pax_global_header00006660000000000000000000000064151143350540014513gustar00rootroot0000000000000052 comment=332807098b528e40e5fca255bf0828eae29f42df msgp-1.6.1/000077500000000000000000000000001511433505400124665ustar00rootroot00000000000000msgp-1.6.1/.github/000077500000000000000000000000001511433505400140265ustar00rootroot00000000000000msgp-1.6.1/.github/workflows/000077500000000000000000000000001511433505400160635ustar00rootroot00000000000000msgp-1.6.1/.github/workflows/test.yml000066400000000000000000000011221511433505400175610ustar00rootroot00000000000000name: test concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true on: workflow_dispatch: push: branches: - 'master' - 'main' tags: - 'v*' pull_request: permissions: contents: read jobs: test: strategy: matrix: go-version: [1.24.x, 1.25.x] os: [ubuntu-latest] runs-on: ${{ matrix.os }} timeout-minutes: 10 steps: - uses: actions/setup-go@v5 with: go-version: ${{ matrix.go-version }} - uses: actions/checkout@v4 - name: test run: make ci msgp-1.6.1/.github/workflows/validate.yml000066400000000000000000000014221511433505400203760ustar00rootroot00000000000000name: validate concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true on: workflow_dispatch: push: branches: - 'master' - 'main' tags: - 'v*' pull_request: permissions: contents: read jobs: linters: strategy: matrix: go-version: [1.25.x] os: [ubuntu-latest] runs-on: ${{ matrix.os }} timeout-minutes: 10 steps: - uses: actions/setup-go@v5 with: go-version: ${{ matrix.go-version }} - uses: actions/checkout@v4 - name: prepare generated code run: make prepare - name: lint uses: golangci/golangci-lint-action@v8 with: version: v2.5.0 args: --print-resources-usage --timeout=10m --verbose msgp-1.6.1/.gitignore000066400000000000000000000003421511433505400144550ustar00rootroot00000000000000_generated/generated.go _generated/generated_test.go _generated/*_gen.go _generated/*_gen_test.go _generated/embeddedStruct/*_gen.go _generated/embeddedStruct/*_gen_test.go msgp/defgen_test.go msgp/cover.out *~ *.coverprofile msgp-1.6.1/.golangci.yml000066400000000000000000000010421511433505400150470ustar00rootroot00000000000000version: "2" linters: enable: - unconvert disable: - errcheck settings: staticcheck: checks: - all - -SA1019 exclusions: generated: lax presets: - comments - common-false-positives - legacy - std-error-handling paths: - third_party$ - builtin$ - examples$ rules: - path: (.+)\.go$ text: JsonNumber should be JSONNumber formatters: exclusions: generated: lax paths: - third_party$ - builtin$ - examples$ msgp-1.6.1/LICENSE000066400000000000000000000021711511433505400134740ustar00rootroot00000000000000Copyright (c) 2014 Philip Hofer Portions Copyright (c) 2009 The Go Authors (license at http://golang.org) where indicated Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.msgp-1.6.1/Makefile000066400000000000000000000023771511433505400141370ustar00rootroot00000000000000 # NOTE: This Makefile is only necessary if you # plan on developing the msgp tool and library. # Installation can still be performed with a # normal `go install`. # generated integration test files GGEN = ./_generated/generated.go ./_generated/generated_test.go # generated unit test files MGEN = ./msgp/defgen_test.go SHELL := /bin/bash BIN = $(GOBIN)/msgp .PHONY: clean wipe install get-deps bench all ci prepare $(BIN): */*.go @go install ./... install: $(BIN) $(GGEN): ./_generated/def.go go generate ./_generated $(MGEN): ./msgp/defs_test.go go generate ./msgp test: all go test ./... ./_generated bench: all go test -bench ./... clean: $(RM) $(GGEN) $(MGEN) wipe: clean $(RM) $(BIN) get-deps: go get -d -t ./... all: install $(GGEN) $(MGEN) # Prepare generated code to be used for linting and testing in CI prepare: go install . go generate ./msgp go generate ./_generated # CI enters here ci: prepare arch if [ `arch` == 'x86_64' ]; then \ sudo apt-get -y -q update; \ sudo apt-get -y -q install build-essential; \ wget -q https://github.com/tinygo-org/tinygo/releases/download/v0.39.0/tinygo_0.39.0_amd64.deb; \ sudo dpkg -i tinygo_0.39.0_amd64.deb; \ export PATH=$$PATH:/usr/local/tinygo/bin; \ fi go test -v ./... ./_generated msgp-1.6.1/README.md000066400000000000000000000135561511433505400137570ustar00rootroot00000000000000MessagePack Code Generator ======= [![Go Reference](https://pkg.go.dev/badge/github.com/tinylib/msgp.svg)](https://pkg.go.dev/github.com/tinylib/msgp) [![test](https://github.com/tinylib/msgp/actions/workflows/test.yml/badge.svg)](https://github.com/tinylib/msgp/actions/workflows/test.yml) [![validate](https://github.com/tinylib/msgp/actions/workflows/validate.yml/badge.svg)](https://github.com/tinylib/msgp/actions/workflows/validate.yml) This is a code generation tool and serialization library for [MessagePack](http://msgpack.org). You can read more about MessagePack [in the wiki](http://github.com/tinylib/msgp/wiki), or at [msgpack.org](http://msgpack.org). ### Why? - Use Go as your schema language - Performance - [JSON interop](https://pkg.go.dev/github.com/tinylib/msgp/msgp#CopyToJSON) - [User-defined extensions](http://github.com/tinylib/msgp/wiki/Using-Extensions) - Type safety - Encoding flexibility ### Quickstart First install the `msgp` generator command. Using Go this is done with `go install github.com/tinylib/msgp@latest` In a source file, include the following directive: ```go //go:generate msgp ``` The `msgp` command will generate serialization methods for all exported type declarations in the file. You can [read more about the code generation options here](http://github.com/tinylib/msgp/wiki/Using-the-Code-Generator). ### Use Field names can be set in much the same way as the `encoding/json` package. For example: ```go type Person struct { Name string `msg:"name"` Address string `msg:"address"` Age int `msg:"age"` Hidden string `msg:"-"` // this field is ignored unexported bool // this field is also ignored } ``` By default, the code generator will satisfy `msgp.Sizer`, `msgp.Encodable`, `msgp.Decodable`, `msgp.Marshaler`, and `msgp.Unmarshaler`. Carefully-designed applications can use these methods to do marshalling/unmarshalling with zero heap allocations. While `msgp.Marshaler` and `msgp.Unmarshaler` are quite similar to the standard library's `json.Marshaler` and `json.Unmarshaler`, `msgp.Encodable` and `msgp.Decodable` are useful for stream serialization. (`*msgp.Writer` and `*msgp.Reader` are essentially protocol-aware versions of `*bufio.Writer` and `*bufio.Reader`, respectively.) An important thing to note is that msgp operates on *individual files*. This means if your structs include types defined in other files, these must be processed as well. ### Features - Extremely fast generated code - Test and benchmark generation - JSON interoperability (see `msgp.CopyToJSON() and msgp.UnmarshalAsJSON()`) - Support for complex type declarations - Native support for Go's `time.Time`, `complex64`, and `complex128` types - Generation of both `[]byte`-oriented and `io.Reader/io.Writer`-oriented methods - Support for arbitrary type system extensions - [Preprocessor directives](http://github.com/tinylib/msgp/wiki/Preprocessor-Directives) - File-based dependency model means fast codegen regardless of source tree size. Consider the following: ```go const Eight = 8 type MyInt int type Data []byte type Struct struct { Which map[string]*MyInt `msg:"which"` Other Data `msg:"other"` Nums [Eight]float64 `msg:"nums"` } ``` As long as the declarations of `MyInt` and `Data` are in the same file as `Struct`, the parser will determine that the type information for `MyInt` and `Data` can be passed into the definition of `Struct` before its methods are generated. #### Extensions MessagePack supports defining your own types through "extensions," which are just a tuple of the data "type" (`int8`) and the raw binary. You [can see a worked example in the wiki.](http://github.com/tinylib/msgp/wiki/Using-Extensions) ### Status Mostly stable, in that no breaking changes have been made to the `/msgp` library in more than a year. Newer versions of the code may generate different code than older versions for performance reasons. I (@philhofer) am aware of a number of stability-critical commercial applications that use this code with good results. But, caveat emptor. You can read more about how `msgp` maps MessagePack types onto Go types [in the wiki](http://github.com/tinylib/msgp/wiki). Here some of the known limitations/restrictions: - Identifiers from outside the processed source file are assumed (optimistically) to satisfy the generator's interfaces. If this isn't the case, your code will fail to compile. - Like most serializers, `chan` and `func` fields are ignored, as well as non-exported fields. - Encoding of `interface{}` is limited to built-ins or types that have explicit encoding methods. - _Maps must have `string` keys._ This is intentional (as it preserves JSON interop.) Although non-string map keys are not forbidden by the MessagePack standard, many serializers impose this restriction. (It also means *any* well-formed `struct` can be de-serialized into a `map[string]interface{}`.) The only exception to this rule is that the deserializers will allow you to read map keys encoded as `bin` types, due to the fact that some legacy encodings permitted this. (However, those values will still be cast to Go `string`s, and they will be converted to `str` types when re-encoded. It is the responsibility of the user to ensure that map keys are UTF-8 safe in this case.) The same rules hold true for JSON translation. If the output compiles, then there's a pretty good chance things are fine. (Plus, we generate tests for you.) *Please, please, please* file an issue if you think the generator is writing broken code. ### Performance If you like benchmarks, see [here](http://bravenewgeek.com/so-you-wanna-go-fast/) and [here](https://github.com/alecthomas/go_serialization_benchmarks). As one might expect, the generated methods that deal with `[]byte` are faster for small objects, but the `io.Reader/Writer` methods are generally more memory-efficient (and, at some point, faster) for large (> 2KB) objects. msgp-1.6.1/_generated/000077500000000000000000000000001511433505400145635ustar00rootroot00000000000000msgp-1.6.1/_generated/allownil.go000066400000000000000000000202431511433505400167340ustar00rootroot00000000000000package _generated import "time" //go:generate msgp type AllowNil0 struct { ABool bool `msg:"abool,allownil"` AInt int `msg:"aint,allownil"` AInt8 int8 `msg:"aint8,allownil"` AInt16 int16 `msg:"aint16,allownil"` AInt32 int32 `msg:"aint32,allownil"` AInt64 int64 `msg:"aint64,allownil"` AUint uint `msg:"auint,allownil"` AUint8 uint8 `msg:"auint8,allownil"` AUint16 uint16 `msg:"auint16,allownil"` AUint32 uint32 `msg:"auint32,allownil"` AUint64 uint64 `msg:"auint64,allownil"` AFloat32 float32 `msg:"afloat32,allownil"` AFloat64 float64 `msg:"afloat64,allownil"` AComplex64 complex64 `msg:"acomplex64,allownil"` AComplex128 complex128 `msg:"acomplex128,allownil"` ANamedBool bool `msg:"anamedbool,allownil"` ANamedInt int `msg:"anamedint,allownil"` ANamedFloat64 float64 `msg:"anamedfloat64,allownil"` AMapStrStr map[string]string `msg:"amapstrstr,allownil"` APtrNamedStr *NamedString `msg:"aptrnamedstr,allownil"` AString string `msg:"astring,allownil"` ANamedString string `msg:"anamedstring,allownil"` AByteSlice []byte `msg:"abyteslice,allownil"` ASliceString []string `msg:"aslicestring,allownil"` ASliceNamedString []NamedString `msg:"aslicenamedstring,allownil"` ANamedStruct NamedStructAN `msg:"anamedstruct,allownil"` APtrNamedStruct *NamedStructAN `msg:"aptrnamedstruct,allownil"` AUnnamedStruct struct { A string `msg:"a,allownil"` } `msg:"aunnamedstruct,allownil"` // allownil not supported on unnamed struct EmbeddableStructAN `msg:",flatten,allownil"` // embed flat EmbeddableStruct2AN `msg:"embeddablestruct2,allownil"` // embed non-flat AArrayInt [5]int `msg:"aarrayint,allownil"` // not supported ATime time.Time `msg:"atime,allownil"` } type AllowNil1 struct { ABool []bool `msg:"abool,allownil"` AInt []int `msg:"aint,allownil"` AInt8 []int8 `msg:"aint8,allownil"` AInt16 []int16 `msg:"aint16,allownil"` AInt32 []int32 `msg:"aint32,allownil"` AInt64 []int64 `msg:"aint64,allownil"` AUint []uint `msg:"auint,allownil"` AUint8 []uint8 `msg:"auint8,allownil"` AUint16 []uint16 `msg:"auint16,allownil"` AUint32 []uint32 `msg:"auint32,allownil"` AUint64 []uint64 `msg:"auint64,allownil"` AFloat32 []float32 `msg:"afloat32,allownil"` AFloat64 []float64 `msg:"afloat64,allownil"` AComplex64 []complex64 `msg:"acomplex64,allownil"` AComplex128 []complex128 `msg:"acomplex128,allownil"` ANamedBool []bool `msg:"anamedbool,allownil"` ANamedInt []int `msg:"anamedint,allownil"` ANamedFloat64 []float64 `msg:"anamedfloat64,allownil"` AMapStrStr map[string]string `msg:"amapstrstr,allownil"` APtrNamedStr *NamedString `msg:"aptrnamedstr,allownil"` AString []string `msg:"astring,allownil"` ANamedString []string `msg:"anamedstring,allownil"` AByteSlice []byte `msg:"abyteslice,allownil"` ASliceString []string `msg:"aslicestring,allownil"` ASliceNamedString []NamedString `msg:"aslicenamedstring,allownil"` ANamedStruct NamedStructAN `msg:"anamedstruct,allownil"` APtrNamedStruct *NamedStructAN `msg:"aptrnamedstruct,allownil"` AUnnamedStruct struct { A []string `msg:"a,allownil"` } `msg:"aunnamedstruct,allownil"` *EmbeddableStructAN `msg:",flatten,allownil"` // embed flat *EmbeddableStruct2AN `msg:"embeddablestruct2,allownil"` // embed non-flat AArrayInt [5]int `msg:"aarrayint,allownil"` // not supported ATime *time.Time `msg:"atime,allownil"` } type EmbeddableStructAN struct { SomeEmbed []string `msg:"someembed,allownil"` } type EmbeddableStruct2AN struct { SomeEmbed2 []string `msg:"someembed2,allownil"` } type NamedStructAN struct { A []string `msg:"a,allownil"` B []string `msg:"b,allownil"` } type AllowNilHalfFull struct { Field00 []string `msg:"field00,allownil"` Field01 []string `msg:"field01"` Field02 []string `msg:"field02,allownil"` Field03 []string `msg:"field03"` } type AllowNilLotsOFields struct { Field00 []string `msg:"field00,allownil"` Field01 []string `msg:"field01,allownil"` Field02 []string `msg:"field02,allownil"` Field03 []string `msg:"field03,allownil"` Field04 []string `msg:"field04,allownil"` Field05 []string `msg:"field05,allownil"` Field06 []string `msg:"field06,allownil"` Field07 []string `msg:"field07,allownil"` Field08 []string `msg:"field08,allownil"` Field09 []string `msg:"field09,allownil"` Field10 []string `msg:"field10,allownil"` Field11 []string `msg:"field11,allownil"` Field12 []string `msg:"field12,allownil"` Field13 []string `msg:"field13,allownil"` Field14 []string `msg:"field14,allownil"` Field15 []string `msg:"field15,allownil"` Field16 []string `msg:"field16,allownil"` Field17 []string `msg:"field17,allownil"` Field18 []string `msg:"field18,allownil"` Field19 []string `msg:"field19,allownil"` Field20 []string `msg:"field20,allownil"` Field21 []string `msg:"field21,allownil"` Field22 []string `msg:"field22,allownil"` Field23 []string `msg:"field23,allownil"` Field24 []string `msg:"field24,allownil"` Field25 []string `msg:"field25,allownil"` Field26 []string `msg:"field26,allownil"` Field27 []string `msg:"field27,allownil"` Field28 []string `msg:"field28,allownil"` Field29 []string `msg:"field29,allownil"` Field30 []string `msg:"field30,allownil"` Field31 []string `msg:"field31,allownil"` Field32 []string `msg:"field32,allownil"` Field33 []string `msg:"field33,allownil"` Field34 []string `msg:"field34,allownil"` Field35 []string `msg:"field35,allownil"` Field36 []string `msg:"field36,allownil"` Field37 []string `msg:"field37,allownil"` Field38 []string `msg:"field38,allownil"` Field39 []string `msg:"field39,allownil"` Field40 []string `msg:"field40,allownil"` Field41 []string `msg:"field41,allownil"` Field42 []string `msg:"field42,allownil"` Field43 []string `msg:"field43,allownil"` Field44 []string `msg:"field44,allownil"` Field45 []string `msg:"field45,allownil"` Field46 []string `msg:"field46,allownil"` Field47 []string `msg:"field47,allownil"` Field48 []string `msg:"field48,allownil"` Field49 []string `msg:"field49,allownil"` Field50 []string `msg:"field50,allownil"` Field51 []string `msg:"field51,allownil"` Field52 []string `msg:"field52,allownil"` Field53 []string `msg:"field53,allownil"` Field54 []string `msg:"field54,allownil"` Field55 []string `msg:"field55,allownil"` Field56 []string `msg:"field56,allownil"` Field57 []string `msg:"field57,allownil"` Field58 []string `msg:"field58,allownil"` Field59 []string `msg:"field59,allownil"` Field60 []string `msg:"field60,allownil"` Field61 []string `msg:"field61,allownil"` Field62 []string `msg:"field62,allownil"` Field63 []string `msg:"field63,allownil"` Field64 []string `msg:"field64,allownil"` Field65 []string `msg:"field65,allownil"` Field66 []string `msg:"field66,allownil"` Field67 []string `msg:"field67,allownil"` Field68 []string `msg:"field68,allownil"` Field69 []string `msg:"field69,allownil"` } type AllowNil10 struct { Field00 []string `msg:"field00,allownil"` Field01 []string `msg:"field01,allownil"` Field02 []string `msg:"field02,allownil"` Field03 []string `msg:"field03,allownil"` Field04 []string `msg:"field04,allownil"` Field05 []string `msg:"field05,allownil"` Field06 []string `msg:"field06,allownil"` Field07 []string `msg:"field07,allownil"` Field08 []string `msg:"field08,allownil"` Field09 []string `msg:"field09,allownil"` } type NotAllowNil10 struct { Field00 []string `msg:"field00"` Field01 []string `msg:"field01"` Field02 []string `msg:"field02"` Field03 []string `msg:"field03"` Field04 []string `msg:"field04"` Field05 []string `msg:"field05"` Field06 []string `msg:"field06"` Field07 []string `msg:"field07"` Field08 []string `msg:"field08"` Field09 []string `msg:"field09"` } type AllowNilOmitEmpty struct { Field00 []string `msg:"field00,allownil,omitempty"` Field01 []string `msg:"field01,allownil"` } type AllowNilOmitEmpty2 struct { Field00 []string `msg:"field00,allownil,omitempty"` Field01 []string `msg:"field01,allownil,omitempty"` } // Primitive types cannot have allownil for now. type NoAllowNil []byte msgp-1.6.1/_generated/allownil_test.go000066400000000000000000000020131511433505400177660ustar00rootroot00000000000000package _generated import ( "bytes" "reflect" "testing" "github.com/tinylib/msgp/msgp" ) func TestAllownil(t *testing.T) { tt := &NamedStructAN{ A: []string{}, B: nil, } var buf bytes.Buffer err := msgp.Encode(&buf, tt) if err != nil { t.Fatal(err) } in := buf.Bytes() for _, tnew := range []*NamedStructAN{{}, {A: []string{}}, {B: []string{}}} { err = msgp.Decode(bytes.NewBuffer(in), tnew) if err != nil { t.Error(err) } if !reflect.DeepEqual(tt, tnew) { t.Logf("in: %#v", tt) t.Logf("out: %#v", tnew) t.Fatal("objects not equal") } } in, err = tt.MarshalMsg(nil) if err != nil { t.Fatal(err) } for _, tanother := range []*NamedStructAN{{}, {A: []string{}}, {B: []string{}}} { var left []byte left, err = tanother.UnmarshalMsg(in) if err != nil { t.Error(err) } if len(left) > 0 { t.Errorf("%d bytes left", len(left)) } if !reflect.DeepEqual(tt, tanother) { t.Logf("in: %#v", tt) t.Logf("out: %#v", tanother) t.Fatal("objects not equal") } } } msgp-1.6.1/_generated/atomic.go000066400000000000000000000016121511433505400163660ustar00rootroot00000000000000package _generated import "sync/atomic" //go:generate msgp //msgp:clearomitted type AtomicTest struct { A atomic.Int64 B atomic.Uint64 C atomic.Int32 D atomic.Uint32 E atomic.Bool Omitted struct { A atomic.Int64 `msg:",omitempty"` B atomic.Uint64 `msg:",omitempty"` C atomic.Int32 `msg:",omitempty"` D atomic.Uint32 `msg:",omitempty"` E atomic.Bool `msg:",omitempty"` } Ptr struct { A *atomic.Int64 B *atomic.Uint64 C *atomic.Int32 D *atomic.Uint32 E *atomic.Bool Omitted struct { A *atomic.Int64 `msg:",omitempty"` B *atomic.Uint64 `msg:",omitempty"` C *atomic.Int32 `msg:",omitempty"` D *atomic.Uint32 `msg:",omitempty"` E *atomic.Bool `msg:",omitempty"` } } F []atomic.Int32 G []*atomic.Int32 // We use pointers, as values don't make sense for maps. H map[string]*atomic.Int32 } msgp-1.6.1/_generated/atomic_test.go000066400000000000000000000174301511433505400174320ustar00rootroot00000000000000package _generated import ( "bytes" "testing" "sync/atomic" "github.com/tinylib/msgp/msgp" ) // Helper: compare two AtomicTest values deeply. func equalAtomicTest(t *testing.T, a, b *AtomicTest) { t.Helper() // Top-level atomics if a.A.Load() != b.A.Load() { t.Fatalf("A mismatch: %d != %d", a.A.Load(), b.A.Load()) } if a.B.Load() != b.B.Load() { t.Fatalf("B mismatch: %d != %d", a.B.Load(), b.B.Load()) } if a.C.Load() != b.C.Load() { t.Fatalf("C mismatch: %d != %d", a.C.Load(), b.C.Load()) } if a.D.Load() != b.D.Load() { t.Fatalf("D mismatch: %d != %d", a.D.Load(), b.D.Load()) } if a.E.Load() != b.E.Load() { t.Fatalf("E mismatch: %t != %t", a.E.Load(), b.E.Load()) } // Omitted (non-pointer) atomics if a.Omitted.A.Load() != b.Omitted.A.Load() { t.Fatalf("Omitted.A mismatch: %d != %d", a.Omitted.A.Load(), b.Omitted.A.Load()) } if a.Omitted.B.Load() != b.Omitted.B.Load() { t.Fatalf("Omitted.B mismatch: %d != %d", a.Omitted.B.Load(), b.Omitted.B.Load()) } if a.Omitted.C.Load() != b.Omitted.C.Load() { t.Fatalf("Omitted.C mismatch: %d != %d", a.Omitted.C.Load(), b.Omitted.C.Load()) } if a.Omitted.D.Load() != b.Omitted.D.Load() { t.Fatalf("Omitted.D mismatch: %d != %d", a.Omitted.D.Load(), b.Omitted.D.Load()) } if a.Omitted.E.Load() != b.Omitted.E.Load() { t.Fatalf("Omitted.E mismatch: %t != %t", a.Omitted.E.Load(), b.Omitted.E.Load()) } // Pointer section switch { case (a.Ptr.A == nil) != (b.Ptr.A == nil): t.Fatalf("Ptr.A nil mismatch: %v vs %v", a.Ptr.A == nil, b.Ptr.A == nil) case a.Ptr.A != nil && a.Ptr.A.Load() != b.Ptr.A.Load(): t.Fatalf("Ptr.A mismatch: %d != %d", a.Ptr.A.Load(), b.Ptr.A.Load()) } switch { case (a.Ptr.B == nil) != (b.Ptr.B == nil): t.Fatalf("Ptr.B nil mismatch: %v vs %v", a.Ptr.B == nil, b.Ptr.B == nil) case a.Ptr.B != nil && a.Ptr.B.Load() != b.Ptr.B.Load(): t.Fatalf("Ptr.B mismatch: %d != %d", a.Ptr.B.Load(), b.Ptr.B.Load()) } switch { case (a.Ptr.C == nil) != (b.Ptr.C == nil): t.Fatalf("Ptr.C nil mismatch: %v vs %v", a.Ptr.C == nil, b.Ptr.C == nil) case a.Ptr.C != nil && a.Ptr.C.Load() != b.Ptr.C.Load(): t.Fatalf("Ptr.C mismatch: %d != %d", a.Ptr.C.Load(), b.Ptr.C.Load()) } switch { case (a.Ptr.D == nil) != (b.Ptr.D == nil): t.Fatalf("Ptr.D nil mismatch: %v vs %v", a.Ptr.D == nil, b.Ptr.D == nil) case a.Ptr.D != nil && a.Ptr.D.Load() != b.Ptr.D.Load(): t.Fatalf("Ptr.D mismatch: %d != %d", a.Ptr.D.Load(), b.Ptr.D.Load()) } switch { case (a.Ptr.E == nil) != (b.Ptr.E == nil): t.Fatalf("Ptr.E nil mismatch: %v vs %v", a.Ptr.E == nil, b.Ptr.E == nil) case a.Ptr.E != nil && a.Ptr.E.Load() != b.Ptr.E.Load(): t.Fatalf("Ptr.E mismatch: %t != %t", a.Ptr.E.Load(), b.Ptr.E.Load()) } // Ptr.Omitted pointers switch { case (a.Ptr.Omitted.A == nil) != (b.Ptr.Omitted.A == nil): t.Fatalf("Ptr.Omitted.A nil mismatch: %v vs %v", a.Ptr.Omitted.A == nil, b.Ptr.Omitted.A == nil) case a.Ptr.Omitted.A != nil && a.Ptr.Omitted.A.Load() != b.Ptr.Omitted.A.Load(): t.Fatalf("Ptr.Omitted.A mismatch: %d != %d", a.Ptr.Omitted.A.Load(), b.Ptr.Omitted.A.Load()) } switch { case (a.Ptr.Omitted.B == nil) != (b.Ptr.Omitted.B == nil): t.Fatalf("Ptr.Omitted.B nil mismatch: %v vs %v", a.Ptr.Omitted.B == nil, b.Ptr.Omitted.B == nil) case a.Ptr.Omitted.B != nil && a.Ptr.Omitted.B.Load() != b.Ptr.Omitted.B.Load(): t.Fatalf("Ptr.Omitted.B mismatch: %d != %d", a.Ptr.Omitted.B.Load(), b.Ptr.Omitted.B.Load()) } switch { case (a.Ptr.Omitted.C == nil) != (b.Ptr.Omitted.C == nil): t.Fatalf("Ptr.Omitted.C nil mismatch: %v vs %v", a.Ptr.Omitted.C == nil, b.Ptr.Omitted.C == nil) case a.Ptr.Omitted.C != nil && a.Ptr.Omitted.C.Load() != b.Ptr.Omitted.C.Load(): t.Fatalf("Ptr.Omitted.C mismatch: %d != %d", a.Ptr.Omitted.C.Load(), b.Ptr.Omitted.C.Load()) } switch { case (a.Ptr.Omitted.D == nil) != (b.Ptr.Omitted.D == nil): t.Fatalf("Ptr.Omitted.D nil mismatch: %v vs %v", a.Ptr.Omitted.D == nil, b.Ptr.Omitted.D == nil) case a.Ptr.Omitted.D != nil && a.Ptr.Omitted.D.Load() != b.Ptr.Omitted.D.Load(): t.Fatalf("Ptr.Omitted.D mismatch: %d != %d", a.Ptr.Omitted.D.Load(), b.Ptr.Omitted.D.Load()) } switch { case (a.Ptr.Omitted.E == nil) != (b.Ptr.Omitted.E == nil): t.Fatalf("Ptr.Omitted.E nil mismatch: %v vs %v", a.Ptr.Omitted.E == nil, b.Ptr.Omitted.E == nil) case a.Ptr.Omitted.E != nil && a.Ptr.Omitted.E.Load() != b.Ptr.Omitted.E.Load(): t.Fatalf("Ptr.Omitted.E mismatch: %t != %t", a.Ptr.Omitted.E.Load(), b.Ptr.Omitted.E.Load()) } // F slice if len(a.F) != len(b.F) { t.Fatalf("F length mismatch: %d != %d", len(a.F), len(b.F)) } for i := range a.F { if a.F[i].Load() != b.F[i].Load() { t.Fatalf("F[%d] mismatch: %d != %d", i, a.F[i].Load(), b.F[i].Load()) } } // G slice of pointers if len(a.G) != len(b.G) { t.Fatalf("G length mismatch: %d != %d", len(a.G), len(b.G)) } for i := range a.G { if (a.G[i] == nil) != (b.G[i] == nil) { t.Fatalf("G[%d] nil mismatch: %v vs %v", i, a.G[i] == nil, b.G[i] == nil) } if a.G[i] != nil && a.G[i].Load() != b.G[i].Load() { t.Fatalf("G[%d] mismatch: %d != %d", i, a.G[i].Load(), b.G[i].Load()) } } // H map[string]*atomic.Int32 if len(a.H) != len(b.H) { t.Fatalf("H length mismatch: %d != %d", len(a.H), len(b.H)) } for k, va := range a.H { vb, ok := b.H[k] if !ok { t.Fatalf("H missing key %q in b", k) } if (va == nil) != (vb == nil) { t.Fatalf("H[%q] nil mismatch: %v vs %v", k, va == nil, vb == nil) } if va != nil && va.Load() != vb.Load() { t.Fatalf("H[%q] mismatch: %d != %d", k, va.Load(), vb.Load()) } } } // Build a populated AtomicTest for roundtrip testing. func makeAtomicTestSample() *AtomicTest { var at AtomicTest // Top-level at.A.Store(-123) at.B.Store(456) at.C.Store(-789) at.D.Store(1011) at.E.Store(true) // Omitted (present even if zero, but we'll set some non-zero) at.Omitted.A.Store(1) at.Omitted.B.Store(2) // leave C zero to exercise omitempty + clearing path at.Omitted.D.Store(4) at.Omitted.E.Store(false) // explicit false // Ptr section at.Ptr.A = new(atomic.Int64) at.Ptr.A.Store(-77) at.Ptr.B = new(atomic.Uint64) at.Ptr.B.Store(88) // leave C nil to exercise pointer omitempty at.Ptr.D = new(atomic.Uint32) at.Ptr.D.Store(99) at.Ptr.E = new(atomic.Bool) at.Ptr.E.Store(true) // Ptr.Omitted at.Ptr.Omitted.A = new(atomic.Int64) at.Ptr.Omitted.A.Store(5) // leave B nil at.Ptr.Omitted.C = new(atomic.Int32) at.Ptr.Omitted.C.Store(-6) // leave D nil at.Ptr.Omitted.E = new(atomic.Bool) at.Ptr.Omitted.E.Store(false) // F slice (values) at.F = make([]atomic.Int32, 3) at.F[0].Store(10) at.F[1].Store(-20) at.F[2].Store(30) // G slice (pointers) at.G = make([]*atomic.Int32, 3) at.G[0] = new(atomic.Int32) at.G[0].Store(100) // leave G[1] nil at.G[2] = new(atomic.Int32) at.G[2].Store(-300) // H map at.H = make(map[string]*atomic.Int32) v1 := new(atomic.Int32) v1.Store(7) at.H["x"] = v1 // include a nil pointer in the map as well at.H["nil"] = nil return &at } func TestAtomicTest_Roundtrip_EncodeDecode(t *testing.T) { orig := makeAtomicTestSample() var buf bytes.Buffer w := msgp.NewWriter(&buf) if err := orig.EncodeMsg(w); err != nil { t.Fatalf("EncodeMsg failed: %v", err) } if err := w.Flush(); err != nil { t.Fatalf("flush failed: %v", err) } r := msgp.NewReader(bytes.NewReader(buf.Bytes())) var out AtomicTest if err := out.DecodeMsg(r); err != nil { t.Fatalf("DecodeMsg failed: %v", err) } equalAtomicTest(t, orig, &out) } func TestAtomicTest_Roundtrip_MarshalUnmarshal(t *testing.T) { orig := makeAtomicTestSample() bts, err := orig.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var out AtomicTest left, err := out.UnmarshalMsg(bts) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(left) != 0 { t.Fatalf("leftover bytes after UnmarshalMsg: %d", len(left)) } equalAtomicTest(t, orig, &out) } msgp-1.6.1/_generated/binary_marshaler.go000066400000000000000000000173121511433505400204400ustar00rootroot00000000000000package _generated import ( "encoding" "fmt" ) //go:generate msgp -v // BinaryTestType implements encoding.BinaryMarshaler and encoding.BinaryUnmarshaler type BinaryTestType struct { Value string } func (t *BinaryTestType) MarshalBinary() ([]byte, error) { return []byte(t.Value), nil } func (t *BinaryTestType) UnmarshalBinary(data []byte) error { t.Value = string(data) return nil } // Verify it implements the interfaces var _ encoding.BinaryMarshaler = (*BinaryTestType)(nil) var _ encoding.BinaryUnmarshaler = (*BinaryTestType)(nil) //msgp:binmarshal BinaryTestType // TextBinTestType implements encoding.TextMarshaler and encoding.TextUnmarshaler type TextBinTestType struct { Value string } func (t *TextBinTestType) MarshalText() ([]byte, error) { return []byte(fmt.Sprintf("text:%s", t.Value)), nil } func (t *TextBinTestType) UnmarshalText(data []byte) error { t.Value = string(data[5:]) // Remove "text:" prefix return nil } var _ encoding.TextMarshaler = (*TextBinTestType)(nil) var _ encoding.TextUnmarshaler = (*TextBinTestType)(nil) //msgp:textmarshal TextBinTestType // TextStringTestType for testing as:string option type TextStringTestType struct { Value string } func (t *TextStringTestType) MarshalText() ([]byte, error) { return []byte(fmt.Sprintf("stringtext:%s", t.Value)), nil } func (t *TextStringTestType) UnmarshalText(data []byte) error { t.Value = string(data[11:]) // Remove "stringtext:" prefix return nil } var _ encoding.TextMarshaler = (*TextStringTestType)(nil) var _ encoding.TextUnmarshaler = (*TextStringTestType)(nil) //msgp:textmarshal as:string TextStringTestType // TestStruct contains various combinations of marshaler types type TestStruct struct { // Direct values BinaryValue BinaryTestType `msg:"bin_val"` TextBinValue TextBinTestType `msg:"text_bin_val"` TextStringValue TextStringTestType `msg:"text_str_val"` // Pointers BinaryPtr *BinaryTestType `msg:"bin_ptr"` TextBinPtr *TextBinTestType `msg:"text_bin_ptr,omitempty"` TextStringPtr *TextStringTestType `msg:"text_str_ptr,omitempty"` // Slices BinarySlice []BinaryTestType `msg:"bin_slice"` TextBinSlice []TextBinTestType `msg:"text_bin_slice"` TextStringSlice []TextStringTestType `msg:"text_str_slice"` // Arrays BinaryArray [3]BinaryTestType `msg:"bin_array"` TextBinArray [2]TextBinTestType `msg:"text_bin_array"` TextStringArray [4]TextStringTestType `msg:"text_str_array"` // Maps with marshaler types as values BinaryMap map[string]BinaryTestType `msg:"bin_map"` TextBinMap map[string]TextBinTestType `msg:"text_bin_map"` TextStringMap map[string]TextStringTestType `msg:"text_str_map"` // Nested pointers and slices NestedPtrSlice []*BinaryTestType `msg:"nested_ptr_slice"` SliceOfArrays [][2]TextBinTestType `msg:"slice_of_arrays"` MapOfSlices map[string][]BinaryTestType `msg:"map_of_slices"` } //msgp:binmarshal ErrorTestType // ErrorTestType for testing error conditions type ErrorTestType struct { ShouldError bool } func (e *ErrorTestType) MarshalBinary() ([]byte, error) { if e.ShouldError { return nil, fmt.Errorf("intentional marshal error") } return []byte("ok"), nil } func (e *ErrorTestType) UnmarshalBinary(data []byte) error { if string(data) == "error" { return fmt.Errorf("intentional unmarshal error") } e.ShouldError = false return nil } // Test types for as:string positioning flexibility // TestTextMarshalerStringMiddle for testing as:string in middle of type list type TestTextMarshalerStringMiddle struct { Value string } func (t *TestTextMarshalerStringMiddle) MarshalText() ([]byte, error) { return []byte("middle:" + t.Value), nil } func (t *TestTextMarshalerStringMiddle) UnmarshalText(text []byte) error { t.Value = string(text) return nil } // TestTextMarshalerStringEnd for testing as:string at end of type list type TestTextMarshalerStringEnd struct { Value string } func (t *TestTextMarshalerStringEnd) MarshalText() ([]byte, error) { return []byte("end:" + t.Value), nil } func (t *TestTextMarshalerStringEnd) UnmarshalText(text []byte) error { t.Value = string(text) return nil } // TestTextAppenderStringPos for testing textappend with as:string positioning type TestTextAppenderStringPos struct { Value string } func (t *TestTextAppenderStringPos) AppendText(dst []byte) ([]byte, error) { return append(dst, []byte("append:"+t.Value)...), nil } func (t *TestTextAppenderStringPos) UnmarshalText(text []byte) error { t.Value = string(text) return nil } // BinaryAppenderType implements encoding.BinaryAppender (Go 1.22+) type BinaryAppenderType struct { Value string } func (t *BinaryAppenderType) AppendBinary(dst []byte) ([]byte, error) { return append(dst, []byte("binappend:"+t.Value)...), nil } func (t *BinaryAppenderType) UnmarshalBinary(data []byte) error { t.Value = string(data) return nil } // TextAppenderBinType implements encoding.TextAppender (stored as binary) type TextAppenderBinType struct { Value string } func (t *TextAppenderBinType) AppendText(dst []byte) ([]byte, error) { return append(dst, []byte("textbin:"+t.Value)...), nil } func (t *TextAppenderBinType) UnmarshalText(text []byte) error { t.Value = string(text) return nil } // ErrorBinaryAppenderType for testing error conditions with BinaryAppender type ErrorBinaryAppenderType struct { ShouldError bool Value string } func (e *ErrorBinaryAppenderType) AppendBinary(dst []byte) ([]byte, error) { if e.ShouldError { return nil, fmt.Errorf("intentional append binary error") } return append(dst, []byte("ok")...), nil } func (e *ErrorBinaryAppenderType) UnmarshalBinary(data []byte) error { if string(data) == "error" { return fmt.Errorf("intentional unmarshal binary error") } e.ShouldError = false e.Value = string(data) return nil } // ErrorTextAppenderType for testing error conditions with TextAppender type ErrorTextAppenderType struct { ShouldError bool Value string } func (e *ErrorTextAppenderType) AppendText(dst []byte) ([]byte, error) { if e.ShouldError { return nil, fmt.Errorf("intentional append text error") } return append(dst, []byte("ok")...), nil } func (e *ErrorTextAppenderType) UnmarshalText(text []byte) error { if string(text) == "error" { return fmt.Errorf("intentional unmarshal text error") } e.ShouldError = false e.Value = string(text) return nil } //msgp:binappend BinaryAppenderType ErrorBinaryAppenderType //msgp:textappend TextAppenderBinType ErrorTextAppenderType //msgp:textmarshal TestTextMarshalerStringMiddle as:string TestTextMarshalerStringEnd //msgp:textappend TestTextAppenderStringPos as:string //msgp:binappend BinaryAppenderValue // BinaryAppenderValue implements encoding.BinaryAppender (Go 1.22+) type BinaryAppenderValue struct { Value string `msg:"-"` } func (t BinaryAppenderValue) AppendBinary(dst []byte) ([]byte, error) { return append(dst, []byte("binappend:"+t.Value)...), nil } func (t *BinaryAppenderValue) UnmarshalBinary(data []byte) error { t.Value = string(data) return nil } //msgp:textappend TestAppendTextString as:string type TestAppendTextString struct { Value string `msg:"-"` } func (t TestAppendTextString) AppendText(dst []byte) ([]byte, error) { return append(dst, []byte("append:"+t.Value)...), nil } func (t *TestAppendTextString) UnmarshalText(text []byte) error { t.Value = string(text) return nil } //msgp:textappend TextAppenderBinValue // TextAppenderBinValue implements encoding.TextAppender (stored as binary) type TextAppenderBinValue struct { Value string `msg:"-"` } func (t TextAppenderBinValue) AppendText(dst []byte) ([]byte, error) { return append(dst, []byte("textbin:"+t.Value)...), nil } func (t *TextAppenderBinValue) UnmarshalText(text []byte) error { t.Value = string(text) return nil } msgp-1.6.1/_generated/binary_marshaler_test.go000066400000000000000000000422121511433505400214740ustar00rootroot00000000000000package _generated import ( "bytes" "strings" "testing" "github.com/tinylib/msgp/msgp" ) func TestBinaryMarshalerDirective(t *testing.T) { original := &BinaryTestType{Value: "test_data"} // Test marshal data, err := original.MarshalMsg(nil) if err != nil { t.Fatalf("Marshal failed: %v", err) } // Test unmarshal result := &BinaryTestType{} _, err = result.UnmarshalMsg(data) if err != nil { t.Fatalf("Unmarshal failed: %v", err) } if result.Value != original.Value { t.Errorf("Expected %s, got %s", original.Value, result.Value) } } func TestTextMarshalerBinDirective(t *testing.T) { original := &TextBinTestType{Value: "test_data"} // Test marshal data, err := original.MarshalMsg(nil) if err != nil { t.Fatalf("Marshal failed: %v", err) } // Test unmarshal result := &TextBinTestType{} _, err = result.UnmarshalMsg(data) if err != nil { t.Fatalf("Unmarshal failed: %v", err) } if result.Value != original.Value { t.Errorf("Expected %s, got %s", original.Value, result.Value) } } func TestTextMarshalerStringDirective(t *testing.T) { original := &TextStringTestType{Value: "test_data"} // Test marshal data, err := original.MarshalMsg(nil) if err != nil { t.Fatalf("Marshal failed: %v", err) } // Test unmarshal result := &TextStringTestType{} _, err = result.UnmarshalMsg(data) if err != nil { t.Fatalf("Unmarshal failed: %v", err) } if result.Value != original.Value { t.Errorf("Expected %s, got %s", original.Value, result.Value) } } func TestBinaryMarshalerRoundTrip(t *testing.T) { tests := []string{"", "hello", "world with spaces", "unicode: 测试"} for _, testVal := range tests { original := &BinaryTestType{Value: testVal} // Test marshal/unmarshal buf, err := original.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for %q: %v", testVal, err) } result := &BinaryTestType{} _, err = result.UnmarshalMsg(buf) if err != nil { t.Fatalf("UnmarshalMsg failed for %q: %v", testVal, err) } if result.Value != testVal { t.Errorf("Round trip failed: expected %q, got %q", testVal, result.Value) } } } func TestTextMarshalerSize(t *testing.T) { testType := &TextBinTestType{Value: "test"} // Get the size size := testType.Msgsize() // Marshal and check the actual size matches estimate data, err := testType.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } if len(data) > size { t.Errorf("Msgsize underestimated: estimated %d, actual %d", size, len(data)) } if size > len(data)+100 { // Allow some reasonable overhead t.Errorf("Msgsize too conservative: estimated %d, actual %d", size, len(data)) } } func TestStructWithMarshalerFields(t *testing.T) { // Create a test struct with all field types populated original := &TestStruct{ // Direct values BinaryValue: BinaryTestType{Value: "binary_val"}, TextBinValue: TextBinTestType{Value: "text_bin_val"}, TextStringValue: TextStringTestType{Value: "text_str_val"}, // Pointers BinaryPtr: &BinaryTestType{Value: "binary_ptr"}, TextBinPtr: &TextBinTestType{Value: "text_bin_ptr"}, TextStringPtr: &TextStringTestType{Value: "text_str_ptr"}, // Slices BinarySlice: []BinaryTestType{ {Value: "bin_slice_0"}, {Value: "bin_slice_1"}, }, TextBinSlice: []TextBinTestType{ {Value: "text_bin_slice_0"}, {Value: "text_bin_slice_1"}, }, TextStringSlice: []TextStringTestType{ {Value: "text_str_slice_0"}, {Value: "text_str_slice_1"}, }, // Arrays BinaryArray: [3]BinaryTestType{ {Value: "bin_array_0"}, {Value: "bin_array_1"}, {Value: "bin_array_2"}, }, TextBinArray: [2]TextBinTestType{ {Value: "text_bin_array_0"}, {Value: "text_bin_array_1"}, }, TextStringArray: [4]TextStringTestType{ {Value: "text_str_array_0"}, {Value: "text_str_array_1"}, {Value: "text_str_array_2"}, {Value: "text_str_array_3"}, }, // Maps BinaryMap: map[string]BinaryTestType{ "key1": {Value: "bin_map_val1"}, "key2": {Value: "bin_map_val2"}, }, TextBinMap: map[string]TextBinTestType{ "key1": {Value: "text_bin_map_val1"}, "key2": {Value: "text_bin_map_val2"}, }, TextStringMap: map[string]TextStringTestType{ "key1": {Value: "text_str_map_val1"}, "key2": {Value: "text_str_map_val2"}, }, // Nested types NestedPtrSlice: []*BinaryTestType{ {Value: "nested_ptr_0"}, {Value: "nested_ptr_1"}, }, SliceOfArrays: [][2]TextBinTestType{ {{Value: "slice_arr_0_0"}, {Value: "slice_arr_0_1"}}, {{Value: "slice_arr_1_0"}, {Value: "slice_arr_1_1"}}, }, MapOfSlices: map[string][]BinaryTestType{ "slice1": {{Value: "map_slice_val_0"}, {Value: "map_slice_val_1"}}, "slice2": {{Value: "map_slice_val_2"}}, }, } // Test marshal/unmarshal data, err := original.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } result := &TestStruct{} _, err = result.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } // Verify direct values if result.BinaryValue.Value != original.BinaryValue.Value { t.Errorf("BinaryValue mismatch: expected %s, got %s", original.BinaryValue.Value, result.BinaryValue.Value) } if result.TextBinValue.Value != original.TextBinValue.Value { t.Errorf("TextBinValue mismatch: expected %s, got %s", original.TextBinValue.Value, result.TextBinValue.Value) } if result.TextStringValue.Value != original.TextStringValue.Value { t.Errorf("TextStringValue mismatch: expected %s, got %s", original.TextStringValue.Value, result.TextStringValue.Value) } // Verify pointers if result.BinaryPtr == nil || result.BinaryPtr.Value != original.BinaryPtr.Value { t.Errorf("BinaryPtr mismatch") } if result.TextBinPtr == nil || result.TextBinPtr.Value != original.TextBinPtr.Value { t.Errorf("TextBinPtr mismatch") } if result.TextStringPtr == nil || result.TextStringPtr.Value != original.TextStringPtr.Value { t.Errorf("TextStringPtr mismatch") } // Verify slices if len(result.BinarySlice) != len(original.BinarySlice) { t.Errorf("BinarySlice length mismatch: expected %d, got %d", len(original.BinarySlice), len(result.BinarySlice)) } else { for i := range result.BinarySlice { if result.BinarySlice[i].Value != original.BinarySlice[i].Value { t.Errorf("BinarySlice[%d] mismatch: expected %s, got %s", i, original.BinarySlice[i].Value, result.BinarySlice[i].Value) } } } // Verify arrays for i := range result.BinaryArray { if result.BinaryArray[i].Value != original.BinaryArray[i].Value { t.Errorf("BinaryArray[%d] mismatch: expected %s, got %s", i, original.BinaryArray[i].Value, result.BinaryArray[i].Value) } } // Verify maps if len(result.BinaryMap) != len(original.BinaryMap) { t.Errorf("BinaryMap length mismatch: expected %d, got %d", len(original.BinaryMap), len(result.BinaryMap)) } else { for k, v := range original.BinaryMap { if resultVal, exists := result.BinaryMap[k]; !exists || resultVal.Value != v.Value { t.Errorf("BinaryMap[%s] mismatch: expected %s, got %s", k, v.Value, resultVal.Value) } } } // Verify nested structures if len(result.NestedPtrSlice) != len(original.NestedPtrSlice) { t.Errorf("NestedPtrSlice length mismatch") } else { for i := range result.NestedPtrSlice { if result.NestedPtrSlice[i] == nil || result.NestedPtrSlice[i].Value != original.NestedPtrSlice[i].Value { t.Errorf("NestedPtrSlice[%d] mismatch", i) } } } } func TestStructWithOmitEmptyFields(t *testing.T) { // Test struct with nil pointers (should use omitempty/omitzero) original := &TestStruct{ BinaryValue: BinaryTestType{Value: "present"}, TextBinValue: TextBinTestType{Value: "also_present"}, TextStringValue: TextStringTestType{Value: "string_present"}, // Leave pointers nil BinaryPtr: nil, TextBinPtr: nil, // this has omitempty tag TextStringPtr: nil, // this has omitzero tag // Empty slices and maps BinarySlice: []BinaryTestType{}, BinaryMap: map[string]BinaryTestType{}, } // Test marshal/unmarshal data, err := original.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } result := &TestStruct{} _, err = result.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } // Verify values are preserved and nils are handled correctly if result.BinaryValue.Value != original.BinaryValue.Value { t.Errorf("BinaryValue mismatch") } if result.BinaryPtr != nil { t.Errorf("Expected BinaryPtr to be nil") } if result.TextBinPtr != nil { t.Errorf("Expected TextBinPtr to be nil") } if result.TextStringPtr != nil { t.Errorf("Expected TextStringPtr to be nil") } } func TestStructSizeEstimation(t *testing.T) { testStruct := &TestStruct{ BinaryValue: BinaryTestType{Value: "test"}, BinarySlice: []BinaryTestType{ {Value: "slice1"}, {Value: "slice2"}, }, BinaryMap: map[string]BinaryTestType{ "key": {Value: "value"}, }, } // Get size estimate size := testStruct.Msgsize() // Marshal and verify size estimate data, err := testStruct.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } if len(data) > size { t.Errorf("Msgsize underestimated: estimated %d, actual %d", size, len(data)) } } func TestMarshalerErrorHandling(t *testing.T) { // Test marshaling with marshaler that can fail errorType := &ErrorTestType{ShouldError: true} _, err := errorType.MarshalMsg(nil) if err == nil { t.Error("Expected marshal error but got none") } // Test in struct context testStruct := &TestStruct{ BinaryValue: BinaryTestType{Value: "good"}, } // This should succeed _, err = testStruct.MarshalMsg(nil) if err != nil { t.Errorf("Expected no error but got: %v", err) } } func TestTextMarshalerAsStringPositioning(t *testing.T) { // Test that as:string works when placed in middle of type list middle := &TestTextMarshalerStringMiddle{Value: "test_middle"} // Marshal data, err := middle.MarshalMsg(nil) if err != nil { t.Fatalf("Failed to marshal: %v", err) } // Unmarshal var decoded TestTextMarshalerStringMiddle _, err = decoded.UnmarshalMsg(data) if err != nil { t.Fatalf("Failed to unmarshal: %v", err) } if decoded.Value != "middle:test_middle" { t.Errorf("Expected 'middle:test_middle', got '%s'", decoded.Value) } // Test that as:string works when placed at end of type list end := &TestTextMarshalerStringEnd{Value: "test_end"} // Marshal data, err = end.MarshalMsg(nil) if err != nil { t.Fatalf("Failed to marshal: %v", err) } // Unmarshal var decodedEnd TestTextMarshalerStringEnd _, err = decodedEnd.UnmarshalMsg(data) if err != nil { t.Fatalf("Failed to unmarshal: %v", err) } if decodedEnd.Value != "end:test_end" { t.Errorf("Expected 'end:test_end', got '%s'", decodedEnd.Value) } } func TestTextAppenderAsStringPositioning(t *testing.T) { // Test that as:string works with textappend directive appender := &TestTextAppenderStringPos{Value: "test_append"} // Marshal data, err := appender.MarshalMsg(nil) if err != nil { t.Fatalf("Failed to marshal: %v", err) } // Unmarshal var decoded TestTextAppenderStringPos _, err = decoded.UnmarshalMsg(data) if err != nil { t.Fatalf("Failed to unmarshal: %v", err) } if decoded.Value != "append:test_append" { t.Errorf("Expected 'append:test_append', got '%s'", decoded.Value) } } func TestBinaryAppenderDirective(t *testing.T) { for _, size := range []int{10, 100, 1000, 100000} { // Test BinaryAppender interface appender := &BinaryAppenderType{Value: strings.Repeat("a", size)} // Test round trip data, err := appender.MarshalMsg(nil) if err != nil { t.Fatalf("Failed to marshal: %v", err) } var decoded BinaryAppenderType _, err = decoded.UnmarshalMsg(data) if err != nil { t.Fatalf("Failed to unmarshal: %v", err) } if want := "binappend:" + appender.Value; decoded.Value != want { t.Errorf("Expected '%s', got '%s'", want, decoded.Value) } // Test encode/decode var buf bytes.Buffer writer := msgp.NewWriter(&buf) err = appender.EncodeMsg(writer) if err != nil { t.Fatalf("Failed to encode: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded2 BinaryAppenderType err = decoded2.DecodeMsg(reader) if err != nil { t.Fatalf("Failed to decode: %v", err) } if want := "binappend:" + appender.Value; decoded2.Value != want { t.Errorf("Expected '%s', got '%s'", want, decoded2.Value) } } } func TestTextAppenderBinDirective(t *testing.T) { // Test TextAppender interface (stored as binary) appender := &TextAppenderBinType{Value: "test_text_bin"} // Test round trip data, err := appender.MarshalMsg(nil) if err != nil { t.Fatalf("Failed to marshal: %v", err) } var decoded TextAppenderBinType _, err = decoded.UnmarshalMsg(data) if err != nil { t.Fatalf("Failed to unmarshal: %v", err) } if decoded.Value != "textbin:test_text_bin" { t.Errorf("Expected 'textbin:test_text_bin', got '%s'", decoded.Value) } // Test encode/decode var buf bytes.Buffer writer := msgp.NewWriter(&buf) err = appender.EncodeMsg(writer) if err != nil { t.Fatalf("Failed to encode: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded2 TextAppenderBinType err = decoded2.DecodeMsg(reader) if err != nil { t.Fatalf("Failed to decode: %v", err) } if decoded2.Value != "textbin:test_text_bin" { t.Errorf("Expected 'textbin:test_text_bin', got '%s'", decoded2.Value) } } func TestBinaryAppenderErrorHandling(t *testing.T) { // Test error handling with BinaryAppender errorType := &ErrorBinaryAppenderType{ShouldError: true} _, err := errorType.MarshalMsg(nil) if err == nil { t.Error("Expected marshal error but got none") } // Test successful case successType := &ErrorBinaryAppenderType{ShouldError: false} data, err := successType.MarshalMsg(nil) if err != nil { t.Fatalf("Expected no error but got: %v", err) } var decoded ErrorBinaryAppenderType _, err = decoded.UnmarshalMsg(data) if err != nil { t.Fatalf("Failed to unmarshal: %v", err) } if decoded.Value != "ok" { t.Errorf("Expected 'ok', got '%s'", decoded.Value) } } func TestTextAppenderErrorHandling(t *testing.T) { // Test error handling with TextAppender errorType := &ErrorTextAppenderType{ShouldError: true} _, err := errorType.MarshalMsg(nil) if err == nil { t.Error("Expected marshal error but got none") } // Test successful case successType := &ErrorTextAppenderType{ShouldError: false} data, err := successType.MarshalMsg(nil) if err != nil { t.Fatalf("Expected no error but got: %v", err) } var decoded ErrorTextAppenderType _, err = decoded.UnmarshalMsg(data) if err != nil { t.Fatalf("Failed to unmarshal: %v", err) } if decoded.Value != "ok" { t.Errorf("Expected 'ok', got '%s'", decoded.Value) } } func TestAppenderTypesSizeEstimation(t *testing.T) { // Test that size estimation works for appender types binaryAppender := &BinaryAppenderType{Value: "size_test"} size := binaryAppender.Msgsize() data, err := binaryAppender.MarshalMsg(nil) if err != nil { t.Fatalf("Failed to marshal: %v", err) } if len(data) > size { t.Errorf("Binary appender size underestimated: estimated %d, actual %d", size, len(data)) } textAppender := &TextAppenderBinType{Value: "size_test"} size = textAppender.Msgsize() data, err = textAppender.MarshalMsg(nil) if err != nil { t.Fatalf("Failed to marshal: %v", err) } if len(data) > size { t.Errorf("Text appender size underestimated: estimated %d, actual %d", size, len(data)) } } func TestBinaryAppenderValueRoundTrip(t *testing.T) { tests := []string{"", "hello", "world with spaces", "unicode: 测试"} for _, testVal := range tests { original := BinaryAppenderValue{Value: testVal} buf, err := original.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for %q: %v", testVal, err) } var result BinaryAppenderValue _, err = result.UnmarshalMsg(buf) if err != nil { t.Fatalf("UnmarshalMsg failed for %q: %v", testVal, err) } expected := "binappend:" + testVal if result.Value != expected { t.Errorf("Round trip failed: expected %q, got %q", expected, result.Value) } } } func TestTestAppendTextStringRoundTrip(t *testing.T) { tests := []string{"", "hello", "world with spaces", "unicode: 测试"} for _, testVal := range tests { original := TestAppendTextString{Value: testVal} buf, err := original.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for %q: %v", testVal, err) } var result TestAppendTextString _, err = result.UnmarshalMsg(buf) if err != nil { t.Fatalf("UnmarshalMsg failed for %q: %v", testVal, err) } expected := "append:" + testVal if result.Value != expected { t.Errorf("Round trip failed: expected %q, got %q", expected, result.Value) } } } func TestTextAppenderBinValueRoundTrip(t *testing.T) { tests := []string{"", "hello", "world with spaces", "unicode: 测试"} for _, testVal := range tests { original := TextAppenderBinValue{Value: testVal} buf, err := original.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for %q: %v", testVal, err) } var result TextAppenderBinValue _, err = result.UnmarshalMsg(buf) if err != nil { t.Fatalf("UnmarshalMsg failed for %q: %v", testVal, err) } expected := "textbin:" + testVal if result.Value != expected { t.Errorf("Round trip failed: expected %q, got %q", expected, result.Value) } } } msgp-1.6.1/_generated/clearomitted.go000066400000000000000000000061241511433505400175710ustar00rootroot00000000000000package _generated import ( "encoding/json" "time" ) //go:generate msgp //msgp:clearomitted // check some specific cases for omitzero type ClearOmitted0 struct { AStruct ClearOmittedA `msg:"astruct,omitempty"` // leave this one omitempty BStruct ClearOmittedA `msg:"bstruct,omitzero"` // and compare to this AStructPtr *ClearOmittedA `msg:"astructptr,omitempty"` // a pointer case omitempty BStructPtr *ClearOmittedA `msg:"bstructptr,omitzero"` // a pointer case omitzero AExt OmitZeroExt `msg:"aext,omitzero"` // external type case // more APtrNamedStr *NamedStringCO `msg:"aptrnamedstr,omitzero"` ANamedStruct NamedStructCO `msg:"anamedstruct,omitzero"` APtrNamedStruct *NamedStructCO `msg:"aptrnamedstruct,omitzero"` EmbeddableStructCO `msg:",flatten,omitzero"` // embed flat EmbeddableStructCO2 `msg:"embeddablestruct2,omitzero"` // embed non-flat ATime time.Time `msg:"atime,omitzero"` ASlice []int `msg:"aslice,omitempty"` AMap map[string]int `msg:"amap,omitempty"` ABin []byte `msg:"abin,omitempty"` AInt int `msg:"aint,omitempty"` AString string `msg:"atring,omitempty"` Adur time.Duration `msg:"adur,omitempty"` AJSON json.Number `msg:"ajson,omitempty"` AnAny any `msg:"anany,omitempty"` ClearOmittedTuple ClearOmittedTuple `msg:"ozt"` // the inside of a tuple should ignore both omitempty and omitzero } type ClearOmittedA struct { A string `msg:"a,omitempty"` B NamedStringCO `msg:"b,omitzero"` C NamedStringCO `msg:"c,omitzero"` } func (o *ClearOmittedA) IsZero() bool { if o == nil { return true } return *o == (ClearOmittedA{}) } type NamedStructCO struct { A string `msg:"a,omitempty"` B string `msg:"b,omitempty"` } func (ns *NamedStructCO) IsZero() bool { if ns == nil { return true } return *ns == (NamedStructCO{}) } type NamedStringCO string func (ns *NamedStringCO) IsZero() bool { if ns == nil { return true } return *ns == "" } type EmbeddableStructCO struct { SomeEmbed string `msg:"someembed2,omitempty"` } func (es EmbeddableStructCO) IsZero() bool { return es == (EmbeddableStructCO{}) } type EmbeddableStructCO2 struct { SomeEmbed2 string `msg:"someembed2,omitempty"` } func (es EmbeddableStructCO2) IsZero() bool { return es == (EmbeddableStructCO2{}) } //msgp:tuple ClearOmittedTuple // ClearOmittedTuple is flagged for tuple output, it should ignore all omitempty and omitzero functionality // since it's fundamentally incompatible. type ClearOmittedTuple struct { FieldA string `msg:"fielda,omitempty"` FieldB NamedStringCO `msg:"fieldb,omitzero"` FieldC NamedStringCO `msg:"fieldc,omitzero"` } type ClearOmitted1 struct { T1 ClearOmittedTuple `msg:"t1"` } msgp-1.6.1/_generated/clearomitted_test.go000066400000000000000000000044241511433505400206310ustar00rootroot00000000000000package _generated import ( "bytes" "encoding/json" "reflect" "testing" "time" "github.com/tinylib/msgp/msgp" ) func TestClearOmitted(t *testing.T) { cleared := ClearOmitted0{} encoded, err := cleared.MarshalMsg(nil) if err != nil { t.Fatal(err) } vPtr := NamedStringCO("value") filled := ClearOmitted0{ AStruct: ClearOmittedA{A: "something"}, BStruct: ClearOmittedA{A: "somthing"}, AStructPtr: &ClearOmittedA{A: "something"}, AExt: OmitZeroExt{25}, APtrNamedStr: &vPtr, ANamedStruct: NamedStructCO{A: "value"}, APtrNamedStruct: &NamedStructCO{A: "sdf"}, EmbeddableStructCO: EmbeddableStructCO{"value"}, EmbeddableStructCO2: EmbeddableStructCO2{"value"}, ATime: time.Now(), ASlice: []int{1, 2, 3}, AMap: map[string]int{"1": 1}, ABin: []byte{1, 2, 3}, ClearOmittedTuple: ClearOmittedTuple{FieldA: "value"}, AInt: 42, AString: "value", Adur: time.Second, AJSON: json.Number(`43.0000000000002`), } dst := filled _, err = dst.UnmarshalMsg(encoded) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(dst, cleared) { t.Errorf("\n got=%#v\nwant=%#v", dst, cleared) } // Reset dst = filled err = dst.DecodeMsg(msgp.NewReader(bytes.NewReader(encoded))) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(dst, cleared) { t.Errorf("\n got=%#v\nwant=%#v", dst, cleared) } // Check that fields aren't accidentally zeroing fields. wantJson, err := json.Marshal(filled) if err != nil { t.Fatal(err) } encoded, err = filled.MarshalMsg(nil) if err != nil { t.Fatal(err) } dst = ClearOmitted0{} _, err = dst.UnmarshalMsg(encoded) if err != nil { t.Fatal(err) } got, err := json.Marshal(dst) if err != nil { t.Fatal(err) } if !bytes.Equal(got, wantJson) { t.Errorf("\n got=%#v\nwant=%#v", string(got), string(wantJson)) } // Reset dst = ClearOmitted0{} err = dst.DecodeMsg(msgp.NewReader(bytes.NewReader(encoded))) if err != nil { t.Fatal(err) } got, err = json.Marshal(dst) if err != nil { t.Fatal(err) } if !bytes.Equal(got, wantJson) { t.Errorf("\n got=%#v\nwant=%#v", string(got), string(wantJson)) } t.Log("OK - got", string(got)) } msgp-1.6.1/_generated/compactfloats.go000066400000000000000000000004221511433505400177470ustar00rootroot00000000000000package _generated //go:generate msgp -d "msgp:compactfloats" -d "replace F64 with:float64" -v //msgp:ignore F64 type F64 float64 type Floats struct { A float64 B float32 Slice []float64 Map map[string]float64 F F64 OE float64 `msg:",omitempty"` } msgp-1.6.1/_generated/compactfloats_test.go000066400000000000000000000035661511433505400210220ustar00rootroot00000000000000package _generated import ( "bytes" "reflect" "testing" "github.com/tinylib/msgp/msgp" ) func TestCompactFloats(t *testing.T) { // Constant that can be represented in f32 without loss const f32ok = -1e2 allF32 := Floats{ A: f32ok, B: f32ok, Slice: []float64{f32ok, f32ok}, Map: map[string]float64{"a": f32ok}, F: f32ok, OE: f32ok, } asF32 := float32(f32ok) wantF32 := map[string]any{"A": asF32, "B": asF32, "F": asF32, "Map": map[string]any{"a": asF32}, "OE": asF32, "Slice": []any{asF32, asF32}} enc, err := allF32.MarshalMsg(nil) if err != nil { t.Error(err) } i, _, _ := msgp.ReadIntfBytes(enc) got := i.(map[string]any) if !reflect.DeepEqual(got, wantF32) { t.Errorf("want: %v, got: %v (diff may be types)", wantF32, got) } var buf bytes.Buffer en := msgp.NewWriter(&buf) allF32.EncodeMsg(en) en.Flush() enc = buf.Bytes() i, _, _ = msgp.ReadIntfBytes(enc) got = i.(map[string]any) if !reflect.DeepEqual(got, wantF32) { t.Errorf("want: %v, got: %v (diff may be types)", wantF32, got) } const f64ok = -10e64 allF64 := Floats{ A: f64ok, B: f32ok, Slice: []float64{f64ok, f64ok}, Map: map[string]float64{"a": f64ok}, F: f64ok, OE: f64ok, } asF64 := float64(f64ok) wantF64 := map[string]any{"A": asF64, "B": asF32, "F": asF64, "Map": map[string]any{"a": asF64}, "OE": asF64, "Slice": []any{asF64, asF64}} enc, err = allF64.MarshalMsg(nil) if err != nil { t.Error(err) } i, _, _ = msgp.ReadIntfBytes(enc) got = i.(map[string]any) if !reflect.DeepEqual(got, wantF64) { t.Errorf("want: %v, got: %v (diff may be types)", wantF64, got) } buf.Reset() en = msgp.NewWriter(&buf) allF64.EncodeMsg(en) en.Flush() enc = buf.Bytes() i, _, _ = msgp.ReadIntfBytes(enc) got = i.(map[string]any) if !reflect.DeepEqual(got, wantF64) { t.Errorf("want: %v, got: %v (diff may be types)", wantF64, got) } } msgp-1.6.1/_generated/convert.go000066400000000000000000000032261511433505400165750ustar00rootroot00000000000000package _generated import "errors" //go:generate msgp //msgp:shim ConvertStringVal as:string using:fromConvertStringVal/toConvertStringVal mode:convert //msgp:ignore ConvertStringVal func fromConvertStringVal(v ConvertStringVal) (string, error) { return string(v), nil } func toConvertStringVal(s string) (ConvertStringVal, error) { return ConvertStringVal(s), nil } type ConvertStringVal string type ConvertString struct { String ConvertStringVal } type ConvertStringSlice struct { Strings []ConvertStringVal } type ConvertStringMapValue struct { Strings map[string]ConvertStringVal } //msgp:shim ConvertIntfVal as:interface{} using:fromConvertIntfVal/toConvertIntfVal mode:convert //msgp:ignore ConvertIntfVal func fromConvertIntfVal(v ConvertIntfVal) (interface{}, error) { return v.Test, nil } func toConvertIntfVal(s interface{}) (ConvertIntfVal, error) { return ConvertIntfVal{Test: s.(string)}, nil } type ConvertIntfVal struct { Test string } type ConvertIntf struct { Intf ConvertIntfVal } //msgp:shim ConvertErrVal as:string using:fromConvertErrVal/toConvertErrVal mode:convert //msgp:ignore ConvertErrVal var ( errConvertFrom = errors.New("error: convert from") errConvertTo = errors.New("error: convert to") ) const ( fromFailStr = "fromfail" toFailStr = "tofail" ) func fromConvertErrVal(v ConvertErrVal) (string, error) { s := string(v) if s == fromFailStr { return "", errConvertFrom } return s, nil } func toConvertErrVal(s string) (ConvertErrVal, error) { if s == toFailStr { return ConvertErrVal(""), errConvertTo } return ConvertErrVal(s), nil } type ConvertErrVal string type ConvertErr struct { Err ConvertErrVal } msgp-1.6.1/_generated/convert_test.go000066400000000000000000000024451511433505400176360ustar00rootroot00000000000000package _generated import ( "bytes" "testing" "github.com/tinylib/msgp/msgp" ) func TestConvertFromEncodeError(t *testing.T) { e := ConvertErr{ConvertErrVal(fromFailStr)} var buf bytes.Buffer w := msgp.NewWriter(&buf) err := e.EncodeMsg(w) if msgp.Cause(err) != errConvertFrom { t.Fatalf("expected conversion error, found '%v'", err.Error()) } } func TestConvertToEncodeError(t *testing.T) { var in, out ConvertErr in = ConvertErr{ConvertErrVal(toFailStr)} var buf bytes.Buffer w := msgp.NewWriter(&buf) err := in.EncodeMsg(w) if err != nil { t.FailNow() } w.Flush() r := msgp.NewReader(&buf) err = (&out).DecodeMsg(r) if msgp.Cause(err) != errConvertTo { t.Fatalf("expected conversion error, found %v", err.Error()) } } func TestConvertFromMarshalError(t *testing.T) { e := ConvertErr{ConvertErrVal(fromFailStr)} var b []byte _, err := e.MarshalMsg(b) if msgp.Cause(err) != errConvertFrom { t.Fatalf("expected conversion error, found %v", err.Error()) } } func TestConvertToMarshalError(t *testing.T) { var in, out ConvertErr in = ConvertErr{ConvertErrVal(toFailStr)} b, err := in.MarshalMsg(nil) if err != nil { t.FailNow() } _, err = (&out).UnmarshalMsg(b) if msgp.Cause(err) != errConvertTo { t.Fatalf("expected conversion error, found %v", err.Error()) } } msgp-1.6.1/_generated/custom_tag.go000066400000000000000000000002251511433505400172560ustar00rootroot00000000000000package _generated //go:generate msgp -d "tag mytag" type CustomTag struct { Foo string `mytag:"foo_custom_name"` Bar int `mytag:"bar1234"` } msgp-1.6.1/_generated/custom_tag_test.go000066400000000000000000000033551511433505400203240ustar00rootroot00000000000000package _generated import ( "encoding/json" "fmt" "reflect" "testing" "bytes" "github.com/tinylib/msgp/msgp" ) func TestCustomTag(t *testing.T) { t.Run("File Scope", func(t *testing.T) { ts := CustomTag{ Foo: "foostring13579", Bar: 999_999} encDecCustomTag(t, ts, "mytag") }) } func encDecCustomTag(t *testing.T, testStruct msgp.Encodable, tag string) { var b bytes.Buffer msgp.Encode(&b, testStruct) // Check tag names using JSON as an intermediary layer // TODO: is there a way to avoid the JSON layer? We'd need to directly decode raw msgpack -> map[string]any refJSON, err := json.Marshal(testStruct) if err != nil { t.Error(fmt.Sprintf("error encoding struct as JSON: %v", err)) } ref := make(map[string]any) // Encoding and decoding the original struct via JSON is necessary // for field comparisons to work, since JSON -> map[string]any // relies on type inferences such as all numbers being float64s json.Unmarshal(refJSON, &ref) var encJSON bytes.Buffer msgp.UnmarshalAsJSON(&encJSON, b.Bytes()) encoded := make(map[string]any) json.Unmarshal(encJSON.Bytes(), &encoded) tsType := reflect.TypeOf(testStruct) for i := 0; i < tsType.NumField(); i++ { // Check encoded field name field := tsType.Field(i) encodedValue, ok := encoded[field.Tag.Get(tag)] if !ok { t.Error("missing encoded value for field", field.Name) continue } // Check encoded field value (against original value post-JSON enc + dec) jsonName, ok := field.Tag.Lookup("json") if !ok { jsonName = field.Name } refValue := ref[jsonName] if !reflect.DeepEqual(refValue, encodedValue) { t.Error(fmt.Sprintf("incorrect encoded value for field %s. reference: %v, encoded: %v", field.Name, refValue, encodedValue)) } } } msgp-1.6.1/_generated/def.go000066400000000000000000000216311511433505400156530ustar00rootroot00000000000000package _generated import ( "encoding/json" "os" "time" "github.com/tinylib/msgp/msgp" ) //go:generate msgp -v -o generated.go // All of the struct // definitions in this // file are fed to the code // generator when `make test` is // called, followed by an // invocation of `go test -v` in this // directory. A simple way of testing // a struct definition is // by adding it to this file. //msgp:timezone utc type Block [32]byte // test fixed-size struct // size compilation type Fixed struct { A float64 B bool } type StandaloneBytes []byte type AliasedType = Fixed type AliasedType2 = *Fixed type AliasedType3 = uint64 type AliasedType4 = *uint64 // tests edge-cases with // compiling size compilation. type X struct { Values [32]byte // should compile to 32*msgp.ByteSize; encoded as Bin ValuesPtr *[32]byte // check (*)[:] deref More Block // should be identical to the above Others [][32]int32 // should compile to len(x.Others)*32*msgp.Int32Size Matrix [][]int32 // should not optimize ManyFixed []Fixed WeirdTag string `msg:"\x0b"` ZCBytes []byte `msg:",zerocopy"` ZCBytesAN []byte `msg:",zerocopy,allownil"` ZCBytesOE []byte `msg:",zerocopy,omitempty"` ZCBytesSlice [][]byte `msg:",zerocopy"` ZCBytesArr [2][]byte `msg:",zerocopy"` ZCBytesMap map[string][]byte `msg:",zerocopy"` ZCBytesMapDeep map[string]map[string][]byte `msg:",zerocopy"` CustomBytes CustomBytes `msg:",zerocopy"` Renamed1 AliasedType Renamed2 AliasedType2 Renamed3 AliasedType3 Renamed4 AliasedType4 } type TestType struct { F *float64 `msg:"float"` Els map[string]string `msg:"elements"` Obj struct { // test anonymous struct ValueA string `msg:"value_a"` ValueB []byte `msg:"value_b"` } `msg:"object"` Child *TestType `msg:"child"` Time time.Time `msg:"time"` Any interface{} `msg:"any"` Appended msgp.Raw `msg:"appended"` Num msgp.Number `msg:"num"` Byte byte Rune rune RunePtr *rune RunePtrPtr **rune RuneSlice []rune Slice1 []string Slice2 []string SlicePtr *[]string MapStringEmpty map[string]struct{} MapStringEmpty2 map[string]EmptyStruct } //msgp:tuple Object type Object struct { ObjectNo string `msg:"objno"` Slice1 []string `msg:"slice1"` Slice2 []string `msg:"slice2"` MapMap map[string]map[string]string MapStringEmpty map[string]struct{} MapStringEmpty2 map[string]EmptyStruct ZCBytes []byte `msg:",zerocopy"` ZCBytesAN []byte `msg:",zerocopy,allownil"` ZCBytesOE []byte `msg:",zerocopy,omitempty"` ZCBytesSlice [][]byte `msg:",zerocopy"` ZCBytesArr [2][]byte `msg:",zerocopy"` ZCBytesMap map[string][]byte `msg:",zerocopy"` ZCBytesMapDeep map[string]map[string][]byte `msg:",zerocopy"` CustomBytes CustomBytes `msg:",zerocopy"` } //msgp:tuple TestBench type TestBench struct { Name string BirthDay time.Time Phone string Siblings int Spouse bool Money float64 } //msgp:tuple TestFast type TestFast struct { Lat, Long, Alt float64 // test inline decl Data []byte } // Test nested aliases type ( FastAlias TestFast AliasContainer struct { Fast FastAlias } ) // Test dependency resolution type ( IntA int IntB IntA IntC IntB ) type TestHidden struct { A string B []float64 Bad func(string) bool // This results in a warning: field "Bad" unsupported } type Embedded struct { *Embedded // test embedded field Children []Embedded PtrChildren []*Embedded Other string } const eight = 8 type Things struct { Cmplx complex64 `msg:"complex"` // test slices Vals []int32 `msg:"values"` Arr [msgp.ExtensionPrefixSize]float64 `msg:"arr"` // test const array and *ast.SelectorExpr as array size Arr2 [4]float64 `msg:"arr2"` // test basic lit array Ext *msgp.RawExtension `msg:"ext,extension"` // test extension Oext msgp.RawExtension `msg:"oext,extension"` // test extension reference } //msgp:shim SpecialID as:[]byte using:toBytes/fromBytes type ( SpecialID string TestObj struct{ ID1, ID2 SpecialID } ) func toBytes(id SpecialID) []byte { return []byte(string(id)) } func fromBytes(id []byte) SpecialID { return SpecialID(string(id)) } type MyEnum byte const ( A MyEnum = iota B C D invalid ) // test shim directive (below) //msgp:shim MyEnum as:string using:(MyEnum).String/myenumStr //msgp:shim *os.File as:string using:filetostr/filefromstr func filetostr(f *os.File) string { return f.Name() } func filefromstr(s string) *os.File { f, _ := os.Open(s) return f } func (m MyEnum) String() string { switch m { case A: return "A" case B: return "B" case C: return "C" case D: return "D" default: return "" } } func myenumStr(s string) MyEnum { switch s { case "A": return A case "B": return B case "C": return C case "D": return D default: return invalid } } // test pass-specific directive //msgp:decode ignore Insane type Insane [3]map[string]struct{ A, B CustomInt } type Custom struct { Bts CustomBytes `msg:"bts"` Mp map[string]*Embedded `msg:"mp"` Enums []MyEnum `msg:"enums"` // test explicit enum shim Some FileHandle `msg:"file_handle"` } type Files []*os.File type FileHandle struct { Relevant Files `msg:"files"` Name string `msg:"name"` } type ( CustomInt int CustomBytes []byte ) type Wrapper struct { Tree *Tree } type Tree struct { Children []Tree Element int Parent *Wrapper } // Ensure all different widths of integer can be used as constant keys. const ( ConstantInt int = 8 ConstantInt8 int8 = 8 ConstantInt16 int16 = 8 ConstantInt32 int32 = 8 ConstantInt64 int64 = 8 ConstantUint uint = 8 ConstantUint8 uint8 = 8 ConstantUint16 uint16 = 8 ConstantUint32 uint32 = 8 ConstantUint64 uint64 = 8 ) type ArrayConstants struct { ConstantInt [ConstantInt]string ConstantInt8 [ConstantInt8]string ConstantInt16 [ConstantInt16]string ConstantInt32 [ConstantInt32]string ConstantInt64 [ConstantInt64]string ConstantUint [ConstantUint]string ConstantUint8 [ConstantUint8]string ConstantUint16 [ConstantUint16]string ConstantUint32 [ConstantUint32]string ConstantUint64 [ConstantUint64]string ConstantHex [0x16]string ConstantOctal [0o7]string } // Ensure non-msg struct tags work: // https://github.com/tinylib/msgp/issues/201 type NonMsgStructTags struct { A []string `json:"fooJSON" msg:"fooMsgp"` B string `json:"barJSON"` C []string `json:"bazJSON" msg:"-"` Nested []struct { A []string `json:"a"` B string `json:"b"` C []string `json:"c"` VeryNested []struct { A []string `json:"a"` B []string `msg:"bbbb" xml:"-"` C map[string]struct{} `msg:"cccc"` } } } type EmptyStruct struct{} type StructByteSlice struct { ABytes []byte `msg:",allownil"` AString []string `msg:",allownil"` ABool []bool `msg:",allownil"` AInt []int `msg:",allownil"` AInt8 []int8 `msg:",allownil"` AInt16 []int16 `msg:",allownil"` AInt32 []int32 `msg:",allownil"` AInt64 []int64 `msg:",allownil"` AUint []uint `msg:",allownil"` AUint8 []uint8 `msg:",allownil"` AUint16 []uint16 `msg:",allownil"` AUint32 []uint32 `msg:",allownil"` AUint64 []uint64 `msg:",allownil"` AFloat32 []float32 `msg:",allownil"` AFloat64 []float64 `msg:",allownil"` AComplex64 []complex64 `msg:",allownil"` AComplex128 []complex128 `msg:",allownil"` AStruct []Fixed `msg:",allownil"` } type NumberJSONSample struct { Single json.Number Array []json.Number Map map[string]json.Number OE json.Number `msg:",omitempty"` } type Flobbity struct { A Flobs `msg:"a,omitempty"` B Flobs `msg:"b,omitempty"` } type Flobs []Flob type Flob struct { X Numberwang `msg:"x"` Y int8 `msg:"y"` Z int8 `msg:"z"` W int32 `msg:"w"` } type Numberwang int8 //msgp:ignore ExternalString type ExternalString string type ExternalArr [4]byte type ExternalInt int //msgp:ignore regex:IGNORE type RegexIGNORETest struct{} // Will fail to compile if also generated func (z *RegexIGNORETest) Msgsize() int { return 0 } //msgp:size ignore regex:IGNSIZE type RegexIGNSIZETest struct{} // Will fail to compile if also generated func (z *RegexIGNSIZETest) Msgsize() int { return 0 } msgp-1.6.1/_generated/def_test.go000066400000000000000000000113151511433505400167100ustar00rootroot00000000000000package _generated import ( "bytes" "encoding/json" "reflect" "testing" "github.com/tinylib/msgp/msgp" ) func TestRuneEncodeDecode(t *testing.T) { tt := &TestType{} r := 'r' rp := &r tt.Rune = r tt.RunePtr = &r tt.RunePtrPtr = &rp tt.RuneSlice = []rune{'a', 'b', '😳'} var buf bytes.Buffer wrt := msgp.NewWriter(&buf) if err := tt.EncodeMsg(wrt); err != nil { t.Errorf("%v", err) } wrt.Flush() var out TestType rdr := msgp.NewReader(&buf) if err := (&out).DecodeMsg(rdr); err != nil { t.Errorf("%v", err) } if r != out.Rune { t.Errorf("rune mismatch: expected %c found %c", r, out.Rune) } if r != *out.RunePtr { t.Errorf("rune ptr mismatch: expected %c found %c", r, *out.RunePtr) } if r != **out.RunePtrPtr { t.Errorf("rune ptr ptr mismatch: expected %c found %c", r, **out.RunePtrPtr) } if !reflect.DeepEqual(tt.RuneSlice, out.RuneSlice) { t.Errorf("rune slice mismatch") } } func TestRuneMarshalUnmarshal(t *testing.T) { tt := &TestType{} r := 'r' rp := &r tt.Rune = r tt.RunePtr = &r tt.RunePtrPtr = &rp tt.RuneSlice = []rune{'a', 'b', '😳'} bts, err := tt.MarshalMsg(nil) if err != nil { t.Errorf("%v", err) } var out TestType if _, err := (&out).UnmarshalMsg(bts); err != nil { t.Errorf("%v", err) } if r != out.Rune { t.Errorf("rune mismatch: expected %c found %c", r, out.Rune) } if r != *out.RunePtr { t.Errorf("rune ptr mismatch: expected %c found %c", r, *out.RunePtr) } if r != **out.RunePtrPtr { t.Errorf("rune ptr ptr mismatch: expected %c found %c", r, **out.RunePtrPtr) } if !reflect.DeepEqual(tt.RuneSlice, out.RuneSlice) { t.Errorf("rune slice mismatch") } } func TestJSONNumber(t *testing.T) { test := NumberJSONSample{ Single: "-42", Array: []json.Number{"0", "-0", "1", "-1", "0.1", "-0.1", "1234", "-1234", "12.34", "-12.34", "12E0", "12E1", "12e34", "12E-0", "12e+1", "12e-34", "-12E0", "-12E1", "-12e34", "-12E-0", "-12e+1", "-12e-34", "1.2E0", "1.2E1", "1.2e34", "1.2E-0", "1.2e+1", "1.2e-34", "-1.2E0", "-1.2E1", "-1.2e34", "-1.2E-0", "-1.2e+1", "-1.2e-34", "0E0", "0E1", "0e34", "0E-0", "0e+1", "0e-34", "-0E0", "-0E1", "-0e34", "-0E-0", "-0e+1", "-0e-34"}, Map: map[string]json.Number{ "a": json.Number("50.2"), }, } // This is not guaranteed to be symmetric encoded, err := test.MarshalMsg(nil) if err != nil { t.Errorf("%v", err) } var v NumberJSONSample _, err = v.UnmarshalMsg(encoded) if err != nil { t.Errorf("%v", err) } // Test two values if v.Single != "-42" { t.Errorf("want %v, got %v", "-42", v.Single) } if v.Map["a"] != "50.2" { t.Errorf("want %v, got %v", "50.2", v.Map["a"]) } var jsBuf bytes.Buffer remain, err := msgp.UnmarshalAsJSON(&jsBuf, encoded) if err != nil { t.Errorf("%v", err) } if len(remain) != 0 { t.Errorf("remain should be empty") } wantjs := `{"Single":-42,"Array":[0,0,1,-1,0.1,-0.1,1234,-1234,12.34,-12.34,12,120,120000000000000000000000000000000000,12,120,0.0000000000000000000000000000000012,-12,-120,-120000000000000000000000000000000000,-12,-120,-0.0000000000000000000000000000000012,1.2,12,12000000000000000000000000000000000,1.2,12,0.00000000000000000000000000000000012,-1.2,-12,-12000000000000000000000000000000000,-1.2,-12,-0.00000000000000000000000000000000012,0,0,0,0,0,0,-0,-0,-0,-0,-0,-0],"Map":{"a":50.2}}` if jsBuf.String() != wantjs { t.Errorf("jsBuf.String() = \n%s, want \n%s", jsBuf.String(), wantjs) } // Test encoding var buf bytes.Buffer en := msgp.NewWriter(&buf) err = test.EncodeMsg(en) if err != nil { t.Errorf("%v", err) } en.Flush() encoded = buf.Bytes() dc := msgp.NewReader(&buf) err = v.DecodeMsg(dc) if err != nil { t.Errorf("%v", err) } // Test two values if v.Single != "-42" { t.Errorf("want %s, got %s", "-42", v.Single) } if v.Map["a"] != "50.2" { t.Errorf("want %s, got %s", "50.2", v.Map["a"]) } jsBuf.Reset() remain, err = msgp.UnmarshalAsJSON(&jsBuf, encoded) if err != nil { t.Errorf("%v", err) } if len(remain) != 0 { t.Errorf("remain should be empty") } if jsBuf.String() != wantjs { t.Errorf("jsBuf.String() = \n%s, want \n%s", jsBuf.String(), wantjs) } // Try interface encoder jd := json.NewDecoder(&jsBuf) jd.UseNumber() var jsIntf map[string]any err = jd.Decode(&jsIntf) if err != nil { t.Errorf("%v", err) } // Ensure we encode correctly _ = (jsIntf["Single"]).(json.Number) fromInt, err := msgp.AppendIntf(nil, jsIntf) if err != nil { t.Errorf("%v", err) } // Take the value from the JSON interface encoder and unmarshal back into our struct. v = NumberJSONSample{} _, err = v.UnmarshalMsg(fromInt) if err != nil { t.Errorf("%v", err) } if v.Single != "-42" { t.Errorf("want %s, got %s", "-42", v.Single) } if v.Map["a"] != "50.2" { t.Errorf("want %s, got %s", "50.2", v.Map["a"]) } } msgp-1.6.1/_generated/embedded_struct.go000066400000000000000000000005651511433505400202550ustar00rootroot00000000000000package _generated //go:generate msgp type GetUserRequestWithEmbeddedStruct struct { Common `msg:",flatten"` UserID uint32 `msg:"user_id"` } type GetUserRequest struct { RequestID uint32 `msg:"request_id"` Token string `msg:"token"` UserID uint32 `msg:"user_id"` } type Common struct { RequestID uint32 `msg:"request_id"` Token string `msg:"token"` } msgp-1.6.1/_generated/embedded_struct_test.go000066400000000000000000000030441511433505400213070ustar00rootroot00000000000000package _generated import ( "testing" ) func TestConvertDataFromAEmbeddedStructToANonEmbeddedStruct(t *testing.T) { getUserRequestWithEmbeddedStruct := GetUserRequestWithEmbeddedStruct{ Common: Common{ RequestID: 10, Token: "token", }, UserID: 1000, } bytes, err := getUserRequestWithEmbeddedStruct.MarshalMsg(nil) if err != nil { t.Fatal(err) } getUserRequest := GetUserRequest{} _, err = getUserRequest.UnmarshalMsg(bytes) if err != nil { t.Fatal(err) } if getUserRequest.RequestID != getUserRequestWithEmbeddedStruct.RequestID { t.Fatal("not same request id") } if getUserRequest.UserID != getUserRequestWithEmbeddedStruct.UserID { t.Fatal("not same user id") } if getUserRequest.Token != getUserRequestWithEmbeddedStruct.Token { t.Fatal("not same token") } return } func TestConvertDataFromANonEmbeddedStructToAEmbeddedStruct(t *testing.T) { getUserRequest := GetUserRequest{ RequestID: 10, Token: "token", UserID: 1000, } bytes, err := getUserRequest.MarshalMsg(nil) if err != nil { t.Fatal(err) } getUserRequestWithEmbeddedStruct := GetUserRequestWithEmbeddedStruct{} _, err = getUserRequestWithEmbeddedStruct.UnmarshalMsg(bytes) if err != nil { t.Fatal(err) } if getUserRequest.RequestID != getUserRequestWithEmbeddedStruct.RequestID { t.Fatal("not same request id") } if getUserRequest.UserID != getUserRequestWithEmbeddedStruct.UserID { t.Fatal("not same user id") } if getUserRequest.Token != getUserRequestWithEmbeddedStruct.Token { t.Fatal("not same token") } return } msgp-1.6.1/_generated/errorwrap.go000066400000000000000000000026701511433505400171420ustar00rootroot00000000000000package _generated //go:generate msgp // The leaves of interest in this crazy structs are strings. The test case // looks for strings in the serialised msgpack and makes them unreadable. type ErrorCtxMapChild struct { Val string } type ErrorCtxMapChildNotInline struct { Val1, Val2, Val3, Val4, Val5 string } type ErrorCtxAsMap struct { Val string Child *ErrorCtxMapChild Children []*ErrorCtxMapChild ComplexChild *ErrorCtxMapChildNotInline Map map[string]string Nest struct { Val string Child *ErrorCtxMapChild Children []*ErrorCtxMapChild Map map[string]string Nest struct { Val string Child *ErrorCtxMapChild Children []*ErrorCtxMapChild Map map[string]string } } } //msgp:tuple ErrorCtxTupleChild type ErrorCtxTupleChild struct { Val string } //msgp:tuple ErrorCtxTupleChildNotInline type ErrorCtxTupleChildNotInline struct { Val1, Val2, Val3, Val4, Val5 string } //msgp:tuple ErrorCtxAsTuple type ErrorCtxAsTuple struct { Val string Child *ErrorCtxTupleChild Children []*ErrorCtxTupleChild ComplexChild *ErrorCtxTupleChildNotInline Map map[string]string Nest struct { Val string Child *ErrorCtxTupleChild Children []*ErrorCtxTupleChild Map map[string]string Nest struct { Val string Child *ErrorCtxTupleChild Children []*ErrorCtxTupleChild Map map[string]string } } } msgp-1.6.1/_generated/errorwrap_test.go000066400000000000000000000162271511433505400202040ustar00rootroot00000000000000package _generated import ( "bytes" "io" "testing" "github.com/tinylib/msgp/msgp" ) func fillErrorCtxAsMap() *ErrorCtxAsMap { v := &ErrorCtxAsMap{} v.Val = "foo" v.ComplexChild = &ErrorCtxMapChildNotInline{Val1: "a", Val2: "b", Val3: "c", Val4: "d", Val5: "e"} v.Child = &ErrorCtxMapChild{Val: "foo"} v.Children = []*ErrorCtxMapChild{{Val: "foo"}, {Val: "bar"}} v.Map = map[string]string{"foo": "bar", "baz": "qux"} v.Nest.Val = "foo" v.Nest.Child = &ErrorCtxMapChild{Val: "foo"} v.Nest.Children = []*ErrorCtxMapChild{{Val: "foo"}, {Val: "bar"}} v.Nest.Map = map[string]string{"foo": "bar", "baz": "qux"} v.Nest.Nest.Val = "foo" v.Nest.Nest.Child = &ErrorCtxMapChild{Val: "foo"} v.Nest.Nest.Children = []*ErrorCtxMapChild{{Val: "foo"}, {Val: "bar"}} v.Nest.Nest.Map = map[string]string{"foo": "bar", "baz": "qux"} return v } func fillErrorCtxAsTuple() *ErrorCtxAsTuple { v := &ErrorCtxAsTuple{} v.Val = "foo" v.ComplexChild = &ErrorCtxTupleChildNotInline{Val1: "a", Val2: "b", Val3: "c", Val4: "d", Val5: "e"} v.Child = &ErrorCtxTupleChild{Val: "foo"} v.Children = []*ErrorCtxTupleChild{{Val: "foo"}, {Val: "bar"}} v.Map = map[string]string{"foo": "bar", "baz": "qux"} v.Nest.Val = "foo" v.Nest.Child = &ErrorCtxTupleChild{Val: "foo"} v.Nest.Children = []*ErrorCtxTupleChild{{Val: "foo"}, {Val: "bar"}} v.Nest.Map = map[string]string{"foo": "bar", "baz": "qux"} v.Nest.Nest.Val = "foo" v.Nest.Nest.Child = &ErrorCtxTupleChild{Val: "foo"} v.Nest.Nest.Children = []*ErrorCtxTupleChild{{Val: "foo"}, {Val: "bar"}} v.Nest.Nest.Map = map[string]string{"foo": "bar", "baz": "qux"} return v } type dodgifierBuf struct { *bytes.Buffer dodgifyString int strIdx int } func (o *dodgifierBuf) Write(b []byte) (n int, err error) { ilen := len(b) if msgp.NextType(b) == msgp.StrType { if o.strIdx == o.dodgifyString { // Fool msgp into thinking this value is a fixint. msgp will throw // a type error for this value. b[0] = 1 } o.strIdx++ } _, err = o.Buffer.Write(b) return ilen, err } type strCounter int func (o *strCounter) Write(b []byte) (n int, err error) { if msgp.NextType(b) == msgp.StrType { *o++ } return len(b), nil } func countStrings(bts []byte) int { r := msgp.NewReader(bytes.NewReader(bts)) strCounter := strCounter(0) for { _, err := r.CopyNext(&strCounter) if err == io.EOF { break } else if err != nil { panic(err) } } return int(strCounter) } func marshalErrorCtx(m msgp.Marshaler) []byte { bts, err := m.MarshalMsg(nil) if err != nil { panic(err) } return bts } // dodgifyMsgpString will wreck the nth string in the msgpack blob // so that it raises an error when decoded or unmarshaled. func dodgifyMsgpString(bts []byte, idx int) []byte { r := msgp.NewReader(bytes.NewReader(bts)) out := &dodgifierBuf{Buffer: &bytes.Buffer{}, dodgifyString: idx} for { _, err := r.CopyNext(out) if err == io.EOF { break } else if err != nil { panic(err) } } return out.Bytes() } func TestErrorCtxAsMapUnmarshal(t *testing.T) { bts := marshalErrorCtx(fillErrorCtxAsMap()) cnt := countStrings(bts) var as []string for i := 0; i < cnt; i++ { dodgeBts := dodgifyMsgpString(bts, i) var ec ErrorCtxAsMap _, err := (&ec).UnmarshalMsg(dodgeBts) as = append(as, err.Error()) } ok, a, b := diffstrs(as, expectedAsMap()) if !ok { t.Fatal(a, b) } } func TestErrorCtxAsMapDecode(t *testing.T) { bts := marshalErrorCtx(fillErrorCtxAsMap()) cnt := countStrings(bts) var as []string for i := 0; i < cnt; i++ { dodgeBts := dodgifyMsgpString(bts, i) r := msgp.NewReader(bytes.NewReader(dodgeBts)) var ec ErrorCtxAsMap err := (&ec).DecodeMsg(r) as = append(as, err.Error()) } ok, a, b := diffstrs(as, expectedAsMap()) if !ok { t.Fatal(a, b) } } func TestErrorCtxAsTupleUnmarshal(t *testing.T) { bts := marshalErrorCtx(fillErrorCtxAsTuple()) cnt := countStrings(bts) var as []string for i := 0; i < cnt; i++ { dodgeBts := dodgifyMsgpString(bts, i) var ec ErrorCtxAsTuple _, err := (&ec).UnmarshalMsg(dodgeBts) as = append(as, err.Error()) } ok, a, b := diffstrs(as, expectedAsTuple()) if !ok { t.Fatal(a, b) } } func TestErrorCtxAsTupleDecode(t *testing.T) { bts := marshalErrorCtx(fillErrorCtxAsTuple()) cnt := countStrings(bts) var as []string for i := 0; i < cnt; i++ { dodgeBts := dodgifyMsgpString(bts, i) r := msgp.NewReader(bytes.NewReader(dodgeBts)) var ec ErrorCtxAsTuple err := (&ec).DecodeMsg(r) as = append(as, err.Error()) } ok, a, b := diffstrs(as, expectedAsTuple()) if !ok { t.Fatal(a, b) } } func diffstrs(a, b []string) (ok bool, as, bs []string) { ma := map[string]bool{} mb := map[string]bool{} for _, x := range a { ma[x] = true } for _, x := range b { mb[x] = true } for _, x := range a { if !mb[x] { as = append(as, x) } } for _, x := range b { if !ma[x] { bs = append(bs, x) } } return len(as)+len(bs) == 0, as, bs } var errPrefix = `msgp: attempted to decode type "int" with method for "str"` func expectedAsTuple() []string { var out []string for _, s := range []string{ `Val`, `Child/Val`, `Children/0/Val`, `Children/1/Val`, `ComplexChild/Val1`, `ComplexChild/Val2`, `ComplexChild/Val3`, `ComplexChild/Val4`, `ComplexChild/Val5`, `Map`, `Map/baz`, `Map`, `Map/foo`, `Nest`, `Nest/Val`, `Nest`, `Nest/Child/Val`, `Nest`, `Nest/Children/0/Val`, `Nest/Children/1/Val`, `Nest`, `Nest/Map`, `Nest/Map/foo`, `Nest/Map`, `Nest/Map/baz`, `Nest`, `Nest/Nest`, `Nest/Nest/Val`, `Nest/Nest`, `Nest/Nest/Child/Val`, `Nest/Nest`, `Nest/Nest/Children/0/Val`, `Nest/Nest/Children/1/Val`, `Nest/Nest`, `Nest/Nest/Map`, `Nest/Nest/Map/foo`, `Nest/Nest/Map`, `Nest/Nest/Map/baz`, } { if s == "" { out = append(out, errPrefix) } else { out = append(out, errPrefix+" at "+s) } } return out } // there are a lot of extra errors in here at the struct level because we are // not discriminating between dodgy struct field map key strings and // values. dodgy struct field map keys have no field context available when // they are read. func expectedAsMap() []string { var out []string for _, s := range []string{ ``, `Val`, ``, `Child`, `Child/Val`, ``, `Children/0`, `Children/0/Val`, `Children/1`, `Children/1/Val`, `ComplexChild`, `ComplexChild/Val1`, `ComplexChild`, `ComplexChild/Val2`, `ComplexChild`, `ComplexChild/Val3`, `ComplexChild`, `ComplexChild/Val4`, `ComplexChild`, `ComplexChild/Val5`, `Map`, `Map/foo`, `Map`, `Map/baz`, ``, `Nest`, `Nest/Val`, `Nest`, `Nest/Child`, `Nest/Child/Val`, `Nest`, `Nest/Children/0`, `Nest/Children/0/Val`, `Nest/Children/1`, `Nest/Children/1/Val`, `Nest`, `Nest/Map`, `Nest/Map/foo`, `Nest/Map`, `Nest/Map/baz`, `Nest`, `Nest/Nest`, `Nest/Nest/Val`, `Nest/Nest`, `Nest/Nest/Child`, `Nest/Nest/Child/Val`, `Nest/Nest`, `Nest/Nest/Children/0`, `Nest/Nest/Children/0/Val`, `Nest/Nest/Children/1`, `Nest/Nest/Children/1/Val`, `Nest/Nest`, `Nest/Nest/Map`, `Nest/Nest/Map/baz`, `Nest/Nest/Map`, `Nest/Nest/Map/foo`, } { if s == "" { out = append(out, errPrefix) } else { out = append(out, errPrefix+" at "+s) } } return out } msgp-1.6.1/_generated/field_limits.go000066400000000000000000000021641511433505400175610ustar00rootroot00000000000000package _generated //go:generate msgp // Aliased types for testing type AliasedSlice []string type AliasedMap map[string]bool type AliasedIntSlice []int // Test structures for field-level limit tags type FieldLimitTestData struct { SmallSlice []int `msg:"small_slice,limit=5"` LargeSlice []string `msg:"large_slice,limit=100"` SmallMap map[string]int `msg:"small_map,limit=3"` LargeMap map[int]string `msg:"large_map,limit=20"` NoLimit []byte `msg:"no_limit"` // Uses file-level limits if any FixedArray [10]int `msg:"fixed_array,limit=2"` // Should be ignored } // Test structure with aliased types and field limits type AliasedFieldLimitTestData struct { SmallAliasedSlice AliasedSlice `msg:"small_aliased_slice,limit=3"` LargeAliasedSlice AliasedSlice `msg:"large_aliased_slice,limit=50"` SmallAliasedMap AliasedMap `msg:"small_aliased_map,limit=2"` LargeAliasedMap AliasedMap `msg:"large_aliased_map,limit=25"` IntSliceAlias AliasedIntSlice `msg:"int_slice_alias,limit=10"` NoLimitAlias AliasedSlice `msg:"no_limit_alias"` // Uses file-level limits }msgp-1.6.1/_generated/gen_test.go000066400000000000000000000124341511433505400167260ustar00rootroot00000000000000package _generated import ( "bytes" "reflect" "testing" "time" "github.com/tinylib/msgp/msgp" ) // benchmark encoding a small, "fast" type. // the point here is to see how much garbage // is generated intrinsically by the encoding/ // decoding process as opposed to the nature // of the struct. func BenchmarkFastEncode(b *testing.B) { v := &TestFast{ Lat: 40.12398, Long: -41.9082, Alt: 201.08290, Data: []byte("whaaaaargharbl"), } var buf bytes.Buffer msgp.Encode(&buf, v) en := msgp.NewWriter(msgp.Nowhere) b.SetBytes(int64(buf.Len())) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { v.EncodeMsg(en) } en.Flush() } // benchmark decoding a small, "fast" type. // the point here is to see how much garbage // is generated intrinsically by the encoding/ // decoding process as opposed to the nature // of the struct. func BenchmarkFastDecode(b *testing.B) { v := &TestFast{ Lat: 40.12398, Long: -41.9082, Alt: 201.08290, Data: []byte("whaaaaargharbl"), } var buf bytes.Buffer msgp.Encode(&buf, v) dc := msgp.NewReader(msgp.NewEndlessReader(buf.Bytes(), b)) b.SetBytes(int64(buf.Len())) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { v.DecodeMsg(dc) } } func (a *TestType) Equal(b *TestType) bool { // compare times, appended, then zero out those // fields, perform a DeepEqual, and restore them ta, tb := a.Time, b.Time if !ta.Equal(tb) { return false } aa, ab := a.Appended, b.Appended if !bytes.Equal(aa, ab) { return false } if len(a.MapStringEmpty) == 0 && len(b.MapStringEmpty) == 0 { a.MapStringEmpty = nil b.MapStringEmpty = nil } if len(a.MapStringEmpty2) == 0 && len(b.MapStringEmpty2) == 0 { a.MapStringEmpty2 = nil b.MapStringEmpty2 = nil } a.Time, b.Time = time.Time{}, time.Time{} aa, ab = nil, nil ok := reflect.DeepEqual(a, b) a.Time, b.Time = ta, tb a.Appended, b.Appended = aa, ab return ok } // This covers the following cases: // - Recursive types // - Non-builtin identifiers (and recursive types) // - time.Time // - map[string]string // - anonymous structs func Test1EncodeDecode(t *testing.T) { f := 32.00 tt := &TestType{ F: &f, Els: map[string]string{ "thing_one": "one", "thing_two": "two", }, Obj: struct { ValueA string `msg:"value_a"` ValueB []byte `msg:"value_b"` }{ ValueA: "here's the first inner value", ValueB: []byte("here's the second inner value"), }, Child: nil, Time: time.Now(), Appended: msgp.Raw([]byte{}), // 'nil' MapStringEmpty: map[string]struct{}{"Key": {}, "Key2": {}}, MapStringEmpty2: map[string]EmptyStruct{"Key3": {}, "Key4": {}}, } var buf bytes.Buffer err := msgp.Encode(&buf, tt) if err != nil { t.Fatal(err) } tnew := new(TestType) err = msgp.Decode(&buf, tnew) if err != nil { t.Error(err) } if !tt.Equal(tnew) { t.Logf("in: %#v", tt) t.Logf("out: %#v", tnew) t.Fatal("objects not equal") } if tnew.Time.Location() != time.UTC { t.Errorf("time location not UTC: %v", tnew.Time.Location()) } tanother := new(TestType) buf.Reset() msgp.Encode(&buf, tt) var left []byte left, err = tanother.UnmarshalMsg(buf.Bytes()) if err != nil { t.Error(err) } if len(left) > 0 { t.Errorf("%d bytes left", len(left)) } if !tt.Equal(tanother) { t.Logf("in: %v", tt) t.Logf("out: %v", tanother) t.Fatal("objects not equal") } if tanother.Time.Location() != time.UTC { t.Errorf("time location not UTC: %v", tanother.Time.Location()) } } func TestIssue168(t *testing.T) { buf := bytes.Buffer{} test := TestObj{} msgp.Encode(&buf, &TestObj{ID1: "1", ID2: "2"}) msgp.Decode(&buf, &test) if test.ID1 != "1" || test.ID2 != "2" { t.Fatalf("got back %+v", test) } } func TestIssue362(t *testing.T) { in := StructByteSlice{ ABytes: make([]byte, 0), AString: make([]string, 0), ABool: make([]bool, 0), AInt: make([]int, 0), AInt8: make([]int8, 0), AInt16: make([]int16, 0), AInt32: make([]int32, 0), AInt64: make([]int64, 0), AUint: make([]uint, 0), AUint8: make([]uint8, 0), AUint16: make([]uint16, 0), AUint32: make([]uint32, 0), AUint64: make([]uint64, 0), AFloat32: make([]float32, 0), AFloat64: make([]float64, 0), AComplex64: make([]complex64, 0), AComplex128: make([]complex128, 0), AStruct: make([]Fixed, 0), } b, err := in.MarshalMsg(nil) if err != nil { t.Fatal(err) } var dst StructByteSlice _, err = dst.UnmarshalMsg(b) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(in, dst) { t.Fatalf("mismatch %#v != %#v", in, dst) } dst2 := StructByteSlice{} dec := msgp.NewReader(bytes.NewReader(b)) err = dst2.DecodeMsg(dec) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(in, dst2) { t.Fatalf("mismatch %#v != %#v", in, dst2) } // Encode with nil zero := StructByteSlice{} b, err = zero.MarshalMsg(nil) if err != nil { t.Fatal(err) } // Decode into dst that now has values... _, err = dst.UnmarshalMsg(b) if err != nil { t.Fatal(err) } // All should be nil now. if !reflect.DeepEqual(zero, dst) { t.Fatalf("mismatch %#v != %#v", zero, dst) } dec = msgp.NewReader(bytes.NewReader(b)) err = dst2.DecodeMsg(dec) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(zero, dst2) { t.Fatalf("mismatch %#v != %#v", zero, dst2) } } msgp-1.6.1/_generated/generics.go000066400000000000000000000056151511433505400167200ustar00rootroot00000000000000package _generated import "github.com/tinylib/msgp/msgp" //go:generate msgp -v type Int64 int type GenericTest[T any, P msgp.RTFor[T]] struct { A T B P C []T `msg:",allownil"` D map[string]T `msg:",allownil"` E GenericTest2[T, P, string] F []GenericTest2[T, P, string] `msg:",allownil"` G map[string]GenericTest2[T, P, string] `msg:",allownil"` AP *T CP []*T `msg:",allownil"` DP map[string]*T `msg:",allownil"` EP *GenericTest2[T, P, string] FP []*GenericTest2[T, P, string] `msg:",allownil"` GP map[string]*GenericTest2[T, P, string] `msg:",allownil"` } type GenericTest2[T any, P msgp.RTFor[T], B any] struct { A T } //msgp:tuple GenericTuple type GenericTuple[T any, P msgp.RTFor[T], B any] struct { A T B P C []T `msg:",allownil"` D map[string]T `msg:",allownil"` E GenericTest2[T, P, string] F []GenericTest2[T, P, string] `msg:",allownil"` G map[string]GenericTest2[T, P, string] `msg:",allownil"` AP *T CP []*T `msg:",allownil"` DP map[string]*T `msg:",allownil"` EP *GenericTest2[T, P, string] FP []*GenericTest2[T, P, string] `msg:",allownil"` GP map[string]*GenericTest2[T, P, string] `msg:",allownil"` } // Type that doesn't have any fields using the generic type should just output valid code. type GenericTestUnused[T any] struct { A string } type GenericTestTwo[A, B any, AP msgp.RTFor[A], BP msgp.RTFor[B]] struct { A A B AP C []A `msg:",allownil"` D map[string]T `msg:",allownil"` E GenericTest2[A, AP, string] F []GenericTest2[A, AP, string] `msg:",allownil"` G map[string]GenericTest2[A, AP, string] `msg:",allownil"` AP *A CP []*A `msg:",allownil"` DP map[string]*A `msg:",allownil"` EP *GenericTest2[A, AP, string] FP []*GenericTest2[A, AP, string] `msg:",allownil"` GP map[string]*GenericTest2[A, AP, string] `msg:",allownil"` A2 B B2 BP C2 []B `msg:",allownil"` D2 map[string]B `msg:",allownil"` E2 GenericTest2[B, BP, string] F2 []GenericTest2[B, BP, string] `msg:",allownil"` G2 map[string]GenericTest2[B, BP, string] `msg:",allownil"` AP2 *B CP2 []*B `msg:",allownil"` DP2 map[string]*B `msg:",allownil"` EP2 *GenericTest2[B, BP, string] FP2 []*GenericTest2[B, BP, string] `msg:",allownil"` GP2 map[string]*GenericTest2[B, BP, string] `msg:",allownil"` } type GenericTest3List[A, B any, AP msgp.RTFor[A], BP msgp.RTFor[B]] []GenericTest3[A, B, AP, BP] type GenericTest3Map[A, B any, AP msgp.RTFor[A], BP msgp.RTFor[B]] map[string]GenericTest3[A, B, AP, BP] type GenericTest3Array[A, B any, AP msgp.RTFor[A], BP msgp.RTFor[B]] [5]GenericTest3[A, B, AP, BP] type GenericTest3[A, B any, _ msgp.RTFor[A], _ msgp.RTFor[B]] struct { A A B B } // GenericTest4 has the msgp.RTFor constraint as a sub-constraint. type GenericTest4[T any, P interface { *T msgp.RTFor[T] }] struct { Totals [60]T } msgp-1.6.1/_generated/generics_test.go000066400000000000000000000073101511433505400177510ustar00rootroot00000000000000package _generated import ( "bytes" "reflect" "testing" "github.com/tinylib/msgp/msgp" ) func TestGenericsMarshal(t *testing.T) { x := GenericTest[Fixed, *Fixed]{} x.B = &Fixed{A: 1.5} x.C = append(x.C, Fixed{A: 2.5}) x.D = map[string]Fixed{"hello": Fixed{A: 2.5}} x.E.A = Fixed{A: 2.5} x.F = append(x.F, GenericTest2[Fixed, *Fixed, string]{A: Fixed{A: 3.5}}) x.G = map[string]GenericTest2[Fixed, *Fixed, string]{"hello": {A: Fixed{A: 3.5}}} bts, err := x.MarshalMsg(nil) if err != nil { t.Fatal(err) } got := GenericTest[Fixed, *Fixed]{} got.B = x.B // We must initialize this. *got.B = Fixed{} bts, err = got.UnmarshalMsg(bts) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(x, got) { t.Errorf("\n got=%#v\nwant=%#v", got, x) } } func TestGenericsEncode(t *testing.T) { x := GenericTest[Fixed, *Fixed]{} x.B = &Fixed{A: 1.5} x.C = append(x.C, Fixed{A: 2.5}) x.D = map[string]Fixed{"hello": Fixed{A: 2.5}} x.E.A = Fixed{A: 2.5} x.F = append(x.F, GenericTest2[Fixed, *Fixed, string]{A: Fixed{A: 3.5}}) x.G = map[string]GenericTest2[Fixed, *Fixed, string]{"hello": {A: Fixed{A: 3.5}}} var buf bytes.Buffer w := msgp.NewWriter(&buf) err := x.EncodeMsg(w) if err != nil { t.Fatal(err) } w.Flush() got := GenericTest[Fixed, *Fixed]{} got.B = x.B // We must initialize this. *got.B = Fixed{} r := msgp.NewReader(&buf) err = got.DecodeMsg(r) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(x, got) { t.Errorf("\n got=%#v\nwant=%#v", got, x) } } // Test for generic alias types (slices, maps, arrays) - these verify the type parameter fix func TestGenericTest3List(t *testing.T) { // Test GenericTest3List list := GenericTest3List[Fixed, Fixed, *Fixed, *Fixed]{ {A: Fixed{A: 1.5}, B: Fixed{A: 2.5}}, {A: Fixed{A: 3.5}, B: Fixed{A: 4.5}}, } // Test marshaling data, err := list.MarshalMsg(nil) if err != nil { t.Fatalf("GenericTest3List.MarshalMsg failed: %v", err) } // Test unmarshaling var list2 GenericTest3List[Fixed, Fixed, *Fixed, *Fixed] _, err = list2.UnmarshalMsg(data) if err != nil { t.Fatalf("GenericTest3List.UnmarshalMsg failed: %v", err) } // Verify round-trip if len(list2) != 2 || list2[0].A.A != 1.5 || list2[0].B.A != 2.5 { t.Errorf("GenericTest3List round-trip failed") } } func TestGenericTest3Map(t *testing.T) { // Test GenericTest3Map testMap := GenericTest3Map[Fixed, Fixed, *Fixed, *Fixed]{ "key1": {A: Fixed{A: 1.5}, B: Fixed{A: 2.5}}, "key2": {A: Fixed{A: 3.5}, B: Fixed{A: 4.5}}, } // Test marshaling data, err := testMap.MarshalMsg(nil) if err != nil { t.Fatalf("GenericTest3Map.MarshalMsg failed: %v", err) } // Test unmarshaling var testMap2 GenericTest3Map[Fixed, Fixed, *Fixed, *Fixed] _, err = testMap2.UnmarshalMsg(data) if err != nil { t.Fatalf("GenericTest3Map.UnmarshalMsg failed: %v", err) } // Verify round-trip if len(testMap2) != 2 || testMap2["key1"].A.A != 1.5 || testMap2["key1"].B.A != 2.5 { t.Errorf("GenericTest3Map round-trip failed") } } func TestGenericTest3Array(t *testing.T) { // Test GenericTest3Array testArray := GenericTest3Array[Fixed, Fixed, *Fixed, *Fixed]{ {A: Fixed{A: 1.5}, B: Fixed{A: 2.5}}, {A: Fixed{A: 3.5}, B: Fixed{A: 4.5}}, {A: Fixed{A: 5.5}, B: Fixed{A: 6.5}}, } // Test marshaling data, err := testArray.MarshalMsg(nil) if err != nil { t.Fatalf("GenericTest3Array.MarshalMsg failed: %v", err) } // Test unmarshaling var testArray2 GenericTest3Array[Fixed, Fixed, *Fixed, *Fixed] _, err = testArray2.UnmarshalMsg(data) if err != nil { t.Fatalf("GenericTest3Array.UnmarshalMsg failed: %v", err) } // Verify round-trip if testArray2[0].A.A != 1.5 || testArray2[0].B.A != 2.5 || testArray2[2].A.A != 5.5 { t.Errorf("GenericTest3Array round-trip failed") } } msgp-1.6.1/_generated/issue102.go000066400000000000000000000012671511433505400164730ustar00rootroot00000000000000package _generated //go:generate msgp type Issue102 struct{} type Issue102deep struct { A int X struct{} Y struct{} Z int } //msgp:tuple Issue102Tuple type Issue102Tuple struct{} //msgp:tuple Issue102TupleDeep type Issue102TupleDeep struct { A int X struct{} Y struct{} Z int } type Issue102Uses struct { Nested Issue102 NestedPtr *Issue102 } //msgp:tuple Issue102TupleUsesTuple type Issue102TupleUsesTuple struct { Nested Issue102Tuple NestedPtr *Issue102Tuple } //msgp:tuple Issue102TupleUsesMap type Issue102TupleUsesMap struct { Nested Issue102 NestedPtr *Issue102 } type Issue102MapUsesTuple struct { Nested Issue102Tuple NestedPtr *Issue102Tuple } msgp-1.6.1/_generated/issue191.go000066400000000000000000000001311511433505400164700ustar00rootroot00000000000000package _generated //go:generate msgp type Issue191 struct { Foo string Bar string } msgp-1.6.1/_generated/issue191_test.go000066400000000000000000000003601511433505400175330ustar00rootroot00000000000000package _generated import ( "testing" ) // Issue #191: panic in unsafe.UnsafeString() func TestIssue191(t *testing.T) { b := []byte{0x81, 0xa0, 0xa0} var i Issue191 _, err := (&i).UnmarshalMsg(b) if err != nil { t.Error(err) } } msgp-1.6.1/_generated/issue94.go000066400000000000000000000004631511433505400164220ustar00rootroot00000000000000package _generated import ( "time" ) //go:generate msgp //msgp:shim time.Time as:string using:timetostr/strtotime type T struct { T time.Time } func timetostr(t time.Time) string { return t.Format(time.RFC3339) } func strtotime(s string) time.Time { t, _ := time.Parse(time.RFC3339, s) return t } msgp-1.6.1/_generated/issue94_test.go000066400000000000000000000010671511433505400174620ustar00rootroot00000000000000package _generated import ( "bytes" "os" "testing" ) // Issue 94: shims were not propogated recursively, // which caused shims that weren't at the top level // to be silently ignored. // // The following line will generate an error after // the code is generated if the generated code doesn't // have the right identifier in it. func TestIssue94(t *testing.T) { b, err := os.ReadFile("issue94_gen.go") if err != nil { t.Fatal(err) } const want = "timetostr" if !bytes.Contains(b, []byte(want)) { t.Errorf("generated code did not contain %q", want) } } msgp-1.6.1/_generated/limits.go000066400000000000000000000065531511433505400164240ustar00rootroot00000000000000//msgp:limit arrays:100 maps:50 package _generated //go:generate msgp // Test structures for limit directive type LimitedData struct { SmallArray [10]int `msg:"small_array"` LargeSlice []byte `msg:"large_slice"` SmallMap map[string]int `msg:"small_map"` } type UnlimitedData struct { BigArray [1000]int `msg:"big_array"` BigSlice []string `msg:"big_slice"` BigMap map[string][]int `msg:"big_map"` } type LimitTestData struct { SmallArray [10]int `msg:"small_array"` LargeSlice []byte `msg:"large_slice"` SmallMap map[string]int `msg:"small_map"` } // Test field limits vs file limits precedence // File limits: arrays:100 maps:50 type FieldOverrideTestData struct { TightSlice []int `msg:"tight_slice,limit=10"` // Field limit (10) < file limit (100) LooseSlice []string `msg:"loose_slice,limit=200"` // Field limit (200) > file limit (100) TightMap map[string]int `msg:"tight_map,limit=5"` // Field limit (5) < file limit (50) LooseMap map[int]string `msg:"loose_map,limit=80"` // Field limit (80) > file limit (50) DefaultSlice []byte `msg:"default_slice"` // No field limit, uses file limit (100) DefaultMap map[string]string `msg:"default_map"` // No field limit, uses file limit (50) } // Test allownil functionality with limits // File limits: arrays:100 maps:50 type AllowNilTestData struct { NilSlice []byte `msg:"nil_slice,allownil"` // Can be nil, uses file limit (100) NilTightSlice []int `msg:"nil_tight_slice,allownil,limit=5"` // Can be nil, field limit (5) < file limit (100) NilLooseSlice []string `msg:"nil_loose_slice,allownil,limit=200"` // Can be nil, field limit (200) > file limit (100) NilZCSlice []byte `msg:"nil_zc_slice,allownil,zerocopy"` // Can be nil, zerocopy, uses file limit (100) NilZCTightSlice []byte `msg:"nil_zc_tight_slice,allownil,zerocopy,limit=5"` // Can be nil, zerocopy, field limit (5) NilMap map[string]int `msg:"nil_map,allownil"` // Can be nil, uses file limit (50) NilTightMap map[string]int `msg:"nil_tight_map,allownil,limit=3"` // Can be nil, field limit (3) < file limit (50) NilLooseMap map[int]string `msg:"nil_loose_map,allownil,limit=75"` // Can be nil, field limit (75) > file limit (50) RegularSlice []byte `msg:"regular_slice"` // Cannot be nil, uses file limit (100) RegularMap map[string]int `msg:"regular_map"` // Cannot be nil, uses file limit (50) ObjSlice []LimitedData `msg:"obj_slice"` // Cannot be nil, uses file limit (100) ObjMap map[string]LimitedData `msg:"obj_map"` // Cannot be nil, uses file limit (50) } type ObjSlices []LimitedData type ObjMaps map[string]LimitedData // Test allownil with zero-sized allocations type AllowNilZeroTestData struct { NilBytes []byte `msg:"nil_bytes,allownil"` // Can be nil, should allocate zero-sized slice RegularBytes []byte `msg:"regular_bytes"` // Cannot be nil } type StandaloneBytesLimited []byte msgp-1.6.1/_generated/limits2.go000066400000000000000000000022021511433505400164710ustar00rootroot00000000000000package _generated //go:generate msgp //msgp:limit arrays:200 maps:100 type LimitTestData2 struct { BigArray [20]int `msg:"big_array"` BigMap map[string]int `msg:"big_map"` } // Test field limits vs file limits precedence with different file limits // File limits: arrays:200 maps:100 type FieldOverrideTestData2 struct { TightSlice []int `msg:"tight_slice,limit=30"` // Field limit (30) < file limit (200) MediumSlice []string `msg:"medium_slice,limit=150"` // Field limit (150) < file limit (200) LooseSlice []byte `msg:"loose_slice,limit=300"` // Field limit (300) > file limit (200) TightMap map[string]int `msg:"tight_map,limit=20"` // Field limit (20) < file limit (100) MediumMap map[int]string `msg:"medium_map,limit=75"` // Field limit (75) < file limit (100) LooseMap map[string][]int `msg:"loose_map,limit=150"` // Field limit (150) > file limit (100) DefaultSlice []int `msg:"default_slice"` // No field limit, uses file limit (200) DefaultMap map[int]int `msg:"default_map"` // No field limit, uses file limit (100) } msgp-1.6.1/_generated/limits_test.go000066400000000000000000001234771511433505400174700ustar00rootroot00000000000000package _generated import ( "bytes" "fmt" "testing" "github.com/tinylib/msgp/msgp" ) func TestSliceLimitEnforcement(t *testing.T) { data := UnlimitedData{} // Test slice limit with DecodeMsg (using big_slice which is []string) t.Run("DecodeMsg_SliceLimit", func(t *testing.T) { buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "big_slice") buf = msgp.AppendArrayHeader(buf, 150) // Exceeds limit of 100 reader := msgp.NewReader(bytes.NewReader(buf)) err := data.DecodeMsg(reader) if err != msgp.ErrLimitExceeded { t.Errorf("Expected ErrLimitExceeded, got %v", err) } }) // Test slice limit with UnmarshalMsg t.Run("UnmarshalMsg_SliceLimit", func(t *testing.T) { buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "big_slice") buf = msgp.AppendArrayHeader(buf, 150) // Exceeds limit of 100 _, err := data.UnmarshalMsg(buf) if err != msgp.ErrLimitExceeded { t.Errorf("Expected ErrLimitExceeded, got %v", err) } }) // Test that slices within limit work fine t.Run("SliceWithinLimit", func(t *testing.T) { buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "big_slice") buf = msgp.AppendArrayHeader(buf, 50) // Within limit for i := 0; i < 50; i++ { buf = msgp.AppendString(buf, "test") } _, err := data.UnmarshalMsg(buf) if err != nil { t.Errorf("Unexpected error for slice within limit: %v", err) } }) } func TestMapLimitEnforcement(t *testing.T) { data := LimitTestData{} // Test map limit with DecodeMsg t.Run("DecodeMsg_MapLimit", func(t *testing.T) { buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "small_map") buf = msgp.AppendMapHeader(buf, 60) // Exceeds limit of 50 reader := msgp.NewReader(bytes.NewReader(buf)) err := data.DecodeMsg(reader) if err != msgp.ErrLimitExceeded { t.Errorf("Expected ErrLimitExceeded, got %v", err) } }) // Test map limit with UnmarshalMsg t.Run("UnmarshalMsg_MapLimit", func(t *testing.T) { buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "small_map") buf = msgp.AppendMapHeader(buf, 60) // Exceeds limit of 50 _, err := data.UnmarshalMsg(buf) if err != msgp.ErrLimitExceeded { t.Errorf("Expected ErrLimitExceeded, got %v", err) } }) // Test that maps within limit work fine t.Run("MapWithinLimit", func(t *testing.T) { buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "small_map") buf = msgp.AppendMapHeader(buf, 3) // Within limit buf = msgp.AppendString(buf, "a") buf = msgp.AppendInt(buf, 1) buf = msgp.AppendString(buf, "b") buf = msgp.AppendInt(buf, 2) buf = msgp.AppendString(buf, "c") buf = msgp.AppendInt(buf, 3) _, err := data.UnmarshalMsg(buf) if err != nil { t.Errorf("Unexpected error for map within limit: %v", err) } }) } func TestFixedArraysNotLimited(t *testing.T) { // Test that fixed arrays are not subject to limits // BigArray [1000]int should work even though 1000 > 100 (array limit) data := UnlimitedData{} t.Run("FixedArray_DecodeMsg", func(t *testing.T) { buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "big_array") buf = msgp.AppendArrayHeader(buf, 1000) // Fixed array size, should not be limited for i := 0; i < 1000; i++ { buf = msgp.AppendInt(buf, i) } reader := msgp.NewReader(bytes.NewReader(buf)) err := data.DecodeMsg(reader) if err != nil { t.Errorf("Fixed arrays should not be limited, got error: %v", err) } }) t.Run("FixedArray_UnmarshalMsg", func(t *testing.T) { buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "big_array") buf = msgp.AppendArrayHeader(buf, 1000) // Fixed array size, should not be limited for i := 0; i < 1000; i++ { buf = msgp.AppendInt(buf, i) } _, err := data.UnmarshalMsg(buf) if err != nil { t.Errorf("Fixed arrays should not be limited, got error: %v", err) } }) } func TestSliceLimitsApplied(t *testing.T) { // Test that dynamic slices are subject to limits data := UnlimitedData{} t.Run("Slice_ExceedsLimit", func(t *testing.T) { buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "big_slice") buf = msgp.AppendArrayHeader(buf, 150) // Exceeds array limit of 100 _, err := data.UnmarshalMsg(buf) if err != msgp.ErrLimitExceeded { t.Errorf("Expected ErrLimitExceeded for slice, got %v", err) } }) t.Run("Slice_WithinLimit", func(t *testing.T) { buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "big_slice") buf = msgp.AppendArrayHeader(buf, 50) // Within array limit of 100 for i := 0; i < 50; i++ { buf = msgp.AppendString(buf, "test") } _, err := data.UnmarshalMsg(buf) if err != nil { t.Errorf("Unexpected error for slice within limit: %v", err) } }) } func TestNestedArrayLimits(t *testing.T) { // Test limits on nested arrays within maps data := UnlimitedData{} t.Run("NestedArray_ExceedsLimit", func(t *testing.T) { buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "big_map") buf = msgp.AppendMapHeader(buf, 1) // Within map limit buf = msgp.AppendString(buf, "key") buf = msgp.AppendArrayHeader(buf, 150) // Nested array exceeds limit of 100 _, err := data.UnmarshalMsg(buf) if err != msgp.ErrLimitExceeded { t.Errorf("Expected ErrLimitExceeded for nested array, got %v", err) } }) t.Run("NestedArray_WithinLimit", func(t *testing.T) { buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "big_map") buf = msgp.AppendMapHeader(buf, 1) // Within map limit buf = msgp.AppendString(buf, "key") buf = msgp.AppendArrayHeader(buf, 50) // Nested array within limit for i := 0; i < 50; i++ { buf = msgp.AppendInt(buf, i) } _, err := data.UnmarshalMsg(buf) if err != nil { t.Errorf("Unexpected error for nested array within limit: %v", err) } }) } func TestMapExceedsLimit(t *testing.T) { data := UnlimitedData{} t.Run("Map_ExceedsLimit", func(t *testing.T) { buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "big_map") buf = msgp.AppendMapHeader(buf, 60) // Exceeds map limit of 50 _, err := data.UnmarshalMsg(buf) if err != msgp.ErrLimitExceeded { t.Errorf("Expected ErrLimitExceeded for map, got %v", err) } }) } func TestStructLevelLimits(t *testing.T) { // Test that the struct-level map limits are enforced data := LimitTestData{} t.Run("StructMap_ExceedsLimit", func(t *testing.T) { // Create a struct with too many fields buf := msgp.AppendMapHeader(nil, 60) // Exceeds map limit of 50 _, err := data.UnmarshalMsg(buf) if err != msgp.ErrLimitExceeded { t.Errorf("Expected ErrLimitExceeded for struct map, got %v", err) } }) } func TestNormalOperationWithinLimits(t *testing.T) { // Test that normal operation works when everything is within limits data := LimitTestData{} // Create valid data data.SmallArray = [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} data.LargeSlice = []byte("test data") data.SmallMap = map[string]int{"a": 1, "b": 2, "c": 3} t.Run("RoundTrip_Marshal_Unmarshal", func(t *testing.T) { // Test MarshalMsg -> UnmarshalMsg buf, err := data.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var result LimitTestData _, err = result.UnmarshalMsg(buf) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } // Verify data integrity if result.SmallArray != data.SmallArray { t.Errorf("SmallArray mismatch: got %v, want %v", result.SmallArray, data.SmallArray) } if !bytes.Equal(result.LargeSlice, data.LargeSlice) { t.Errorf("LargeSlice mismatch: got %v, want %v", result.LargeSlice, data.LargeSlice) } if len(result.SmallMap) != len(data.SmallMap) { t.Errorf("SmallMap length mismatch: got %d, want %d", len(result.SmallMap), len(data.SmallMap)) } }) t.Run("RoundTrip_Encode_Decode", func(t *testing.T) { // Test EncodeMsg -> DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := data.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() var result LimitTestData reader := msgp.NewReader(&buf) err = result.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } // Verify data integrity if result.SmallArray != data.SmallArray { t.Errorf("SmallArray mismatch: got %v, want %v", result.SmallArray, data.SmallArray) } if !bytes.Equal(result.LargeSlice, data.LargeSlice) { t.Errorf("LargeSlice mismatch: got %v, want %v", result.LargeSlice, data.LargeSlice) } if len(result.SmallMap) != len(data.SmallMap) { t.Errorf("SmallMap length mismatch: got %d, want %d", len(result.SmallMap), len(data.SmallMap)) } }) } func TestMarshalLimitEnforcement(t *testing.T) { // Test marshal-time limit enforcement with MarshalLimitTestData // This struct has marshal:true with arrays:30 maps:20 t.Run("MarshalMsg_SliceLimit", func(t *testing.T) { data := MarshalLimitTestData{ TestSlice: make([]string, 40), // Exceeds array limit of 30 } // Fill the slice for i := range data.TestSlice { data.TestSlice[i] = "test" } _, err := data.MarshalMsg(nil) if err == nil { t.Error("Expected error for slice exceeding marshal limit, got nil") } }) t.Run("MarshalMsg_MapLimit", func(t *testing.T) { data := MarshalLimitTestData{ TestMap: make(map[string]int, 25), // Exceeds map limit of 20 } // Fill the map for i := 0; i < 25; i++ { data.TestMap[fmt.Sprintf("key%d", i)] = i } _, err := data.MarshalMsg(nil) if err == nil { t.Error("Expected error for map exceeding marshal limit, got nil") } }) t.Run("EncodeMsg_SliceLimit", func(t *testing.T) { data := MarshalLimitTestData{ TestSlice: make([]string, 40), // Exceeds array limit of 30 } // Fill the slice for i := range data.TestSlice { data.TestSlice[i] = "test" } var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := data.EncodeMsg(writer) if err == nil { t.Error("Expected error for slice exceeding marshal limit, got nil") } }) t.Run("EncodeMsg_MapLimit", func(t *testing.T) { data := MarshalLimitTestData{ TestMap: make(map[string]int, 25), // Exceeds map limit of 20 } // Fill the map for i := 0; i < 25; i++ { data.TestMap[fmt.Sprintf("key%d", i)] = i } var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := data.EncodeMsg(writer) if err == nil { t.Error("Expected error for map exceeding marshal limit, got nil") } }) t.Run("MarshalWithinLimits", func(t *testing.T) { data := MarshalLimitTestData{ SmallArray: [5]int{1, 2, 3, 4, 5}, TestSlice: []string{"a", "b", "c"}, // Within limit of 30 TestMap: map[string]int{"x": 1, "y": 2}, // Within limit of 20 } // Test MarshalMsg _, err := data.MarshalMsg(nil) if err != nil { t.Errorf("Unexpected error for data within marshal limits: %v", err) } // Test EncodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err = data.EncodeMsg(writer) if err != nil { t.Errorf("Unexpected error for data within marshal limits: %v", err) } }) t.Run("FixedArraysNotLimited_Marshal", func(t *testing.T) { // Fixed arrays should not be subject to marshal limits data := MarshalLimitTestData{ SmallArray: [5]int{1, 2, 3, 4, 5}, // Fixed array size } _, err := data.MarshalMsg(nil) if err != nil { t.Errorf("Fixed arrays should not be limited during marshal, got error: %v", err) } }) } func TestFieldLevelLimits(t *testing.T) { // Test field-level limit enforcement with FieldLimitTestData t.Run("SmallSlice_WithinLimit", func(t *testing.T) { data := FieldLimitTestData{ SmallSlice: []int{1, 2, 3}, // Within limit of 5 } // Marshal marshaled, err := data.MarshalMsg(nil) if err != nil { t.Fatalf("Unexpected marshal error: %v", err) } // Unmarshal var result FieldLimitTestData _, err = result.UnmarshalMsg(marshaled) if err != nil { t.Fatalf("Unexpected unmarshal error: %v", err) } if len(result.SmallSlice) != len(data.SmallSlice) { t.Errorf("SmallSlice length mismatch: got %d, want %d", len(result.SmallSlice), len(data.SmallSlice)) } }) t.Run("SmallSlice_ExceedsLimit", func(t *testing.T) { data := FieldLimitTestData{ SmallSlice: []int{1, 2, 3, 4, 5, 6, 7}, // Exceeds limit of 5 } marshaled, err := data.MarshalMsg(nil) if err != nil { t.Fatalf("Unexpected marshal error: %v", err) } // Unmarshal should fail var result FieldLimitTestData _, err = result.UnmarshalMsg(marshaled) if err == nil { t.Error("Expected error for SmallSlice exceeding limit, got nil") } }) t.Run("SmallMap_WithinLimit", func(t *testing.T) { data := FieldLimitTestData{ SmallMap: map[string]int{"a": 1, "b": 2}, // Within limit of 3 } marshaled, err := data.MarshalMsg(nil) if err != nil { t.Fatalf("Unexpected marshal error: %v", err) } var result FieldLimitTestData _, err = result.UnmarshalMsg(marshaled) if err != nil { t.Fatalf("Unexpected unmarshal error: %v", err) } if len(result.SmallMap) != len(data.SmallMap) { t.Errorf("SmallMap length mismatch: got %d, want %d", len(result.SmallMap), len(data.SmallMap)) } }) t.Run("SmallMap_ExceedsLimit", func(t *testing.T) { data := FieldLimitTestData{ SmallMap: map[string]int{"a": 1, "b": 2, "c": 3, "d": 4}, // Exceeds limit of 3 } marshaled, err := data.MarshalMsg(nil) if err != nil { t.Fatalf("Unexpected marshal error: %v", err) } // Unmarshal should fail var result FieldLimitTestData _, err = result.UnmarshalMsg(marshaled) if err == nil { t.Error("Expected error for SmallMap exceeding limit, got nil") } }) t.Run("FixedArrays_NotLimited_Field", func(t *testing.T) { // Fixed arrays should not be subject to field-level limits data := FieldLimitTestData{ FixedArray: [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, // Fixed size, should not be limited } marshaled, err := data.MarshalMsg(nil) if err != nil { t.Fatalf("Unexpected marshal error for fixed array: %v", err) } var result FieldLimitTestData _, err = result.UnmarshalMsg(marshaled) if err != nil { t.Errorf("Fixed arrays should not be limited with field tags, got error: %v", err) } }) t.Run("DecodeMsg_FieldLimits", func(t *testing.T) { data := FieldLimitTestData{ SmallSlice: []int{1, 2, 3, 4, 5, 6}, // Exceeds limit of 5 } marshaled, err := data.MarshalMsg(nil) if err != nil { t.Fatalf("Unexpected marshal error: %v", err) } // Test DecodeMsg path var result FieldLimitTestData reader := msgp.NewReader(bytes.NewReader(marshaled)) err = result.DecodeMsg(reader) if err == nil { t.Error("Expected error for DecodeMsg with field exceeding limit, got nil") } }) } func TestFieldVsFileLimitPrecedence(t *testing.T) { // Test precedence: field limits should override file limits // limits.go has: arrays:100 maps:50 t.Run("TightSlice_FieldOverride", func(t *testing.T) { // File limit: arrays:100, field limit: 10 -> field limit should apply data := FieldOverrideTestData{ TightSlice: make([]int, 15), // Exceeds field limit (10) but within file limit (100) } marshaled, err := data.MarshalMsg(nil) if err != nil { t.Fatalf("Unexpected marshal error: %v", err) } var result FieldOverrideTestData _, err = result.UnmarshalMsg(marshaled) if err == nil { t.Error("Expected error for TightSlice exceeding field limit (10), got nil") } }) t.Run("LooseSlice_FieldOverride", func(t *testing.T) { // File limit: arrays:100, field limit: 200 -> field limit should apply data := FieldOverrideTestData{ LooseSlice: make([]string, 150), // Within field limit (200) but exceeds file limit (100) } for i := range data.LooseSlice { data.LooseSlice[i] = "test" } marshaled, err := data.MarshalMsg(nil) if err != nil { t.Fatalf("Unexpected marshal error: %v", err) } var result FieldOverrideTestData _, err = result.UnmarshalMsg(marshaled) if err != nil { t.Errorf("Expected success for LooseSlice within field limit (200), got error: %v", err) } }) t.Run("DefaultFields_UseFileLimit", func(t *testing.T) { // Fields without field limits should use file limits data := FieldOverrideTestData{ DefaultSlice: make([]byte, 120), // Exceeds file limit (100) } marshaled, err := data.MarshalMsg(nil) if err != nil { t.Fatalf("Unexpected marshal error: %v", err) } var result FieldOverrideTestData _, err = result.UnmarshalMsg(marshaled) if err == nil { t.Error("Expected error for DefaultSlice exceeding file limit (100), got nil") } }) } func TestMarshalFieldVsFileLimitPrecedence(t *testing.T) { // Test precedence with marshal:true // marshal_limits.go has: arrays:30 maps:20 marshal:true t.Run("Marshal_TightSlice_FieldOverride", func(t *testing.T) { // File limit: arrays:30, field limit: 10 -> field limit should apply // Note: Since I only implemented field limits for unmarshal.go, marshal limits won't work yet data := MarshalFieldOverrideTestData{ TightSlice: make([]int, 15), // Exceeds field limit (10) but within file limit (30) } marshaled, err := data.MarshalMsg(nil) if err != nil { t.Fatalf("Unexpected marshal error: %v", err) } var result MarshalFieldOverrideTestData _, err = result.UnmarshalMsg(marshaled) if err == nil { t.Error("Expected error for TightSlice exceeding field limit (10), got nil") } }) t.Run("Marshal_DefaultFields_UseFileLimit", func(t *testing.T) { // Fields without field limits should use file limits data := MarshalFieldOverrideTestData{ DefaultSlice: make([]byte, 35), // Exceeds file limit (30) } marshaled, err := data.MarshalMsg(nil) if err != nil { t.Fatalf("Unexpected marshal error: %v", err) } var result MarshalFieldOverrideTestData _, err = result.UnmarshalMsg(marshaled) if err == nil { t.Error("Expected error for DefaultSlice exceeding file limit (30), got nil") } }) } func TestAliasedTypesWithFieldLimits(t *testing.T) { // Test field-level limits with aliased types t.Run("SmallAliasedSlice_WithinLimit", func(t *testing.T) { data := AliasedFieldLimitTestData{ SmallAliasedSlice: AliasedSlice{"a", "b"}, // Within limit of 3 } marshaled, err := data.MarshalMsg(nil) if err != nil { t.Fatalf("Unexpected marshal error: %v", err) } var result AliasedFieldLimitTestData _, err = result.UnmarshalMsg(marshaled) if err != nil { t.Fatalf("Unexpected unmarshal error: %v", err) } if len(result.SmallAliasedSlice) != len(data.SmallAliasedSlice) { t.Errorf("SmallAliasedSlice length mismatch: got %d, want %d", len(result.SmallAliasedSlice), len(data.SmallAliasedSlice)) } }) t.Run("SmallAliasedSlice_ExceedsLimit", func(t *testing.T) { data := AliasedFieldLimitTestData{ SmallAliasedSlice: AliasedSlice{"a", "b", "c", "d", "e"}, // Exceeds limit of 3 } marshaled, err := data.MarshalMsg(nil) if err != nil { t.Fatalf("Unexpected marshal error: %v", err) } var result AliasedFieldLimitTestData _, err = result.UnmarshalMsg(marshaled) if err == nil { t.Error("Expected error for SmallAliasedSlice exceeding limit (3), got nil") } }) t.Run("SmallAliasedMap_ExceedsLimit", func(t *testing.T) { data := AliasedFieldLimitTestData{ SmallAliasedMap: AliasedMap{ "key1": true, "key2": false, "key3": true, // Exceeds limit of 2 }, } marshaled, err := data.MarshalMsg(nil) if err != nil { t.Fatalf("Unexpected marshal error: %v", err) } var result AliasedFieldLimitTestData _, err = result.UnmarshalMsg(marshaled) if err == nil { t.Error("Expected error for SmallAliasedMap exceeding limit (2), got nil") } }) t.Run("IntSliceAlias_ExceedsLimit", func(t *testing.T) { data := AliasedFieldLimitTestData{ IntSliceAlias: make(AliasedIntSlice, 15), // Exceeds limit of 10 } for i := range data.IntSliceAlias { data.IntSliceAlias[i] = i } marshaled, err := data.MarshalMsg(nil) if err != nil { t.Fatalf("Unexpected marshal error: %v", err) } var result AliasedFieldLimitTestData _, err = result.UnmarshalMsg(marshaled) if err == nil { t.Error("Expected error for IntSliceAlias exceeding limit (10), got nil") } }) t.Run("DecodeMsg_AliasedTypes", func(t *testing.T) { data := AliasedFieldLimitTestData{ SmallAliasedSlice: AliasedSlice{"a", "b", "c", "d"}, // Exceeds limit of 3 } marshaled, err := data.MarshalMsg(nil) if err != nil { t.Fatalf("Unexpected marshal error: %v", err) } // Test DecodeMsg path var result AliasedFieldLimitTestData reader := msgp.NewReader(bytes.NewReader(marshaled)) err = result.DecodeMsg(reader) if err == nil { t.Error("Expected error for DecodeMsg with aliased slice exceeding limit, got nil") } }) } func TestAllowNilFunctionality(t *testing.T) { // Test allownil functionality with DecodeMsg and UnmarshalMsg t.Run("AllowNil_NilValues_DecodeMsg", func(t *testing.T) { data := AllowNilTestData{} // Create message with nil values for allownil fields buf := msgp.AppendMapHeader(nil, 8) // NilSlice - send nil buf = msgp.AppendString(buf, "nil_slice") buf = msgp.AppendNil(buf) // NilTightSlice - send nil buf = msgp.AppendString(buf, "nil_tight_slice") buf = msgp.AppendNil(buf) // NilLooseSlice - send nil buf = msgp.AppendString(buf, "nil_loose_slice") buf = msgp.AppendNil(buf) // NilMap - send nil buf = msgp.AppendString(buf, "nil_map") buf = msgp.AppendNil(buf) // NilTightMap - send nil buf = msgp.AppendString(buf, "nil_tight_map") buf = msgp.AppendNil(buf) // NilLooseMap - send nil buf = msgp.AppendString(buf, "nil_loose_map") buf = msgp.AppendNil(buf) // RegularSlice - send empty slice buf = msgp.AppendString(buf, "regular_slice") buf = msgp.AppendBytes(buf, []byte{}) // RegularMap - send empty map buf = msgp.AppendString(buf, "regular_map") buf = msgp.AppendMapHeader(buf, 0) reader := msgp.NewReader(bytes.NewReader(buf)) err := data.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed with allownil fields: %v", err) } // Verify nil fields are properly handled if data.NilSlice != nil { t.Errorf("Expected NilSlice to be nil, got %v", data.NilSlice) } if data.NilTightSlice != nil { t.Errorf("Expected NilTightSlice to be nil, got %v", data.NilTightSlice) } if data.NilLooseSlice != nil { t.Errorf("Expected NilLooseSlice to be nil, got %v", data.NilLooseSlice) } if data.NilMap != nil { t.Errorf("Expected NilMap to be nil, got %v", data.NilMap) } if data.NilTightMap != nil { t.Errorf("Expected NilTightMap to be nil, got %v", data.NilTightMap) } if data.NilLooseMap != nil { t.Errorf("Expected NilLooseMap to be nil, got %v", data.NilLooseMap) } // Regular fields should be empty but allocated if data.RegularSlice == nil { t.Error("Expected RegularSlice to be allocated (empty), got nil") } if len(data.RegularSlice) != 0 { t.Errorf("Expected RegularSlice to be empty, got length %d", len(data.RegularSlice)) } if data.RegularMap == nil { t.Error("Expected RegularMap to be allocated (empty), got nil") } if len(data.RegularMap) != 0 { t.Errorf("Expected RegularMap to be empty, got length %d", len(data.RegularMap)) } }) t.Run("AllowNil_NilValues_UnmarshalMsg", func(t *testing.T) { data := AllowNilTestData{} // Create same message for unmarshal test buf := msgp.AppendMapHeader(nil, 8) buf = msgp.AppendString(buf, "nil_slice") buf = msgp.AppendNil(buf) buf = msgp.AppendString(buf, "nil_tight_slice") buf = msgp.AppendNil(buf) buf = msgp.AppendString(buf, "nil_loose_slice") buf = msgp.AppendNil(buf) buf = msgp.AppendString(buf, "nil_map") buf = msgp.AppendNil(buf) buf = msgp.AppendString(buf, "nil_tight_map") buf = msgp.AppendNil(buf) buf = msgp.AppendString(buf, "nil_loose_map") buf = msgp.AppendNil(buf) buf = msgp.AppendString(buf, "regular_slice") buf = msgp.AppendBytes(buf, []byte{}) buf = msgp.AppendString(buf, "regular_map") buf = msgp.AppendMapHeader(buf, 0) _, err := data.UnmarshalMsg(buf) if err != nil { t.Fatalf("UnmarshalMsg failed with allownil fields: %v", err) } // Same verification as DecodeMsg test if data.NilSlice != nil { t.Errorf("Expected NilSlice to be nil, got %v", data.NilSlice) } if data.RegularSlice == nil { t.Error("Expected RegularSlice to be allocated (empty), got nil") } }) t.Run("AllowNil_WithData_RespectLimits", func(t *testing.T) { data := AllowNilTestData{} // Test that allownil fields still respect limits when they have data buf := msgp.AppendMapHeader(nil, 3) // NilTightSlice with data exceeding limit (5) buf = msgp.AppendString(buf, "nil_tight_slice") buf = msgp.AppendArrayHeader(buf, 10) // Exceeds field limit of 5 for i := 0; i < 10; i++ { buf = msgp.AppendInt(buf, i) } // NilLooseSlice with data within limit (200) buf = msgp.AppendString(buf, "nil_loose_slice") buf = msgp.AppendArrayHeader(buf, 150) // Within field limit of 200 for i := 0; i < 150; i++ { buf = msgp.AppendString(buf, "test") } // NilTightMap with data exceeding limit (3) buf = msgp.AppendString(buf, "nil_tight_map") buf = msgp.AppendMapHeader(buf, 5) // Exceeds field limit of 3 for i := 0; i < 5; i++ { buf = msgp.AppendString(buf, fmt.Sprintf("key%d", i)) buf = msgp.AppendInt(buf, i) } _, err := data.UnmarshalMsg(buf) if err != msgp.ErrLimitExceeded { t.Errorf("Expected ErrLimitExceeded for allownil field exceeding limit, got %v", err) } }) t.Run("AllowNil_WithData_WithinLimits", func(t *testing.T) { data := AllowNilTestData{} // Test that allownil fields work normally when within limits buf := msgp.AppendMapHeader(nil, 3) // NilTightSlice with data within limit (5) buf = msgp.AppendString(buf, "nil_tight_slice") buf = msgp.AppendArrayHeader(buf, 3) // Within field limit of 5 for i := 0; i < 3; i++ { buf = msgp.AppendInt(buf, i) } // NilSlice with data within file limit (100) buf = msgp.AppendString(buf, "nil_slice") buf = msgp.AppendBytes(buf, make([]byte, 50)) // Within file limit of 100 // NilTightMap with data within limit (3) buf = msgp.AppendString(buf, "nil_tight_map") buf = msgp.AppendMapHeader(buf, 2) // Within field limit of 3 buf = msgp.AppendString(buf, "key1") buf = msgp.AppendInt(buf, 1) buf = msgp.AppendString(buf, "key2") buf = msgp.AppendInt(buf, 2) _, err := data.UnmarshalMsg(buf) if err != nil { t.Fatalf("Unexpected error for allownil fields within limits: %v", err) } // Verify data was properly loaded if len(data.NilTightSlice) != 3 { t.Errorf("Expected NilTightSlice length 3, got %d", len(data.NilTightSlice)) } if len(data.NilSlice) != 50 { t.Errorf("Expected NilSlice length 50, got %d", len(data.NilSlice)) } if len(data.NilTightMap) != 2 { t.Errorf("Expected NilTightMap length 2, got %d", len(data.NilTightMap)) } }) } func TestAllowNilZeroSizedSlices(t *testing.T) { // Test the zero-sized slice allocation behavior t.Run("ZeroSized_NilBytes_DecodeMsg", func(t *testing.T) { data := AllowNilZeroTestData{} // Send zero-sized byte slice buf := msgp.AppendMapHeader(nil, 2) buf = msgp.AppendString(buf, "nil_bytes") buf = msgp.AppendBytes(buf, []byte{}) // Zero-sized bytes buf = msgp.AppendString(buf, "regular_bytes") buf = msgp.AppendBytes(buf, []byte{}) reader := msgp.NewReader(bytes.NewReader(buf)) err := data.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } // Both should be allocated but empty (not nil) if data.NilBytes == nil { t.Error("Expected NilBytes to be allocated (empty), got nil - allownil should allocate zero-sized slice") } if len(data.NilBytes) != 0 { t.Errorf("Expected NilBytes to be empty, got length %d", len(data.NilBytes)) } if data.RegularBytes == nil { t.Error("Expected RegularBytes to be allocated (empty), got nil") } if len(data.RegularBytes) != 0 { t.Errorf("Expected RegularBytes to be empty, got length %d", len(data.RegularBytes)) } }) t.Run("ZeroSized_NilBytes_UnmarshalMsg", func(t *testing.T) { data := AllowNilZeroTestData{} // Same test for unmarshal buf := msgp.AppendMapHeader(nil, 2) buf = msgp.AppendString(buf, "nil_bytes") buf = msgp.AppendBytes(buf, []byte{}) buf = msgp.AppendString(buf, "regular_bytes") buf = msgp.AppendBytes(buf, []byte{}) _, err := data.UnmarshalMsg(buf) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } // Verify zero-sized allocation if data.NilBytes == nil { t.Error("Expected NilBytes to be allocated (empty), got nil - allownil should allocate zero-sized slice") } if len(data.NilBytes) != 0 { t.Errorf("Expected NilBytes to be empty, got length %d", len(data.NilBytes)) } }) t.Run("ActualNil_vs_ZeroSized", func(t *testing.T) { data1 := AllowNilZeroTestData{} data2 := AllowNilZeroTestData{} // Test 1: Send actual nil buf1 := msgp.AppendMapHeader(nil, 1) buf1 = msgp.AppendString(buf1, "nil_bytes") buf1 = msgp.AppendNil(buf1) // Test 2: Send zero-sized slice buf2 := msgp.AppendMapHeader(nil, 1) buf2 = msgp.AppendString(buf2, "nil_bytes") buf2 = msgp.AppendBytes(buf2, []byte{}) _, err1 := data1.UnmarshalMsg(buf1) if err1 != nil { t.Fatalf("UnmarshalMsg with nil failed: %v", err1) } _, err2 := data2.UnmarshalMsg(buf2) if err2 != nil { t.Fatalf("UnmarshalMsg with zero-sized failed: %v", err2) } // data1 received actual nil - should remain nil for allownil field if data1.NilBytes != nil { t.Errorf("Expected data1.NilBytes (from nil) to remain nil, got %v", data1.NilBytes) } // data2 received zero-sized slice - should be allocated empty slice if data2.NilBytes == nil { t.Error("Expected data2.NilBytes (from zero-sized) to be allocated, got nil") } // Both should be empty if len(data1.NilBytes) != 0 { t.Errorf("Expected data1.NilBytes length 0, got %d", len(data1.NilBytes)) } if len(data2.NilBytes) != 0 { t.Errorf("Expected data2.NilBytes length 0, got %d", len(data2.NilBytes)) } }) } func TestAllowNilSecurityLimits(t *testing.T) { // Test that allownil fields still enforce security limits properly t.Run("AllowNil_BytesExceedLimit_UnmarshalMsg", func(t *testing.T) { data := AllowNilTestData{} // Try to send bytes that exceed file limit (100) buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "nil_slice") // Uses file limit (100) buf = msgp.AppendBytes(buf, make([]byte, 150)) // Exceeds limit _, err := data.UnmarshalMsg(buf) if err != msgp.ErrLimitExceeded { t.Errorf("Expected ErrLimitExceeded for allownil bytes exceeding limit, got %v", err) } }) t.Run("AllowNil_BytesExceedLimit_DecodeMsg", func(t *testing.T) { data := AllowNilTestData{} // Try to send bytes that exceed file limit (100) buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "nil_slice") // Uses file limit (100) buf = msgp.AppendBytes(buf, make([]byte, 150)) // Exceeds limit reader := msgp.NewReader(bytes.NewReader(buf)) err := data.DecodeMsg(reader) if err != msgp.ErrLimitExceeded { t.Errorf("Expected ErrLimitExceeded for allownil bytes exceeding limit, got %v", err) } }) t.Run("AllowNil_SliceExceedFieldLimit_UnmarshalMsg", func(t *testing.T) { data := AllowNilTestData{} // Try to send slice that exceeds field limit buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "nil_tight_slice") // Field limit = 5 buf = msgp.AppendArrayHeader(buf, 8) // Exceeds field limit for i := 0; i < 8; i++ { buf = msgp.AppendInt(buf, i) } _, err := data.UnmarshalMsg(buf) if err != msgp.ErrLimitExceeded { t.Errorf("Expected ErrLimitExceeded for allownil slice exceeding field limit, got %v", err) } }) t.Run("AllowNil_SliceExceedFieldLimit_DecodeMsg", func(t *testing.T) { data := AllowNilTestData{} // Try to send slice that exceeds field limit buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "nil_tight_slice") // Field limit = 5 buf = msgp.AppendArrayHeader(buf, 8) // Exceeds field limit for i := 0; i < 8; i++ { buf = msgp.AppendInt(buf, i) } reader := msgp.NewReader(bytes.NewReader(buf)) err := data.DecodeMsg(reader) if err != msgp.ErrLimitExceeded { t.Errorf("Expected ErrLimitExceeded for allownil slice exceeding field limit, got %v", err) } }) t.Run("AllowNil_MapExceedFieldLimit_UnmarshalMsg", func(t *testing.T) { data := AllowNilTestData{} // Try to send map that exceeds field limit buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "nil_tight_map") // Field limit = 3 buf = msgp.AppendMapHeader(buf, 5) // Exceeds field limit for i := 0; i < 5; i++ { buf = msgp.AppendString(buf, fmt.Sprintf("key%d", i)) buf = msgp.AppendInt(buf, i) } _, err := data.UnmarshalMsg(buf) if err != msgp.ErrLimitExceeded { t.Errorf("Expected ErrLimitExceeded for allownil map exceeding field limit, got %v", err) } }) t.Run("AllowNil_MapExceedFieldLimit_DecodeMsg", func(t *testing.T) { data := AllowNilTestData{} // Try to send map that exceeds field limit buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "nil_tight_map") // Field limit = 3 buf = msgp.AppendMapHeader(buf, 5) // Exceeds field limit for i := 0; i < 5; i++ { buf = msgp.AppendString(buf, fmt.Sprintf("key%d", i)) buf = msgp.AppendInt(buf, i) } reader := msgp.NewReader(bytes.NewReader(buf)) err := data.DecodeMsg(reader) if err != msgp.ErrLimitExceeded { t.Errorf("Expected ErrLimitExceeded for allownil map exceeding field limit, got %v", err) } }) t.Run("AllowNil_HeaderFirstSecurity_UnmarshalMsg", func(t *testing.T) { // Verify that allownil still uses header-first security approach data := AllowNilTestData{} // Create a message that would cause memory exhaustion if read data-first // This test ensures that even allownil fields check limits before allocation buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "nil_slice") // Manually craft a message with a huge size header but don't include the data // This should fail at the limit check, not during data reading buf = append(buf, 0xc6) // bin32 format buf = append(buf, 0x00, 0x00, 0x27, 0x10) // size = 10000 (exceeds limit of 100) // Don't append actual data - should fail before trying to read it _, err := data.UnmarshalMsg(buf) if err != msgp.ErrLimitExceeded { t.Errorf("Expected ErrLimitExceeded (header-first check), got %v", err) } }) t.Run("AllowNil_HeaderFirstSecurity_DecodeMsg", func(t *testing.T) { // Verify that allownil still uses header-first security approach with DecodeMsg data := AllowNilTestData{} // Create a message that would cause memory exhaustion if read data-first // This test ensures that even allownil fields check limits before allocation buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "nil_slice") // Manually craft a message with a huge size header but don't include the data // This should fail at the limit check, not during data reading buf = append(buf, 0xc6) // bin32 format buf = append(buf, 0x00, 0x00, 0x27, 0x10) // size = 10000 (exceeds limit of 100) // Don't append actual data - should fail before trying to read it reader := msgp.NewReader(bytes.NewReader(buf)) err := data.DecodeMsg(reader) if err != msgp.ErrLimitExceeded { t.Errorf("Expected ErrLimitExceeded (header-first check), got %v", err) } }) } func TestAllowNilZeroCopy(t *testing.T) { // Test that zerocopy+allownil combination works correctly with security fixes t.Run("ZeroCopy_AllowNil_NilValues_UnmarshalMsg", func(t *testing.T) { data := AllowNilTestData{} // Create message with nil for zerocopy+allownil field buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "nil_zc_slice") buf = msgp.AppendNil(buf) _, err := data.UnmarshalMsg(buf) if err != nil { t.Fatalf("UnmarshalMsg failed with zerocopy allownil nil value: %v", err) } // Field should remain nil if data.NilZCSlice != nil { t.Errorf("Expected NilZCSlice to remain nil, got %v", data.NilZCSlice) } }) t.Run("ZeroCopy_AllowNil_EmptyData_UnmarshalMsg", func(t *testing.T) { data := AllowNilTestData{} // Create message with empty data for zerocopy+allownil field buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "nil_zc_slice") buf = msgp.AppendBytes(buf, []byte{}) _, err := data.UnmarshalMsg(buf) if err != nil { t.Fatalf("UnmarshalMsg failed with zerocopy allownil empty data: %v", err) } // Field should be allocated but empty if data.NilZCSlice == nil { t.Error("Expected NilZCSlice to be allocated (empty), got nil") } if len(data.NilZCSlice) != 0 { t.Errorf("Expected NilZCSlice to be empty, got length %d", len(data.NilZCSlice)) } }) t.Run("ZeroCopy_AllowNil_WithData_UnmarshalMsg", func(t *testing.T) { data := AllowNilTestData{} testData := []byte{1, 2, 3, 4, 5} // Create message with actual data for zerocopy+allownil field buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "nil_zc_slice") buf = msgp.AppendBytes(buf, testData) originalBuf := make([]byte, len(buf)) copy(originalBuf, buf) _, err := data.UnmarshalMsg(buf) if err != nil { t.Fatalf("UnmarshalMsg failed with zerocopy allownil data: %v", err) } // Field should contain the data if data.NilZCSlice == nil { t.Error("Expected NilZCSlice to be allocated, got nil") } if len(data.NilZCSlice) != len(testData) { t.Errorf("Expected NilZCSlice length %d, got %d", len(testData), len(data.NilZCSlice)) } for i, b := range testData { if data.NilZCSlice[i] != b { t.Errorf("Expected NilZCSlice[%d] = %d, got %d", i, b, data.NilZCSlice[i]) } } }) t.Run("ZeroCopy_AllowNil_SecurityLimits_UnmarshalMsg", func(t *testing.T) { data := AllowNilTestData{} // Test that zerocopy+allownil still enforces limits buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "nil_zc_tight_slice") // Field limit = 5 // Create oversized data that should exceed field limit oversizedData := make([]byte, 10) // Exceeds field limit of 5 buf = msgp.AppendBytes(buf, oversizedData) _, err := data.UnmarshalMsg(buf) if err != msgp.ErrLimitExceeded { t.Errorf("Expected ErrLimitExceeded for zerocopy allownil field exceeding limit, got %v", err) } }) t.Run("ZeroCopy_AllowNil_HeaderFirstSecurity_UnmarshalMsg", func(t *testing.T) { data := AllowNilTestData{} // Test header-first security for zerocopy+allownil buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "nil_zc_slice") // Manually craft message with huge header but no data buf = append(buf, 0xc6) // bin32 format buf = append(buf, 0x00, 0x00, 0x27, 0x10) // size = 10000 (exceeds limit) _, err := data.UnmarshalMsg(buf) if err != msgp.ErrLimitExceeded { t.Errorf("Expected ErrLimitExceeded (header-first check) for zerocopy allownil, got %v", err) } }) // Add DecodeMsg versions for complete coverage t.Run("ZeroCopy_AllowNil_NilValues_DecodeMsg", func(t *testing.T) { data := AllowNilTestData{} // Create message with nil for zerocopy+allownil field buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "nil_zc_slice") buf = msgp.AppendNil(buf) reader := msgp.NewReader(bytes.NewReader(buf)) err := data.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed with zerocopy allownil nil value: %v", err) } // Field should remain nil if data.NilZCSlice != nil { t.Errorf("Expected NilZCSlice to remain nil, got %v", data.NilZCSlice) } }) t.Run("ZeroCopy_AllowNil_EmptyData_DecodeMsg", func(t *testing.T) { data := AllowNilTestData{} // Create message with empty data for zerocopy+allownil field buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "nil_zc_slice") buf = msgp.AppendBytes(buf, []byte{}) reader := msgp.NewReader(bytes.NewReader(buf)) err := data.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed with zerocopy allownil empty data: %v", err) } // Field should be allocated but empty if data.NilZCSlice == nil { t.Error("Expected NilZCSlice to be allocated (empty), got nil") } if len(data.NilZCSlice) != 0 { t.Errorf("Expected NilZCSlice to be empty, got length %d", len(data.NilZCSlice)) } }) t.Run("ZeroCopy_AllowNil_WithData_DecodeMsg", func(t *testing.T) { data := AllowNilTestData{} testData := []byte{1, 2, 3, 4, 5} // Create message with actual data for zerocopy+allownil field buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "nil_zc_slice") buf = msgp.AppendBytes(buf, testData) reader := msgp.NewReader(bytes.NewReader(buf)) err := data.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed with zerocopy allownil data: %v", err) } // Field should contain the data if data.NilZCSlice == nil { t.Error("Expected NilZCSlice to be allocated, got nil") } if len(data.NilZCSlice) != len(testData) { t.Errorf("Expected NilZCSlice length %d, got %d", len(testData), len(data.NilZCSlice)) } for i, b := range testData { if data.NilZCSlice[i] != b { t.Errorf("Expected NilZCSlice[%d] = %d, got %d", i, b, data.NilZCSlice[i]) } } }) t.Run("ZeroCopy_AllowNil_SecurityLimits_DecodeMsg", func(t *testing.T) { data := AllowNilTestData{} // Test that zerocopy+allownil still enforces limits buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "nil_zc_tight_slice") // Field limit = 5 // Create oversized data that should exceed field limit oversizedData := make([]byte, 10) // Exceeds field limit of 5 buf = msgp.AppendBytes(buf, oversizedData) reader := msgp.NewReader(bytes.NewReader(buf)) err := data.DecodeMsg(reader) if err != msgp.ErrLimitExceeded { t.Errorf("Expected ErrLimitExceeded for zerocopy allownil field exceeding limit, got %v", err) } }) t.Run("ZeroCopy_AllowNil_HeaderFirstSecurity_DecodeMsg", func(t *testing.T) { data := AllowNilTestData{} // Test header-first security for zerocopy+allownil buf := msgp.AppendMapHeader(nil, 1) buf = msgp.AppendString(buf, "nil_zc_slice") // Manually craft message with huge header but no data buf = append(buf, 0xc6) // bin32 format buf = append(buf, 0x00, 0x00, 0x27, 0x10) // size = 10000 (exceeds limit) reader := msgp.NewReader(bytes.NewReader(buf)) err := data.DecodeMsg(reader) if err != msgp.ErrLimitExceeded { t.Errorf("Expected ErrLimitExceeded (header-first check) for zerocopy allownil, got %v", err) } }) } msgp-1.6.1/_generated/map_autoshim.go000066400000000000000000000026151511433505400176040ustar00rootroot00000000000000package _generated //go:generate msgp -v //msgp:maps autoshim //msgp:replace ExternalString with:string //msgp:replace ExternalInt with:int type MyMapKeyStruct3 struct { MapString map[string]int `msg:",allownil"` MapString3 map[ExternalString]int `msg:",allownil"` MapString2 map[ExternalInt]int `msg:",allownil"` MapFloat32 map[float32]int `msg:",allownil"` MapFloat64 map[float64]int `msg:",allownil"` MapUint map[uint]int `msg:",allownil"` MapUint8 map[uint8]int `msg:",allownil"` MapUint16 map[uint16]int `msg:",allownil"` MapUint32 map[uint32]int `msg:",allownil"` MapUint64 map[uint64]int `msg:",allownil"` MapByte map[byte]int `msg:",allownil"` MapInt map[int]int `msg:",allownil"` MapInt8 map[int8]int `msg:",allownil"` MapInt16 map[int16]int `msg:",allownil"` MapInt32 map[int32]int `msg:",allownil"` MapInt64 map[int64]int `msg:",allownil"` MapBool map[bool]int `msg:",allownil"` MapMapInt map[int]map[int]int `msg:",allownil"` // Maps with unsupported base types. MapArray map[[4]byte]int `msg:",allownil"` // Ignored MapArray4 map[[4]uint32]int `msg:",allownil"` // Ignored MapComplex64 map[complex64]int `msg:",allownil"` // Ignored MapComplex128 map[complex128]int `msg:",allownil"` // Ignored } msgp-1.6.1/_generated/map_autoshim_test.go000066400000000000000000000073361511433505400206500ustar00rootroot00000000000000package _generated import ( "bytes" "math" "math/rand/v2" "reflect" "strconv" "testing" "github.com/tinylib/msgp/msgp" ) func TestAutoShimKeys(t *testing.T) { rng := rand.New(rand.NewPCG(0, 0)) // Generate a bunch of random maps for i := range 500 { var test MyMapKeyStruct3 if i != 0 { // Don't add anything to the first object test.MapString = make(map[string]int) test.MapString2 = make(map[ExternalInt]int) test.MapString3 = make(map[ExternalString]int) test.MapFloat32 = make(map[float32]int) test.MapFloat64 = make(map[float64]int) test.MapUint = make(map[uint]int) test.MapUint8 = make(map[uint8]int) test.MapUint16 = make(map[uint16]int) test.MapUint32 = make(map[uint32]int) test.MapUint64 = make(map[uint64]int) test.MapByte = make(map[byte]int) test.MapInt = make(map[int]int) test.MapInt8 = make(map[int8]int) test.MapInt16 = make(map[int16]int) test.MapInt32 = make(map[int32]int) test.MapInt64 = make(map[int64]int) test.MapBool = make(map[bool]int) test.MapMapInt = make(map[int]map[int]int) for range rng.IntN(50) { test.MapString[string(strconv.Itoa(rng.IntN(math.MaxInt32)))] = rng.IntN(100) } for range rng.IntN(50) { test.MapString3[ExternalString(strconv.Itoa(rng.IntN(math.MaxInt32)))] = rng.IntN(100) } for range rng.IntN(50) { test.MapString2[ExternalInt(rng.IntN(math.MaxInt32))] = rng.IntN(100) } for range rng.IntN(50) { test.MapFloat32[float32(rng.Float32())] = rng.IntN(100) } for range rng.IntN(50) { test.MapFloat64[rng.Float64()] = rng.IntN(100) } for range rng.IntN(50) { test.MapUint[uint(rng.Uint64())] = rng.IntN(100) } for range rng.IntN(50) { test.MapUint8[uint8(rng.Uint64())] = rng.IntN(100) } for range rng.IntN(50) { test.MapUint16[uint16(rng.Uint64())] = rng.IntN(100) } for range rng.IntN(50) { test.MapUint32[rng.Uint32()] = rng.IntN(100) } for range rng.IntN(50) { test.MapUint64[rng.Uint64()] = rng.IntN(100) } for range rng.IntN(50) { test.MapByte[byte(uint8(rng.Uint64()))] = rng.IntN(100) } for range rng.IntN(50) { test.MapInt[rng.IntN(math.MaxInt32)] = rng.IntN(100) } for range rng.IntN(50) { test.MapInt8[int8(rng.IntN(int(math.MaxInt8)+1))] = rng.IntN(100) } for range rng.IntN(50) { test.MapInt16[int16(rng.IntN(int(math.MaxInt16)+1))] = rng.IntN(100) } for range rng.IntN(50) { test.MapInt32[int32(rng.IntN(int(math.MaxInt32)))] = rng.IntN(100) } for range rng.IntN(50) { // Use only non-negative values to stay within IntN capabilities test.MapInt64[int64(rng.IntN(int(math.MaxInt32)))] = rng.IntN(100) } if rng.IntN(2) == 0 { test.MapBool[true] = rng.IntN(100) } if rng.IntN(2) == 0 { test.MapBool[false] = rng.IntN(100) } for range rng.IntN(50) { dst := make(map[int]int, 50) test.MapMapInt[rng.Int()] = dst for range rng.IntN(50) { dst[rng.Int()] = rng.IntN(100) } } } var encoded [][]byte b, err := test.MarshalMsg(nil) if err != nil { t.Fatal(err) } encoded = append(encoded, b) var buf bytes.Buffer en := msgp.NewWriter(&buf) err = test.EncodeMsg(en) if err != nil { t.Fatal(err) } err = en.Flush() if err != nil { t.Fatal(err) } encoded = append(encoded, buf.Bytes()) for _, enc := range encoded { var decoded, decoded2 MyMapKeyStruct3 _, err = decoded.UnmarshalMsg(enc) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(&decoded, &test) { t.Errorf("decoded != test") } dec := msgp.NewReader(bytes.NewReader(enc)) err = decoded2.DecodeMsg(dec) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(&decoded2, &test) { t.Errorf("decoded2 != test") } } } } msgp-1.6.1/_generated/map_bin_key.go000066400000000000000000000045431511433505400173750ustar00rootroot00000000000000package _generated import ( "encoding/hex" "time" ) //go:generate msgp -unexported -v //msgp:maps binkeys type ArrayMapKey [4]byte //msgp:replace ExternalArr with:[4]byte //msgp:replace ExternalString with:string type mapKeyBytes2 [8]byte //msgp:shim mapKeyBytes2 as:string using:hexEncode2/hexDecode2 witherr:false type mapKeyShimmed time.Duration //msgp:shim mapKeyShimmed as:[]byte using:durEncode/durDecode witherr:true type MyStringType string type MyMapKeyStruct2 struct { MapString map[string]int `msg:",allownil"` MapString2 map[MyStringType]int `msg:",allownil"` MapString3 map[ExternalString]int `msg:",allownil"` MapString4 map[mapKeyBytes2]int `msg:",allownil"` MapFloat32 map[float32]int `msg:",allownil"` MapFloat64 map[float64]int `msg:",allownil"` MapComplex64 map[complex64]int `msg:",allownil"` MapComplex128 map[complex128]int `msg:",allownil"` MapUint map[uint]int `msg:",allownil"` MapUint8 map[uint8]int `msg:",allownil"` MapUint16 map[uint16]int `msg:",allownil"` MapUint32 map[uint32]int `msg:",allownil"` MapUint64 map[uint64]int `msg:",allownil"` MapByte map[byte]int `msg:",allownil"` MapInt map[int]int `msg:",allownil"` MapInt8 map[int8]int `msg:",allownil"` MapInt16 map[int16]int `msg:",allownil"` MapInt32 map[int32]int `msg:",allownil"` MapInt64 map[int64]int `msg:",allownil"` MapBool map[bool]int `msg:",allownil"` MapMapInt map[int]map[int]int `msg:",allownil"` // Maps with array keys MapArray map[[4]byte]int `msg:",allownil"` MapArray2 map[ArrayMapKey]int `msg:",allownil"` MapArray3 map[ExternalArr]int `msg:",allownil"` MapArray4 map[[4]uint32]int `msg:",allownil"` // Maps with shimmed types MapDuration map[mapKeyShimmed]int `msg:",allownil"` } func hexEncode2(b mapKeyBytes2) string { return hex.EncodeToString(b[:]) } func hexDecode2(s string) mapKeyBytes2 { var b [8]byte _, err := hex.Decode(b[:], []byte(s)) if err != nil { panic(err) } return b } func durEncode(v mapKeyShimmed) []byte { return []byte(time.Duration(v).String()) } func durDecode(b []byte) (mapKeyShimmed, error) { v, err := time.ParseDuration(string(b)) return mapKeyShimmed(v), err } msgp-1.6.1/_generated/map_bin_key_test.go000066400000000000000000000120211511433505400204220ustar00rootroot00000000000000package _generated import ( "bytes" "math" "math/rand/v2" "reflect" "strconv" "testing" "github.com/tinylib/msgp/msgp" ) func TestBinKeys(t *testing.T) { rng := rand.New(rand.NewPCG(0, 0)) // Generate a bunch of random maps for i := range 500 { var test MyMapKeyStruct2 if i != 0 { // Don't add anything to the first object test.MapString = make(map[string]int) test.MapString2 = make(map[MyStringType]int) test.MapString3 = make(map[ExternalString]int) test.MapFloat32 = make(map[float32]int) test.MapFloat64 = make(map[float64]int) test.MapComplex64 = make(map[complex64]int) test.MapComplex128 = make(map[complex128]int) test.MapUint = make(map[uint]int) test.MapUint8 = make(map[uint8]int) test.MapUint16 = make(map[uint16]int) test.MapUint32 = make(map[uint32]int) test.MapUint64 = make(map[uint64]int) test.MapByte = make(map[byte]int) test.MapInt = make(map[int]int) test.MapInt8 = make(map[int8]int) test.MapInt16 = make(map[int16]int) test.MapInt32 = make(map[int32]int) test.MapInt64 = make(map[int64]int) test.MapBool = make(map[bool]int) test.MapArray = make(map[[4]byte]int) test.MapArray2 = make(map[ArrayMapKey]int) test.MapArray3 = make(map[ExternalArr]int) test.MapArray4 = make(map[[4]uint32]int) test.MapDuration = make(map[mapKeyShimmed]int) test.MapMapInt = make(map[int]map[int]int) for range rng.IntN(50) { test.MapString[string(strconv.Itoa(rng.IntN(math.MaxInt32)))] = rng.IntN(100) } for range rng.IntN(50) { test.MapString2[MyStringType(strconv.Itoa(rng.IntN(math.MaxInt32)))] = rng.IntN(100) } for range rng.IntN(50) { test.MapString3[ExternalString(strconv.Itoa(rng.IntN(math.MaxInt32)))] = rng.IntN(100) } for range rng.IntN(50) { test.MapFloat32[float32(rng.Float32())] = rng.IntN(100) } for range rng.IntN(50) { test.MapFloat64[rng.Float64()] = rng.IntN(100) } for range rng.IntN(50) { c := complex(float32(rng.Float32()), float32(rng.Float32())) test.MapComplex64[c] = rng.IntN(100) } for range rng.IntN(50) { c := complex(rng.Float64(), rng.Float64()) test.MapComplex128[c] = rng.IntN(100) } for range rng.IntN(50) { test.MapUint[uint(rng.Uint64())] = rng.IntN(100) } for range rng.IntN(50) { test.MapUint8[uint8(rng.Uint64())] = rng.IntN(100) } for range rng.IntN(50) { test.MapUint16[uint16(rng.Uint64())] = rng.IntN(100) } for range rng.IntN(50) { test.MapUint32[rng.Uint32()] = rng.IntN(100) } for range rng.IntN(50) { test.MapUint64[rng.Uint64()] = rng.IntN(100) } for range rng.IntN(50) { test.MapByte[byte(uint8(rng.Uint64()))] = rng.IntN(100) } for range rng.IntN(50) { test.MapInt[rng.IntN(math.MaxInt32)] = rng.IntN(100) } for range rng.IntN(50) { test.MapInt8[int8(rng.IntN(int(math.MaxInt8)+1))] = rng.IntN(100) } for range rng.IntN(50) { test.MapInt16[int16(rng.IntN(int(math.MaxInt16)+1))] = rng.IntN(100) } for range rng.IntN(50) { test.MapInt32[int32(rng.IntN(int(math.MaxInt32)))] = rng.IntN(100) } for range rng.IntN(50) { // Use only non-negative values to stay within IntN capabilities test.MapInt64[int64(rng.IntN(int(math.MaxInt32)))] = rng.IntN(100) } if rng.IntN(2) == 0 { test.MapBool[true] = rng.IntN(100) } if rng.IntN(2) == 0 { test.MapBool[false] = rng.IntN(100) } for range rng.IntN(50) { var k [4]byte for i := 0; i < 4; i++ { k[i] = uint8(rng.Uint64()) } test.MapArray[k] = rng.IntN(100) } for range rng.IntN(50) { var k ArrayMapKey for i := 0; i < 4; i++ { k[i] = uint8(rng.Uint64()) } test.MapArray2[k] = rng.IntN(100) } for range rng.IntN(50) { var k ExternalArr for i := 0; i < 4; i++ { k[i] = uint8(rng.Uint64()) } test.MapArray3[k] = rng.IntN(100) } for range rng.IntN(50) { var k [4]uint32 for i := 0; i < 4; i++ { k[i] = rng.Uint32() } test.MapArray4[k] = rng.IntN(100) } for range rng.IntN(50) { test.MapDuration[mapKeyShimmed(rng.IntN(math.MaxInt32))] = rng.IntN(100) } for range rng.IntN(50) { dst := make(map[int]int, 50) test.MapMapInt[rng.Int()] = dst for range rng.IntN(50) { dst[rng.Int()] = rng.IntN(100) } } } var encoded [][]byte b, err := test.MarshalMsg(nil) if err != nil { t.Fatal(err) } encoded = append(encoded, b) var buf bytes.Buffer en := msgp.NewWriter(&buf) err = test.EncodeMsg(en) if err != nil { t.Fatal(err) } err = en.Flush() if err != nil { t.Fatal(err) } encoded = append(encoded, buf.Bytes()) for _, enc := range encoded { var decoded, decoded2 MyMapKeyStruct2 _, err = decoded.UnmarshalMsg(enc) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(&decoded, &test) { t.Errorf("decoded != test") } dec := msgp.NewReader(bytes.NewReader(enc)) err = decoded2.DecodeMsg(dec) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(&decoded2, &test) { t.Errorf("decoded2 != test") } } } } msgp-1.6.1/_generated/map_shim_key.go000066400000000000000000000045411511433505400175630ustar00rootroot00000000000000package _generated import ( "encoding/hex" "strconv" ) //go:generate msgp -unexported -v //msgp:maps shim //msgp:shim mapKey as:string using:mapKeyToString/stringToMapKey witherr:true type mapKey uint64 type mapKeyString string //msgp:shim mapKeyBytes as:string using:hexEncode/hexDecode witherr:false type mapKeyBytes [8]byte //msgp:replace ExternalString with:string type MyMapKeyStruct struct { Map map[mapKey]int `msg:",allownil"` // Keys are converted to strings via shim MapS map[mapKeyString]int `msg:",allownil"` // Keys are strings, with conversion MapX map[ExternalString]int `msg:",allownil"` // Keys is an external type to the file, replaced with a cast MapB map[mapKeyBytes]int `msg:",allownil"` // Keys are bytes, converted to hex strings via shim MapUint map[uint64]int `msg:",allownil"` // Will be ignored (as current behavior) Original map[string]int `msg:",allownil"` // Original map, for comparison purposes // Should all be ignored: MapFloat32 map[float32]int `msg:",allownil"` MapFloat64 map[float64]int `msg:",allownil"` MapComplex64 map[complex64]int `msg:",allownil"` MapComplex128 map[complex128]int `msg:",allownil"` MapUint2 map[uint]int `msg:",allownil"` MapUint8 map[uint8]int `msg:",allownil"` MapUint16 map[uint16]int `msg:",allownil"` MapUint32 map[uint32]int `msg:",allownil"` MapUint64 map[uint64]int `msg:",allownil"` MapByte map[byte]int `msg:",allownil"` MapInt map[int]int `msg:",allownil"` MapInt8 map[int8]int `msg:",allownil"` MapInt16 map[int16]int `msg:",allownil"` MapInt32 map[int32]int `msg:",allownil"` MapInt64 map[int64]int `msg:",allownil"` MapBool map[bool]int `msg:",allownil"` } // stringToMapKey and mapKeyToString are shim functions that convert between // mapKey and string. func stringToMapKey(s string) (mapKey, error) { v, err := strconv.ParseUint(s, 10, 64) if err != nil { return 0, err } return mapKey(v), nil } func mapKeyToString(k mapKey) string { return strconv.FormatUint(uint64(k), 10) } func hexEncode(b mapKeyBytes) string { return hex.EncodeToString(b[:]) } func hexDecode(s string) mapKeyBytes { var b [8]byte _, err := hex.Decode(b[:], []byte(s)) if err != nil { panic(err) } return b } msgp-1.6.1/_generated/map_shim_key_test.go000066400000000000000000000033771511433505400206300ustar00rootroot00000000000000package _generated import ( "bytes" "encoding/binary" "math" "math/rand/v2" "reflect" "strconv" "testing" "github.com/tinylib/msgp/msgp" ) func TestShimmedKeys(t *testing.T) { rng := rand.New(rand.NewPCG(0, 0)) // Generate a bunch of random maps for i := range 500 { var test MyMapKeyStruct if i != 0 { // Don't add anything to the first object test.Map = make(map[mapKey]int) test.MapS = make(map[mapKeyString]int) test.MapX = make(map[ExternalString]int) test.MapB = make(map[mapKeyBytes]int) for range rng.IntN(50) { test.Map[mapKey(rng.IntN(math.MaxInt32))] = rng.IntN(100) } for range rng.IntN(50) { test.MapS[mapKeyString(strconv.Itoa(rng.IntN(math.MaxInt32)))] = rng.IntN(100) } for range rng.IntN(50) { test.MapX[ExternalString(strconv.Itoa(rng.IntN(math.MaxInt32)))] = rng.IntN(100) } for range rng.IntN(50) { var tmp [8]byte binary.LittleEndian.PutUint64(tmp[:], rng.Uint64()) test.MapB[tmp] = rng.IntN(100) } } var encoded [][]byte b, err := test.MarshalMsg(nil) if err != nil { t.Fatal(err) } encoded = append(encoded, b) var buf bytes.Buffer en := msgp.NewWriter(&buf) err = test.EncodeMsg(en) if err != nil { t.Fatal(err) } err = en.Flush() if err != nil { t.Fatal(err) } encoded = append(encoded, buf.Bytes()) for _, enc := range encoded { var decoded, decoded2 MyMapKeyStruct _, err = decoded.UnmarshalMsg(enc) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(&decoded, &test) { t.Errorf("decoded != test") } dec := msgp.NewReader(bytes.NewReader(enc)) err = decoded2.DecodeMsg(dec) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(&decoded2, &test) { t.Errorf("decoded2 != test") } } } } msgp-1.6.1/_generated/marshal_limits.go000066400000000000000000000020541511433505400201230ustar00rootroot00000000000000//msgp:limit arrays:30 maps:20 marshal:true package _generated //go:generate msgp // Test structures for marshal-time limit enforcement type MarshalLimitTestData struct { SmallArray [5]int `msg:"small_array"` TestSlice []string `msg:"test_slice"` TestMap map[string]int `msg:"test_map"` } // Test field limits vs file limits precedence with marshal:true // File limits: arrays:30 maps:20 marshal:true type MarshalFieldOverrideTestData struct { TightSlice []int `msg:"tight_slice,limit=10"` // Field limit (10) < file limit (30) LooseSlice []string `msg:"loose_slice,limit=50"` // Field limit (50) > file limit (30) TightMap map[string]int `msg:"tight_map,limit=5"` // Field limit (5) < file limit (20) LooseMap map[int]string `msg:"loose_map,limit=40"` // Field limit (40) > file limit (20) DefaultSlice []byte `msg:"default_slice"` // No field limit, uses file limit (30) DefaultMap map[string]byte `msg:"default_map"` // No field limit, uses file limit (20) } msgp-1.6.1/_generated/newtime.go000066400000000000000000000010561511433505400165640ustar00rootroot00000000000000package _generated import "time" //go:generate msgp -v //msgp:newtime //msgp:timezone local type NewTime struct { T time.Time Array []time.Time Map map[string]time.Time } func (t1 NewTime) Equal(t2 NewTime) bool { if !t1.T.Equal(t2.T) { return false } if len(t1.Array) != len(t2.Array) { return false } for i := range t1.Array { if !t1.Array[i].Equal(t2.Array[i]) { return false } } if len(t1.Map) != len(t2.Map) { return false } for k, v := range t1.Map { if !t2.Map[k].Equal(v) { return false } } return true } msgp-1.6.1/_generated/newtime_test.go000066400000000000000000000051741511433505400176300ustar00rootroot00000000000000package _generated import ( "bytes" "math/rand" "testing" "time" "github.com/tinylib/msgp/msgp" ) func TestNewTime(t *testing.T) { value := NewTime{ T: time.Now().UTC(), Array: []time.Time{time.Now().UTC(), time.Now().UTC()}, Map: map[string]time.Time{ "a": time.Now().UTC(), }, } encoded, err := value.MarshalMsg(nil) if err != nil { t.Fatal(err) } checkExtMinusOne(t, encoded) var got NewTime _, err = got.UnmarshalMsg(encoded) if err != nil { t.Fatal(err) } if !value.Equal(got) { t.Errorf("UnmarshalMsg got %v want %v", value, got) } if got.T.Location() != time.Local { t.Errorf("DecodeMsg got %v want %v", got.T.Location(), time.Local) } var buf bytes.Buffer w := msgp.NewWriter(&buf) err = value.EncodeMsg(w) if err != nil { t.Fatal(err) } w.Flush() checkExtMinusOne(t, buf.Bytes()) got = NewTime{} r := msgp.NewReader(&buf) err = got.DecodeMsg(r) if err != nil { t.Fatal(err) } if !value.Equal(got) { t.Errorf("DecodeMsg got %v want %v", value, got) } if got.T.Location() != time.Local { t.Errorf("DecodeMsg got %v want %v", got.T.Location(), time.Local) } } func checkExtMinusOne(t *testing.T, b []byte) { r := msgp.NewReader(bytes.NewBuffer(b)) _, err := r.ReadMapHeader() if err != nil { t.Fatal(err) } key, err := r.ReadMapKey(nil) if err != nil { t.Fatal(err) } for !bytes.Equal(key, []byte("T")) { key, err = r.ReadMapKey(nil) if err != nil { t.Fatal(err) } } n, _, err := r.ReadExtensionRaw() if err != nil { t.Fatal(err) } if n != -1 { t.Fatalf("got %v want -1", n) } t.Log("Was -1 extension") } func TestNewTimeRandom(t *testing.T) { rng := rand.New(rand.NewSource(0)) runs := int(1e6) if testing.Short() { runs = 1e4 } for i := 0; i < runs; i++ { nanos := rng.Int63n(999999999 + 1) secs := rng.Uint64() // Tweak the distribution, so we get more than average number of // length 4 and 8 timestamps. if rng.Intn(5) == 0 { secs %= uint64(time.Now().Unix()) if rng.Intn(2) == 0 { nanos = 0 } } value := NewTime{ T: time.Unix(int64(secs), nanos), } encoded, err := value.MarshalMsg(nil) if err != nil { t.Fatal(err) } var got NewTime _, err = got.UnmarshalMsg(encoded) if err != nil { t.Fatal(err) } if !value.Equal(got) { t.Fatalf("UnmarshalMsg got %v want %v", value, got) } var buf bytes.Buffer w := msgp.NewWriter(&buf) err = value.EncodeMsg(w) if err != nil { t.Fatal(err) } w.Flush() got = NewTime{} r := msgp.NewReader(&buf) err = got.DecodeMsg(r) if err != nil { t.Fatal(err) } if !value.Equal(got) { t.Fatalf("DecodeMsg got %v want %v", value, got) } } } msgp-1.6.1/_generated/omitempty.go000066400000000000000000000175121511433505400171470ustar00rootroot00000000000000package _generated import "time" //go:generate msgp type OmitEmpty0 struct { ABool bool `msg:"abool,omitempty"` AInt int `msg:"aint,omitempty"` AInt8 int8 `msg:"aint8,omitempty"` AInt16 int16 `msg:"aint16,omitempty"` AInt32 int32 `msg:"aint32,omitempty"` AInt64 int64 `msg:"aint64,omitempty"` AUint uint `msg:"auint,omitempty"` AUint8 uint8 `msg:"auint8,omitempty"` AUint16 uint16 `msg:"auint16,omitempty"` AUint32 uint32 `msg:"auint32,omitempty"` AUint64 uint64 `msg:"auint64,omitempty"` AFloat32 float32 `msg:"afloat32,omitempty"` AFloat64 float64 `msg:"afloat64,omitempty"` AComplex64 complex64 `msg:"acomplex64,omitempty"` AComplex128 complex128 `msg:"acomplex128,omitempty"` ANamedBool bool `msg:"anamedbool,omitempty"` ANamedInt int `msg:"anamedint,omitempty"` ANamedFloat64 float64 `msg:"anamedfloat64,omitempty"` AMapStrStr map[string]string `msg:"amapstrstr,omitempty"` APtrNamedStr *NamedString `msg:"aptrnamedstr,omitempty"` AString string `msg:"astring,omitempty"` ANamedString string `msg:"anamedstring,omitempty"` AByteSlice []byte `msg:"abyteslice,omitempty"` ASliceByteSlice [][]byte `msg:"aslicebyteslice,omitempty"` AMapByteSlice map[string][]byte `msg:"amapbyteslice,omitempty"` ASliceString []string `msg:"aslicestring,omitempty"` ASliceNamedString []NamedString `msg:"aslicenamedstring,omitempty"` ANamedStruct NamedStruct `msg:"anamedstruct,omitempty"` APtrNamedStruct *NamedStruct `msg:"aptrnamedstruct,omitempty"` AUnnamedStruct struct { A string `msg:"a,omitempty"` } `msg:"aunnamedstruct,omitempty"` // omitempty not supported on unnamed struct EmbeddableStruct `msg:",flatten,omitempty"` // embed flat EmbeddableStruct2 `msg:"embeddablestruct2,omitempty"` // embed non-flat AArrayInt [5]int `msg:"aarrayint,omitempty"` // not supported ATime time.Time `msg:"atime,omitempty"` } type TypeSample struct { K uint32 `msg:"k,omitempty"` V uint32 `msg:"v,omitempty"` } type TypeSamples []TypeSample type ( NamedBool bool NamedInt int NamedFloat64 float64 NamedString string ) type EmbeddableStruct struct { SomeEmbed string `msg:"someembed,omitempty"` } type EmbeddableStruct2 struct { SomeEmbed2 string `msg:"someembed2,omitempty"` } type NamedStruct struct { A string `msg:"a,omitempty"` B string `msg:"b,omitempty"` } type OmitEmptyHalfFull struct { Field00 string `msg:"field00,omitempty"` Field01 string `msg:"field01"` Field02 string `msg:"field02,omitempty"` Field03 string `msg:"field03"` } type OmitEmptyLotsOFields struct { Field00 string `msg:"field00,omitempty"` Field01 string `msg:"field01,omitempty"` Field02 string `msg:"field02,omitempty"` Field03 string `msg:"field03,omitempty"` Field04 string `msg:"field04,omitempty"` Field05 string `msg:"field05,omitempty"` Field06 string `msg:"field06,omitempty"` Field07 string `msg:"field07,omitempty"` Field08 string `msg:"field08,omitempty"` Field09 string `msg:"field09,omitempty"` Field10 string `msg:"field10,omitempty"` Field11 string `msg:"field11,omitempty"` Field12 string `msg:"field12,omitempty"` Field13 string `msg:"field13,omitempty"` Field14 string `msg:"field14,omitempty"` Field15 string `msg:"field15,omitempty"` Field16 string `msg:"field16,omitempty"` Field17 string `msg:"field17,omitempty"` Field18 string `msg:"field18,omitempty"` Field19 string `msg:"field19,omitempty"` Field20 string `msg:"field20,omitempty"` Field21 string `msg:"field21,omitempty"` Field22 string `msg:"field22,omitempty"` Field23 string `msg:"field23,omitempty"` Field24 string `msg:"field24,omitempty"` Field25 string `msg:"field25,omitempty"` Field26 string `msg:"field26,omitempty"` Field27 string `msg:"field27,omitempty"` Field28 string `msg:"field28,omitempty"` Field29 string `msg:"field29,omitempty"` Field30 string `msg:"field30,omitempty"` Field31 string `msg:"field31,omitempty"` Field32 string `msg:"field32,omitempty"` Field33 string `msg:"field33,omitempty"` Field34 string `msg:"field34,omitempty"` Field35 string `msg:"field35,omitempty"` Field36 string `msg:"field36,omitempty"` Field37 string `msg:"field37,omitempty"` Field38 string `msg:"field38,omitempty"` Field39 string `msg:"field39,omitempty"` Field40 string `msg:"field40,omitempty"` Field41 string `msg:"field41,omitempty"` Field42 string `msg:"field42,omitempty"` Field43 string `msg:"field43,omitempty"` Field44 string `msg:"field44,omitempty"` Field45 string `msg:"field45,omitempty"` Field46 string `msg:"field46,omitempty"` Field47 string `msg:"field47,omitempty"` Field48 string `msg:"field48,omitempty"` Field49 string `msg:"field49,omitempty"` Field50 string `msg:"field50,omitempty"` Field51 string `msg:"field51,omitempty"` Field52 string `msg:"field52,omitempty"` Field53 string `msg:"field53,omitempty"` Field54 string `msg:"field54,omitempty"` Field55 string `msg:"field55,omitempty"` Field56 string `msg:"field56,omitempty"` Field57 string `msg:"field57,omitempty"` Field58 string `msg:"field58,omitempty"` Field59 string `msg:"field59,omitempty"` Field60 string `msg:"field60,omitempty"` Field61 string `msg:"field61,omitempty"` Field62 string `msg:"field62,omitempty"` Field63 string `msg:"field63,omitempty"` Field64 string `msg:"field64,omitempty"` Field65 string `msg:"field65,omitempty"` Field66 string `msg:"field66,omitempty"` Field67 string `msg:"field67,omitempty"` Field68 string `msg:"field68,omitempty"` Field69 string `msg:"field69,omitempty"` } type OmitEmpty10 struct { Field00 string `msg:"field00,omitempty"` Field01 string `msg:"field01,omitempty"` Field02 string `msg:"field02,omitempty"` Field03 string `msg:"field03,omitempty"` Field04 string `msg:"field04,omitempty"` Field05 string `msg:"field05,omitempty"` Field06 string `msg:"field06,omitempty"` Field07 string `msg:"field07,omitempty"` Field08 string `msg:"field08,omitempty"` Field09 string `msg:"field09,omitempty"` } type NotOmitEmpty10 struct { Field00 string `msg:"field00"` Field01 string `msg:"field01"` Field02 string `msg:"field02"` Field03 string `msg:"field03"` Field04 string `msg:"field04"` Field05 string `msg:"field05"` Field06 string `msg:"field06"` Field07 string `msg:"field07"` Field08 string `msg:"field08"` Field09 string `msg:"field09"` } type OmitEmptyNoName struct { ABool bool `msg:",omitempty"` AInt int `msg:",omitempty"` AInt8 int8 `msg:",omitempty"` AInt16 int16 `msg:",omitempty"` AInt32 int32 `msg:",omitempty"` AInt64 int64 `msg:",omitempty"` AUint uint `msg:",omitempty"` AUint8 uint8 `msg:",omitempty"` AUint16 uint16 `msg:",omitempty"` AUint32 uint32 `msg:",omitempty"` AUint64 uint64 `msg:",omitempty"` AFloat32 float32 `msg:",omitempty"` AFloat64 float64 `msg:",omitempty"` AComplex64 complex64 `msg:",omitempty"` AComplex128 complex128 `msg:",omitempty"` ANamedBool bool `msg:",omitempty"` ANamedInt int `msg:",omitempty"` ANamedFloat64 float64 `msg:",omitempty"` AMapStrStr map[string]string `msg:",omitempty"` APtrNamedStr *NamedString `msg:",omitempty"` AString string `msg:",omitempty"` AByteSlice []byte `msg:",omitempty"` ASliceString []string `msg:",omitempty"` ASliceNamedString []NamedString `msg:",omitempty"` ANamedStruct NamedStruct `msg:",omitempty"` APtrNamedStruct *NamedStruct `msg:",omitempty"` AUnnamedStruct struct { A string `msg:",omitempty"` } `msg:",omitempty"` // omitempty not supported on unnamed struct EmbeddableStruct `msg:",flatten,omitempty"` // embed flat EmbeddableStruct2 `msg:",omitempty"` // embed non-flat AArrayInt [5]int `msg:",omitempty"` // not supported ATime time.Time `msg:",omitempty"` } msgp-1.6.1/_generated/omitempty_test.go000066400000000000000000000147131511433505400202060ustar00rootroot00000000000000package _generated import ( "bytes" "io" "reflect" "testing" "github.com/tinylib/msgp/msgp" ) func mustEncodeToJSON(o msgp.Encodable) string { var buf bytes.Buffer var err error en := msgp.NewWriter(&buf) err = o.EncodeMsg(en) if err != nil { panic(err) } en.Flush() var outbuf bytes.Buffer _, err = msgp.CopyToJSON(&outbuf, &buf) if err != nil { panic(err) } return outbuf.String() } func TestOmitEmpty0(t *testing.T) { var s string var oe0a OmitEmpty0 s = mustEncodeToJSON(&oe0a) if s != `{"aunnamedstruct":{},"aarrayint":[0,0,0,0,0]}` { t.Errorf("wrong result: %s", s) } var oe0b OmitEmpty0 oe0b.AString = "teststr" s = mustEncodeToJSON(&oe0b) if s != `{"astring":"teststr","aunnamedstruct":{},"aarrayint":[0,0,0,0,0]}` { t.Errorf("wrong result: %s", s) } // more than 15 fields filled in var oe0c OmitEmpty0 oe0c.ABool = true oe0c.AInt = 1 oe0c.AInt8 = 1 oe0c.AInt16 = 1 oe0c.AInt32 = 1 oe0c.AInt64 = 1 oe0c.AUint = 1 oe0c.AUint8 = 1 oe0c.AUint16 = 1 oe0c.AUint32 = 1 oe0c.AUint64 = 1 oe0c.AFloat32 = 1 oe0c.AFloat64 = 1 oe0c.AComplex64 = complex(1, 1) oe0c.AComplex128 = complex(1, 1) oe0c.AString = "test" oe0c.ANamedBool = true oe0c.ANamedInt = 1 oe0c.ANamedFloat64 = 1 var buf bytes.Buffer en := msgp.NewWriter(&buf) err := oe0c.EncodeMsg(en) if err != nil { t.Fatal(err) } en.Flush() de := msgp.NewReader(&buf) var oe0d OmitEmpty0 err = oe0d.DecodeMsg(de) if err != nil { t.Fatal(err) } // spot check some fields if oe0c.AFloat32 != oe0d.AFloat32 { t.Fail() } if oe0c.ANamedBool != oe0d.ANamedBool { t.Fail() } if oe0c.AInt64 != oe0d.AInt64 { t.Fail() } } func TestOmitEmptyNoNames(t *testing.T) { var s string var oe0a OmitEmptyNoName s = mustEncodeToJSON(&oe0a) if s != `{"AUnnamedStruct":{},"AArrayInt":[0,0,0,0,0]}` { t.Errorf("wrong result: %s", s) } var oe0b OmitEmptyNoName oe0b.AString = "teststr" s = mustEncodeToJSON(&oe0b) if s != `{"AString":"teststr","AUnnamedStruct":{},"AArrayInt":[0,0,0,0,0]}` { t.Errorf("wrong result: %s", s) } // more than 15 fields filled in var oe0c OmitEmptyNoName oe0c.ABool = true oe0c.AInt = 1 oe0c.AInt8 = 1 oe0c.AInt16 = 1 oe0c.AInt32 = 1 oe0c.AInt64 = 1 oe0c.AUint = 1 oe0c.AUint8 = 1 oe0c.AUint16 = 1 oe0c.AUint32 = 1 oe0c.AUint64 = 1 oe0c.AFloat32 = 1 oe0c.AFloat64 = 1 oe0c.AComplex64 = complex(1, 1) oe0c.AComplex128 = complex(1, 1) oe0c.AString = "test" oe0c.ANamedBool = true oe0c.ANamedInt = 1 oe0c.ANamedFloat64 = 1 var buf bytes.Buffer en := msgp.NewWriter(&buf) err := oe0c.EncodeMsg(en) if err != nil { t.Fatal(err) } en.Flush() de := msgp.NewReader(&buf) var oe0d OmitEmptyNoName err = oe0d.DecodeMsg(de) if err != nil { t.Fatal(err) } // spot check some fields if oe0c.AFloat32 != oe0d.AFloat32 { t.Fail() } if oe0c.ANamedBool != oe0d.ANamedBool { t.Fail() } if oe0c.AInt64 != oe0d.AInt64 { t.Fail() } } // TestOmitEmptyHalfFull tests mixed omitempty and not func TestOmitEmptyHalfFull(t *testing.T) { var s string var oeA OmitEmptyHalfFull s = mustEncodeToJSON(&oeA) if s != `{"field01":"","field03":""}` { t.Errorf("wrong result: %s", s) } var oeB OmitEmptyHalfFull oeB.Field02 = "val2" s = mustEncodeToJSON(&oeB) if s != `{"field01":"","field02":"val2","field03":""}` { t.Errorf("wrong result: %s", s) } var oeC OmitEmptyHalfFull oeC.Field03 = "val3" s = mustEncodeToJSON(&oeC) if s != `{"field01":"","field03":"val3"}` { t.Errorf("wrong result: %s", s) } } // TestOmitEmptyLotsOFields tests the case of > 64 fields (triggers the bitmask needing to be an array instead of a single value) func TestOmitEmptyLotsOFields(t *testing.T) { var s string var oeLotsA OmitEmptyLotsOFields s = mustEncodeToJSON(&oeLotsA) if s != `{}` { t.Errorf("wrong result: %s", s) } var oeLotsB OmitEmptyLotsOFields oeLotsB.Field04 = "val4" s = mustEncodeToJSON(&oeLotsB) if s != `{"field04":"val4"}` { t.Errorf("wrong result: %s", s) } var oeLotsC OmitEmptyLotsOFields oeLotsC.Field64 = "val64" s = mustEncodeToJSON(&oeLotsC) if s != `{"field64":"val64"}` { t.Errorf("wrong result: %s", s) } } func BenchmarkOmitEmpty10AllEmpty(b *testing.B) { en := msgp.NewWriter(io.Discard) var s OmitEmpty10 b.ResetTimer() for i := 0; i < b.N; i++ { err := s.EncodeMsg(en) if err != nil { b.Fatal(err) } } } func BenchmarkOmitEmpty10AllFull(b *testing.B) { en := msgp.NewWriter(io.Discard) var s OmitEmpty10 s.Field00 = "this is the value of field00" s.Field01 = "this is the value of field01" s.Field02 = "this is the value of field02" s.Field03 = "this is the value of field03" s.Field04 = "this is the value of field04" s.Field05 = "this is the value of field05" s.Field06 = "this is the value of field06" s.Field07 = "this is the value of field07" s.Field08 = "this is the value of field08" s.Field09 = "this is the value of field09" b.ResetTimer() for i := 0; i < b.N; i++ { err := s.EncodeMsg(en) if err != nil { b.Fatal(err) } } } func BenchmarkNotOmitEmpty10AllEmpty(b *testing.B) { en := msgp.NewWriter(io.Discard) var s NotOmitEmpty10 b.ResetTimer() for i := 0; i < b.N; i++ { err := s.EncodeMsg(en) if err != nil { b.Fatal(err) } } } func BenchmarkNotOmitEmpty10AllFull(b *testing.B) { en := msgp.NewWriter(io.Discard) var s NotOmitEmpty10 s.Field00 = "this is the value of field00" s.Field01 = "this is the value of field01" s.Field02 = "this is the value of field02" s.Field03 = "this is the value of field03" s.Field04 = "this is the value of field04" s.Field05 = "this is the value of field05" s.Field06 = "this is the value of field06" s.Field07 = "this is the value of field07" s.Field08 = "this is the value of field08" s.Field09 = "this is the value of field09" b.ResetTimer() for i := 0; i < b.N; i++ { err := s.EncodeMsg(en) if err != nil { b.Fatal(err) } } } func TestTypeAlias(t *testing.T) { value := TypeSamples{TypeSample{}, TypeSample{K: 1, V: 2}} encoded, err := value.MarshalMsg(nil) if err != nil { t.Fatal(err) } var got TypeSamples _, err = got.UnmarshalMsg(encoded) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(value, got) { t.Errorf("UnmarshalMsg got %v want %v", value, got) } var buf bytes.Buffer w := msgp.NewWriter(&buf) err = value.EncodeMsg(w) if err != nil { t.Fatal(err) } w.Flush() got = TypeSamples{} r := msgp.NewReader(&buf) err = got.DecodeMsg(r) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(value, got) { t.Errorf("UnmarshalMsg got %v want %v", value, got) } } msgp-1.6.1/_generated/omitzero.go000066400000000000000000000047251511433505400167720ustar00rootroot00000000000000package _generated import "time" //go:generate msgp // check some specific cases for omitzero type OmitZero0 struct { AStruct OmitZeroA `msg:"astruct,omitempty"` // leave this one omitempty BStruct OmitZeroA `msg:"bstruct,omitzero"` // and compare to this AStructPtr *OmitZeroA `msg:"astructptr,omitempty"` // a pointer case omitempty BStructPtr *OmitZeroA `msg:"bstructptr,omitzero"` // a pointer case omitzero AExt OmitZeroExt `msg:"aext,omitzero"` // external type case AExtPtr *OmitZeroExtPtr `msg:"aextptr,omitzero"` // external type pointer case // more APtrNamedStr *NamedStringOZ `msg:"aptrnamedstr,omitzero"` ANamedStruct NamedStructOZ `msg:"anamedstruct,omitzero"` APtrNamedStruct *NamedStructOZ `msg:"aptrnamedstruct,omitzero"` EmbeddableStruct `msg:",flatten,omitzero"` // embed flat EmbeddableStructOZ `msg:"embeddablestruct2,omitzero"` // embed non-flat ATime time.Time `msg:"atime,omitzero"` OmitZeroTuple OmitZeroTuple `msg:"ozt"` // the inside of a tuple should ignore both omitempty and omitzero } type OmitZeroA struct { A string `msg:"a,omitempty"` B NamedStringOZ `msg:"b,omitzero"` C NamedStringOZ `msg:"c,omitzero"` } func (o *OmitZeroA) IsZero() bool { if o == nil { return true } return *o == (OmitZeroA{}) } type NamedStructOZ struct { A string `msg:"a,omitempty"` B string `msg:"b,omitempty"` } func (ns *NamedStructOZ) IsZero() bool { if ns == nil { return true } return *ns == (NamedStructOZ{}) } type NamedStringOZ string func (ns *NamedStringOZ) IsZero() bool { if ns == nil { return true } return *ns == "" } type EmbeddableStructOZ struct { SomeEmbed string `msg:"someembed2,omitempty"` } func (es EmbeddableStructOZ) IsZero() bool { return es == (EmbeddableStructOZ{}) } type EmbeddableStructOZ2 struct { SomeEmbed2 string `msg:"someembed2,omitempty"` } func (es EmbeddableStructOZ2) IsZero() bool { return es == (EmbeddableStructOZ2{}) } //msgp:tuple OmitZeroTuple // OmitZeroTuple is flagged for tuple output, it should ignore all omitempty and omitzero functionality // since it's fundamentally incompatible. type OmitZeroTuple struct { FieldA string `msg:"fielda,omitempty"` FieldB NamedStringOZ `msg:"fieldb,omitzero"` FieldC NamedStringOZ `msg:"fieldc,omitzero"` } type OmitZero1 struct { T1 OmitZeroTuple `msg:"t1"` } msgp-1.6.1/_generated/omitzero_ext.go000066400000000000000000000047041511433505400176470ustar00rootroot00000000000000package _generated import ( "github.com/tinylib/msgp/msgp" ) // this has "external" types that will show up // as generic IDENT during code generation type OmitZeroExt struct { a int // custom type } // IsZero will return true if a is not positive func (o OmitZeroExt) IsZero() bool { return o.a <= 0 } // EncodeMsg implements msgp.Encodable func (o OmitZeroExt) EncodeMsg(en *msgp.Writer) (err error) { if o.a > 0 { return en.WriteInt(o.a) } return en.WriteNil() } // DecodeMsg implements msgp.Decodable func (o *OmitZeroExt) DecodeMsg(dc *msgp.Reader) (err error) { if dc.IsNil() { err = dc.ReadNil() if err != nil { return } o.a = 0 return } o.a, err = dc.ReadInt() return err } // MarshalMsg implements msgp.Marshaler func (o OmitZeroExt) MarshalMsg(b []byte) (ret []byte, err error) { ret = msgp.Require(b, o.Msgsize()) if o.a > 0 { return msgp.AppendInt(ret, o.a), nil } return msgp.AppendNil(ret), nil } // UnmarshalMsg implements msgp.Unmarshaler func (o *OmitZeroExt) UnmarshalMsg(bts []byte) (ret []byte, err error) { if msgp.IsNil(bts) { bts, err = msgp.ReadNilBytes(bts) return bts, err } o.a, bts, err = msgp.ReadIntBytes(bts) return bts, err } // Msgsize implements msgp.Msgsizer func (o OmitZeroExt) Msgsize() (s int) { return msgp.IntSize } type OmitZeroExtPtr struct { a int // custom type } // IsZero will return true if a is nil or not positive func (o *OmitZeroExtPtr) IsZero() bool { return o == nil || o.a <= 0 } // EncodeMsg implements msgp.Encodable func (o *OmitZeroExtPtr) EncodeMsg(en *msgp.Writer) (err error) { if o.a > 0 { return en.WriteInt(o.a) } return en.WriteNil() } // DecodeMsg implements msgp.Decodable func (o *OmitZeroExtPtr) DecodeMsg(dc *msgp.Reader) (err error) { if dc.IsNil() { err = dc.ReadNil() if err != nil { return } o.a = 0 return } o.a, err = dc.ReadInt() return err } // MarshalMsg implements msgp.Marshaler func (o *OmitZeroExtPtr) MarshalMsg(b []byte) (ret []byte, err error) { ret = msgp.Require(b, o.Msgsize()) if o.a > 0 { return msgp.AppendInt(ret, o.a), nil } return msgp.AppendNil(ret), nil } // UnmarshalMsg implements msgp.Unmarshaler func (o *OmitZeroExtPtr) UnmarshalMsg(bts []byte) (ret []byte, err error) { if msgp.IsNil(bts) { bts, err = msgp.ReadNilBytes(bts) return bts, err } o.a, bts, err = msgp.ReadIntBytes(bts) return bts, err } // Msgsize implements msgp.Msgsizer func (o *OmitZeroExtPtr) Msgsize() (s int) { return msgp.IntSize } msgp-1.6.1/_generated/omitzero_test.go000066400000000000000000000034021511433505400200200ustar00rootroot00000000000000package _generated import ( "bytes" "testing" ) func TestOmitZero(t *testing.T) { t.Run("OmitZeroExt_not_empty", func(t *testing.T) { z := OmitZero0{AExt: OmitZeroExt{a: 1}} b, err := z.MarshalMsg(nil) if err != nil { t.Fatal(err) } if !bytes.Contains(b, []byte("aext")) { t.Errorf("expected to find aext in bytes %X", b) } z = OmitZero0{} _, err = z.UnmarshalMsg(b) if err != nil { t.Fatal(err) } if z.AExt.a != 1 { t.Errorf("z.AExt.a expected 1 but got %d", z.AExt.a) } }) t.Run("OmitZeroExt_negative", func(t *testing.T) { z := OmitZero0{AExt: OmitZeroExt{a: -1}} // negative value should act as empty, via IsEmpty() call b, err := z.MarshalMsg(nil) if err != nil { t.Fatal(err) } if bytes.Contains(b, []byte("aext")) { t.Errorf("expected to not find aext in bytes %X", b) } z = OmitZero0{} _, err = z.UnmarshalMsg(b) if err != nil { t.Fatal(err) } if z.AExt.a != 0 { t.Errorf("z.AExt.a expected 0 but got %d", z.AExt.a) } }) t.Run("OmitZeroTuple", func(t *testing.T) { // make sure tuple encoding isn't affected by omitempty or omitzero z := OmitZero0{OmitZeroTuple: OmitZeroTuple{FieldA: "", FieldB: "", FieldC: "fcval"}} b, err := z.MarshalMsg(nil) if err != nil { t.Fatal(err) } // verify the exact binary encoding, that the values follow each other without field names if !bytes.Contains(b, []byte{0xA0, 0xA0, 0xA5, 'f', 'c', 'v', 'a', 'l'}) { t.Errorf("failed to find expected bytes in %X", b) } z = OmitZero0{} _, err = z.UnmarshalMsg(b) if err != nil { t.Fatal(err) } if z.OmitZeroTuple.FieldA != "" || z.OmitZeroTuple.FieldB != "" || z.OmitZeroTuple.FieldC != "fcval" { t.Errorf("z.OmitZeroTuple unexpected value: %#v", z.OmitZeroTuple) } }) } msgp-1.6.1/_generated/pointer.go000066400000000000000000000120241511433505400165710ustar00rootroot00000000000000package _generated import ( "fmt" "time" "github.com/tinylib/msgp/msgp" ) //go:generate msgp $GOFILE$ // Generate only pointer receivers: //msgp:pointer var mustNoInterf = []interface{}{ Pointer0{}, NamedBoolPointer(true), NamedIntPointer(0), NamedFloat64Pointer(0), NamedStringPointer(""), NamedMapStructPointer(nil), NamedMapStructPointer2(nil), NamedMapStringPointer(nil), NamedMapStringPointer2(nil), EmbeddableStructPointer{}, EmbeddableStruct2Pointer{}, PointerHalfFull{}, PointerNoName{}, } var mustHaveInterf = []interface{}{ &Pointer0{}, mustPtr(NamedBoolPointer(true)), mustPtr(NamedIntPointer(0)), mustPtr(NamedFloat64Pointer(0)), mustPtr(NamedStringPointer("")), mustPtr(NamedMapStructPointer(nil)), mustPtr(NamedMapStructPointer2(nil)), mustPtr(NamedMapStringPointer(nil)), mustPtr(NamedMapStringPointer2(nil)), &EmbeddableStructPointer{}, &EmbeddableStruct2Pointer{}, &PointerHalfFull{}, &PointerNoName{}, } func mustPtr[T any](v T) *T { return &v } func init() { for _, v := range mustNoInterf { if _, ok := v.(msgp.Marshaler); ok { panic(fmt.Sprintf("type %T supports interface", v)) } if _, ok := v.(msgp.Encodable); ok { panic(fmt.Sprintf("type %T supports interface", v)) } } for _, v := range mustHaveInterf { if _, ok := v.(msgp.Marshaler); !ok { panic(fmt.Sprintf("type %T does not support interface", v)) } if _, ok := v.(msgp.Encodable); !ok { panic(fmt.Sprintf("type %T does not support interface", v)) } } } type Pointer0 struct { ABool bool `msg:"abool"` AInt int `msg:"aint"` AInt8 int8 `msg:"aint8"` AInt16 int16 `msg:"aint16"` AInt32 int32 `msg:"aint32"` AInt64 int64 `msg:"aint64"` AUint uint `msg:"auint"` AUint8 uint8 `msg:"auint8"` AUint16 uint16 `msg:"auint16"` AUint32 uint32 `msg:"auint32"` AUint64 uint64 `msg:"auint64"` AFloat32 float32 `msg:"afloat32"` AFloat64 float64 `msg:"afloat64"` AComplex64 complex64 `msg:"acomplex64"` AComplex128 complex128 `msg:"acomplex128"` ANamedBool bool `msg:"anamedbool"` ANamedInt int `msg:"anamedint"` ANamedFloat64 float64 `msg:"anamedfloat64"` AMapStrStr map[string]string `msg:"amapstrstr"` APtrNamedStr *NamedString `msg:"aptrnamedstr"` AString string `msg:"astring"` ANamedString string `msg:"anamedstring"` AByteSlice []byte `msg:"abyteslice"` ASliceString []string `msg:"aslicestring"` ASliceNamedString []NamedString `msg:"aslicenamedstring"` ANamedStruct NamedStruct `msg:"anamedstruct"` APtrNamedStruct *NamedStruct `msg:"aptrnamedstruct"` AUnnamedStruct struct { A string `msg:"a"` } `msg:"aunnamedstruct"` // omitempty not supported on unnamed struct EmbeddableStruct `msg:",flatten"` // embed flat EmbeddableStruct2 `msg:"embeddablestruct2"` // embed non-flat AArrayInt [5]int `msg:"aarrayint"` // not supported ATime time.Time `msg:"atime"` } type ( NamedBoolPointer bool NamedIntPointer int NamedFloat64Pointer float64 NamedStringPointer string NamedMapStructPointer map[string]Pointer0 NamedMapStructPointer2 map[string]*Pointer0 NamedMapStringPointer map[string]NamedStringPointer NamedMapStringPointer2 map[string]*NamedStringPointer ) type EmbeddableStructPointer struct { SomeEmbed string `msg:"someembed"` } type EmbeddableStruct2Pointer struct { SomeEmbed2 string `msg:"someembed2"` } type NamedStructPointer struct { A string `msg:"a"` B string `msg:"b"` } type PointerHalfFull struct { Field00 string `msg:"field00"` Field01 string `msg:"field01"` Field02 string `msg:"field02"` Field03 string `msg:"field03"` } type PointerNoName struct { ABool bool `msg:""` AInt int `msg:""` AInt8 int8 `msg:""` AInt16 int16 `msg:""` AInt32 int32 `msg:""` AInt64 int64 `msg:""` AUint uint `msg:""` AUint8 uint8 `msg:""` AUint16 uint16 `msg:""` AUint32 uint32 `msg:""` AUint64 uint64 `msg:""` AFloat32 float32 `msg:""` AFloat64 float64 `msg:""` AComplex64 complex64 `msg:""` AComplex128 complex128 `msg:""` ANamedBool bool `msg:""` ANamedInt int `msg:""` ANamedFloat64 float64 `msg:""` AMapStrF map[string]NamedFloat64Pointer `msg:""` AMapStrStruct map[string]PointerHalfFull `msg:""` AMapStrStruct2 map[string]*PointerHalfFull `msg:""` APtrNamedStr *NamedStringPointer `msg:""` AString string `msg:""` AByteSlice []byte `msg:""` ASliceString []string `msg:""` ASliceNamedString []NamedStringPointer `msg:""` ANamedStruct NamedStructPointer `msg:""` APtrNamedStruct *NamedStructPointer `msg:""` AUnnamedStruct struct { A string `msg:""` } `msg:""` // omitempty not supported on unnamed struct EmbeddableStructPointer `msg:",flatten"` // embed flat EmbeddableStruct2Pointer `msg:""` // embed non-flat AArrayInt [5]int `msg:""` // not supported ATime time.Time `msg:""` ADur time.Duration `msg:""` } msgp-1.6.1/_generated/replace.go000066400000000000000000000034631511433505400165330ustar00rootroot00000000000000package _generated import "encoding/json" //go:generate msgp //msgp:replace Any with:any //msgp:replace MapString with:CompatibleMapString //msgp:replace MapAny with:map[string]any //msgp:replace SliceString with:[]string //msgp:replace SliceInt with:CompatibleSliceInt //msgp:replace Array8 with:CompatibleArray8 //msgp:replace Array16 with:[16]byte //msgp:replace String with:string //msgp:replace Int with:CompatibleInt //msgp:replace Uint with:uint //msgp:replace Float32 with:CompatibleFloat32 //msgp:replace Float64 with:CompatibleFloat64 //msgp:replace Time with:time.Time //msgp:replace Duration with:time.Duration //msgp:replace StructA with:CompatibleStructA //msgp:replace StructB with:CompatibleStructB //msgp:replace StructC with:CompatibleStructC //msgp:replace StructD with:CompatibleStructD //msgp:replace StructI with:CompatibleStructI //msgp:replace StructS with:CompatibleStructS type ( CompatibleMapString map[string]string CompatibleArray8 [8]byte CompatibleInt int CompatibleFloat32 float32 CompatibleFloat64 float64 CompatibleSliceInt []Int // Doesn't work // CompatibleTime time.Time CompatibleStructA struct { StructB StructB Int Int } CompatibleStructB struct { StructC StructC Any Any Array8 Array8 } CompatibleStructC struct { StructD StructD Float64 Float32 Float32 Float64 } CompatibleStructD struct { Time Time Duration Duration MapString MapString } CompatibleStructI struct { Int *Int Uint *Uint } CompatibleStructS struct { Slice SliceInt } Dummy struct { StructA StructA StructI StructI StructS StructS Array16 Array16 Uint Uint String String } ) //msgp:replace json.Number with:string type NumberJSONSampleReplace struct { Single json.Number Array []json.Number Map map[string]json.Number } msgp-1.6.1/_generated/replace_ext.go000066400000000000000000000013751511433505400174130ustar00rootroot00000000000000package _generated import "time" // external types to test replace directive type ( MapString map[string]string MapAny map[string]any SliceString []String SliceInt []Int Array8 [8]byte Array16 [16]byte Int int Uint uint String string Float32 float32 Float64 float64 Time time.Time Duration time.Duration Any any StructA struct { StructB StructB Int Int } StructB struct { StructC StructC Any Any Array8 Array8 } StructC struct { StructD StructD Float64 Float32 Float32 Float64 } StructD struct { Time Time Duration Duration MapString MapString } StructI struct { Int *Int Uint *Uint } StructS struct { Slice SliceInt } ) msgp-1.6.1/_generated/replace_test.go000066400000000000000000000163671511433505400176010ustar00rootroot00000000000000package _generated import ( "bytes" "encoding/json" "reflect" "testing" "time" "github.com/tinylib/msgp/msgp" ) func compareStructD(t *testing.T, a, b *CompatibleStructD) { t.Helper() if !time.Time(a.Time).Equal(time.Time(b.Time)) { t.Fatal("not same time") } if a.Duration != b.Duration { t.Fatal("not same duration") } if len(a.MapString) != len(b.MapString) { t.Fatal("not same map") } for k, v1 := range a.MapString { if v2, ok := b.MapString[k]; !ok || v1 != v2 { t.Fatal("not same map") } } } func compareStructC(t *testing.T, a, b *CompatibleStructC) { t.Helper() if a.Float32 != b.Float32 { t.Fatal("not same float32") } if a.Float64 != b.Float64 { t.Fatal("not same float64") } compareStructD(t, (*CompatibleStructD)(&a.StructD), (*CompatibleStructD)(&b.StructD)) } func compareStructB(t *testing.T, a, b *CompatibleStructB) { t.Helper() if a.Array8 != b.Array8 { t.Fatal("not same array") } if a.Any != b.Any { t.Fatal("not same any") } compareStructC(t, (*CompatibleStructC)(&a.StructC), (*CompatibleStructC)(&b.StructC)) } func compareStructA(t *testing.T, a, b *CompatibleStructA) { t.Helper() if a.Int != b.Int { t.Fatal("not same int") } compareStructB(t, (*CompatibleStructB)(&a.StructB), (*CompatibleStructB)(&b.StructB)) } func compareStructI(t *testing.T, a, b *CompatibleStructI) { t.Helper() if *a.Int != *b.Int { t.Fatal("not same int") } if *a.Uint != *b.Uint { t.Fatal("not same uint") } } func compareStructS(t *testing.T, a, b *CompatibleStructS) { t.Helper() if len(a.Slice) != len(b.Slice) { t.Fatal("not same slice") } for i := 0; i < len(a.Slice); i++ { if a.Slice[i] != b.Slice[i] { t.Fatal("not same slice") } } } func TestReplace_ABCD(t *testing.T) { d := CompatibleStructD{ Time: Time(time.Now()), Duration: Duration(time.Duration(1234)), MapString: map[string]string{ "foo": "bar", "hello": "word", "baz": "quux", }, } c := CompatibleStructC{ StructD: StructD(d), Float32: 1.0, Float64: 2.0, } b := CompatibleStructB{ StructC: StructC(c), Any: "sup", Array8: [8]byte{'f', 'o', 'o'}, } a := CompatibleStructA{ StructB: StructB(b), Int: 10, } t.Run("D", func(t *testing.T) { bytes, err := d.MarshalMsg(nil) if err != nil { t.Fatal(err) } ud := CompatibleStructD{} _, err = ud.UnmarshalMsg(bytes) if err != nil { t.Fatal(err) } compareStructD(t, &d, &ud) }) t.Run("C", func(t *testing.T) { bytes, err := c.MarshalMsg(nil) if err != nil { t.Fatal(err) } uc := CompatibleStructC{} _, err = uc.UnmarshalMsg(bytes) if err != nil { t.Fatal(err) } compareStructC(t, &c, &uc) }) t.Run("B", func(t *testing.T) { bytes, err := b.MarshalMsg(nil) if err != nil { t.Fatal(err) } ub := CompatibleStructB{} _, err = ub.UnmarshalMsg(bytes) if err != nil { t.Fatal(err) } compareStructB(t, &b, &ub) }) t.Run("A", func(t *testing.T) { bytes, err := a.MarshalMsg(nil) if err != nil { t.Fatal(err) } ua := CompatibleStructA{} _, err = ua.UnmarshalMsg(bytes) if err != nil { t.Fatal(err) } compareStructA(t, &a, &ua) }) } func TestReplace_I(t *testing.T) { var int0 int = -10 var uint0 uint = 12 i := CompatibleStructI{ Int: (*Int)(&int0), Uint: (*Uint)(&uint0), } bytes, err := i.MarshalMsg(nil) if err != nil { t.Fatal(err) } ui := CompatibleStructI{} _, err = ui.UnmarshalMsg(bytes) if err != nil { t.Fatal(err) } compareStructI(t, &i, &ui) } func TestReplace_S(t *testing.T) { s := CompatibleStructS{ Slice: []Int{10, 12, 14, 16}, } bytes, err := s.MarshalMsg(nil) if err != nil { t.Fatal(err) } us := CompatibleStructS{} _, err = us.UnmarshalMsg(bytes) if err != nil { t.Fatal(err) } compareStructS(t, &s, &us) } func TestReplace_Dummy(t *testing.T) { dummy := Dummy{ StructA: StructA{ StructB: StructB{ StructC: StructC{ StructD: StructD{ Time: Time(time.Now()), Duration: Duration(time.Duration(1234)), MapString: map[string]string{ "foo": "bar", "hello": "word", "baz": "quux", }, }, Float32: 1.0, Float64: 2.0, }, Any: "sup", Array8: [8]byte{'f', 'o', 'o'}, }, Int: 10, }, StructI: StructI{ Int: new(Int), Uint: new(Uint), }, StructS: StructS{ Slice: []Int{10, 12, 14, 16}, }, Uint: 10, String: "cheese", } *dummy.StructI.Int = 1234 *dummy.StructI.Uint = 555 bytes, err := dummy.MarshalMsg(nil) if err != nil { t.Fatal(err) } udummy := Dummy{} _, err = udummy.UnmarshalMsg(bytes) if err != nil { t.Fatal(err) } compareStructA(t, (*CompatibleStructA)(&dummy.StructA), (*CompatibleStructA)(&udummy.StructA)) compareStructI(t, (*CompatibleStructI)(&dummy.StructI), (*CompatibleStructI)(&udummy.StructI)) compareStructS(t, (*CompatibleStructS)(&dummy.StructS), (*CompatibleStructS)(&udummy.StructS)) if dummy.Uint != udummy.Uint { t.Fatal("not same uint") } if dummy.String != udummy.String { t.Fatal("not same string") } } func TestJSONNumberReplace(t *testing.T) { test := NumberJSONSampleReplace{ Single: "-42", Array: []json.Number{"0", "-0", "1", "-1", "0.1", "-0.1", "1234", "-1234", "12.34", "-12.34", "12E0", "12E1", "12e34", "12E-0", "12e+1", "12e-34", "-12E0", "-12E1", "-12e34", "-12E-0", "-12e+1", "-12e-34", "1.2E0", "1.2E1", "1.2e34", "1.2E-0", "1.2e+1", "1.2e-34", "-1.2E0", "-1.2E1", "-1.2e34", "-1.2E-0", "-1.2e+1", "-1.2e-34", "0E0", "0E1", "0e34", "0E-0", "0e+1", "0e-34", "-0E0", "-0E1", "-0e34", "-0E-0", "-0e+1", "-0e-34"}, Map: map[string]json.Number{ "a": json.Number("50"), }, } encoded, err := test.MarshalMsg(nil) if err != nil { t.Errorf("%v", err) } var v NumberJSONSampleReplace _, err = v.UnmarshalMsg(encoded) if err != nil { t.Errorf("%v", err) } // Symmetric since we store strings. if !reflect.DeepEqual(v, test) { t.Fatalf("want %v, got %v", test, v) } var jsBuf bytes.Buffer remain, err := msgp.UnmarshalAsJSON(&jsBuf, encoded) if err != nil { t.Errorf("%v", err) } if len(remain) != 0 { t.Errorf("remain should be empty") } // Retains number formatting. Map order is random, though. wantjs := `{"Single":"-42","Array":["0","-0","1","-1","0.1","-0.1","1234","-1234","12.34","-12.34","12E0","12E1","12e34","12E-0","12e+1","12e-34","-12E0","-12E1","-12e34","-12E-0","-12e+1","-12e-34","1.2E0","1.2E1","1.2e34","1.2E-0","1.2e+1","1.2e-34","-1.2E0","-1.2E1","-1.2e34","-1.2E-0","-1.2e+1","-1.2e-34","0E0","0E1","0e34","0E-0","0e+1","0e-34","-0E0","-0E1","-0e34","-0E-0","-0e+1","-0e-34"],"Map":{"a":"50"}}` if jsBuf.String() != wantjs { t.Errorf("jsBuf.String() = \n%s, want \n%s", jsBuf.String(), wantjs) } // Test encoding var buf bytes.Buffer en := msgp.NewWriter(&buf) err = test.EncodeMsg(en) if err != nil { t.Errorf("%v", err) } en.Flush() encoded = buf.Bytes() dc := msgp.NewReader(&buf) err = v.DecodeMsg(dc) if err != nil { t.Errorf("%v", err) } if !reflect.DeepEqual(v, test) { t.Fatalf("want %v, got %v", test, v) } jsBuf.Reset() remain, err = msgp.UnmarshalAsJSON(&jsBuf, encoded) if err != nil { t.Errorf("%v", err) } if len(remain) != 0 { t.Errorf("remain should be empty") } if jsBuf.String() != wantjs { t.Errorf("jsBuf.String() = \n%s, want \n%s", jsBuf.String(), wantjs) } } msgp-1.6.1/_generated/setof.go000066400000000000000000000124701511433505400162360ustar00rootroot00000000000000package _generated import "github.com/tinylib/msgp/msgp/setof" //go:generate msgp type SetOf struct { String setof.String StringSorted setof.StringSorted Int setof.Int IntSorted setof.IntSorted Int64 setof.Int64 Int64Sorted setof.Int64Sorted Int32 setof.Int32 Int32Sorted setof.Int32Sorted Int16 setof.Int16 Int16Sorted setof.Int16Sorted Int8 setof.Int8 Int8Sorted setof.Int8Sorted Byte setof.Byte ByteSorted setof.ByteSorted Uint setof.Uint UintSorted setof.UintSorted Uint64 setof.Uint64 Uint64Sorted setof.Uint64Sorted Uint32 setof.Uint32 Uint32Sorted setof.Uint32Sorted Uint16 setof.Uint16 Uint16Sorted setof.Uint16Sorted Uint8 setof.Uint8 Uint8Sorted setof.Uint8Sorted Float32 setof.Float32 Float32Sorted setof.Float32Sorted Float64 setof.Float64 Float64Sorted setof.Float64Sorted } //msgp:tuple SetOfTuple type SetOfTuple struct { String setof.String StringSorted setof.StringSorted Int setof.Int IntSorted setof.IntSorted Int64 setof.Int64 Int64Sorted setof.Int64Sorted Int32 setof.Int32 Int32Sorted setof.Int32Sorted Int16 setof.Int16 Int16Sorted setof.Int16Sorted Int8 setof.Int8 Int8Sorted setof.Int8Sorted Byte setof.Byte ByteSorted setof.ByteSorted Uint setof.Uint UintSorted setof.UintSorted Uint64 setof.Uint64 Uint64Sorted setof.Uint64Sorted Uint32 setof.Uint32 Uint32Sorted setof.Uint32Sorted Uint16 setof.Uint16 Uint16Sorted setof.Uint16Sorted Uint8 setof.Uint8 Uint8Sorted setof.Uint8Sorted Float32 setof.Float32 Float32Sorted setof.Float32Sorted Float64 setof.Float64 Float64Sorted setof.Float64Sorted } var setofFilled = SetOf{ String: map[string]struct{}{"a": {}, "b": {}, "c": {}}, StringSorted: map[string]struct{}{"d": {}, "e": {}, "f": {}}, Int: map[int]struct{}{1: {}, 2: {}, 3: {}}, IntSorted: map[int]struct{}{4: {}, 5: {}, 6: {}}, Int64: map[int64]struct{}{1: {}, 2: {}, 3: {}}, Int64Sorted: map[int64]struct{}{4: {}, 5: {}, 6: {}}, Int32: map[int32]struct{}{1: {}, 2: {}, 3: {}}, Int32Sorted: map[int32]struct{}{4: {}, 5: {}, 6: {}}, Int16: map[int16]struct{}{1: {}, 2: {}, 3: {}}, Int16Sorted: map[int16]struct{}{4: {}, 5: {}, 6: {}}, Int8: map[int8]struct{}{1: {}, 2: {}, 3: {}}, Int8Sorted: map[int8]struct{}{4: {}, 5: {}, 6: {}}, Byte: map[byte]struct{}{1: {}, 2: {}, 3: {}}, ByteSorted: map[byte]struct{}{4: {}, 5: {}, 6: {}}, Uint: map[uint]struct{}{1: {}, 2: {}, 3: {}}, UintSorted: map[uint]struct{}{4: {}, 5: {}, 6: {}}, Uint64: map[uint64]struct{}{1: {}, 2: {}, 3: {}}, Uint64Sorted: map[uint64]struct{}{4: {}, 5: {}, 6: {}}, Uint32: map[uint32]struct{}{1: {}, 2: {}, 3: {}}, Uint32Sorted: map[uint32]struct{}{4: {}, 5: {}, 6: {}}, Uint16: map[uint16]struct{}{1: {}, 2: {}, 3: {}}, Uint16Sorted: map[uint16]struct{}{4: {}, 5: {}, 6: {}}, Uint8: map[uint8]struct{}{1: {}, 2: {}, 3: {}}, Uint8Sorted: map[uint8]struct{}{4: {}, 5: {}, 6: {}}, Float32: map[float32]struct{}{1: {}, 2: {}, 3: {}}, Float32Sorted: map[float32]struct{}{4: {}, 5: {}, 6: {}}, Float64: map[float64]struct{}{1: {}, 2: {}, 3: {}}, Float64Sorted: map[float64]struct{}{4: {}, 5: {}, 6: {}}, } var setofZeroLen = SetOf{ String: map[string]struct{}{}, StringSorted: map[string]struct{}{}, Int: map[int]struct{}{}, IntSorted: map[int]struct{}{}, Int64: map[int64]struct{}{}, Int64Sorted: map[int64]struct{}{}, Int32: map[int32]struct{}{}, Int32Sorted: map[int32]struct{}{}, Int16: map[int16]struct{}{}, Int16Sorted: map[int16]struct{}{}, Int8: map[int8]struct{}{}, Int8Sorted: map[int8]struct{}{}, Byte: map[byte]struct{}{}, ByteSorted: map[byte]struct{}{}, Uint: map[uint]struct{}{}, UintSorted: map[uint]struct{}{}, Uint64: map[uint64]struct{}{}, Uint64Sorted: map[uint64]struct{}{}, Uint32: map[uint32]struct{}{}, Uint32Sorted: map[uint32]struct{}{}, Uint16: map[uint16]struct{}{}, Uint16Sorted: map[uint16]struct{}{}, Uint8: map[uint8]struct{}{}, Uint8Sorted: map[uint8]struct{}{}, Float32: map[float32]struct{}{}, Float32Sorted: map[float32]struct{}{}, Float64: map[float64]struct{}{}, Float64Sorted: map[float64]struct{}{}, } var setofSortedFilled = SetOf{ StringSorted: map[string]struct{}{"d": {}, "e": {}, "f": {}}, IntSorted: map[int]struct{}{4: {}, 5: {}, 6: {}}, Int64Sorted: map[int64]struct{}{4: {}, 5: {}, 6: {}}, Int32Sorted: map[int32]struct{}{4: {}, 5: {}, 6: {}}, Int16Sorted: map[int16]struct{}{4: {}, 5: {}, 6: {}}, Int8Sorted: map[int8]struct{}{4: {}, 5: {}, 6: {}}, ByteSorted: map[byte]struct{}{4: {}, 5: {}, 6: {}}, UintSorted: map[uint]struct{}{4: {}, 5: {}, 6: {}}, Uint64Sorted: map[uint64]struct{}{4: {}, 5: {}, 6: {}}, Uint32Sorted: map[uint32]struct{}{4: {}, 5: {}, 6: {}}, Uint16Sorted: map[uint16]struct{}{4: {}, 5: {}, 6: {}}, Uint8Sorted: map[uint8]struct{}{4: {}, 5: {}, 6: {}}, Float32Sorted: map[float32]struct{}{4: {}, 5: {}, 6: {}}, Float64Sorted: map[float64]struct{}{4: {}, 5: {}, 6: {}}, } msgp-1.6.1/_generated/setof_test.go000066400000000000000000000112221511433505400172670ustar00rootroot00000000000000package _generated import ( "bytes" "reflect" "testing" "github.com/tinylib/msgp/msgp" ) func TestSetOf_MarshalMsg(t *testing.T) { b, err := setofFilled.MarshalMsg(nil) if err != nil { t.Fatal(err) } var got SetOf if _, err := got.UnmarshalMsg(b); err != nil { t.Fatal(err) } if !reflect.DeepEqual(got, setofFilled) { t.Fatalf("unmarshaled value does not match original: %+v != %+v", got, setofFilled) } // nil values... var empty SetOf b, err = empty.MarshalMsg(nil) if err != nil { t.Fatal(err) } if _, err := got.UnmarshalMsg(b); err != nil { t.Fatal(err) } if !reflect.DeepEqual(got, empty) { t.Fatalf("unmarshaled value does not match original: %+v != %+v", got, empty) } // empty values... b, err = setofZeroLen.MarshalMsg(nil) if err != nil { t.Fatal(err) } if _, err := got.UnmarshalMsg(b); err != nil { t.Fatal(err) } if !reflect.DeepEqual(got, setofZeroLen) { t.Fatalf("unmarshaled value does not match original: %+v != %+v", got, setofZeroLen) } } func TestSetOf_EncodeMsg(t *testing.T) { var buf bytes.Buffer enc := msgp.NewWriter(&buf) dec := msgp.NewReader(&buf) err := setofFilled.EncodeMsg(enc) if err != nil { t.Fatal(err) } enc.Flush() var got SetOf if err := got.DecodeMsg(dec); err != nil { t.Fatal(err) } if !reflect.DeepEqual(got, setofFilled) { t.Fatalf("unmarshaled value does not match original: %+v != %+v", got, setofFilled) } // nil values... var empty SetOf err = empty.EncodeMsg(enc) if err != nil { t.Fatal(err) } enc.Flush() if err := got.DecodeMsg(dec); err != nil { t.Fatal(err) } if !reflect.DeepEqual(got, empty) { t.Fatalf("unmarshaled value does not match original: %+v != %+v", got, empty) } // empty values... err = setofZeroLen.EncodeMsg(enc) if err != nil { t.Fatal(err) } enc.Flush() if err := got.DecodeMsg(dec); err != nil { t.Fatal(err) } if !reflect.DeepEqual(got, setofZeroLen) { t.Fatalf("unmarshaled value does not match original: %+v != %+v", got, setofZeroLen) } } func TestSetOfTuple_MarshalMsg(t *testing.T) { want := SetOfTuple(setofFilled) b, err := want.MarshalMsg(nil) if err != nil { t.Fatal(err) } var got SetOfTuple if _, err := got.UnmarshalMsg(b); err != nil { t.Fatal(err) } if !reflect.DeepEqual(got, want) { t.Fatalf("unmarshaled value does not match original: %+v != %+v", got, want) } // nil values... var empty SetOfTuple b, err = empty.MarshalMsg(nil) if err != nil { t.Fatal(err) } if _, err := got.UnmarshalMsg(b); err != nil { t.Fatal(err) } if !reflect.DeepEqual(got, empty) { t.Fatalf("unmarshaled value does not match original: %+v != %+v", got, empty) } // empty values... want = SetOfTuple(setofZeroLen) b, err = want.MarshalMsg(nil) if err != nil { t.Fatal(err) } if _, err := got.UnmarshalMsg(b); err != nil { t.Fatal(err) } if !reflect.DeepEqual(got, want) { t.Fatalf("unmarshaled value does not match original: %+v != %+v", got, want) } } func TestSetOfTuple_EncodeMsg(t *testing.T) { var buf bytes.Buffer enc := msgp.NewWriter(&buf) dec := msgp.NewReader(&buf) want := SetOfTuple(setofFilled) err := want.EncodeMsg(enc) if err != nil { t.Fatal(err) } enc.Flush() var got SetOfTuple if err := got.DecodeMsg(dec); err != nil { t.Fatal(err) } if !reflect.DeepEqual(got, want) { t.Fatalf("unmarshaled value does not match original: %+v != %+v", got, want) } // nil values... var empty SetOfTuple err = empty.EncodeMsg(enc) if err != nil { t.Fatal(err) } enc.Flush() if err := got.DecodeMsg(dec); err != nil { t.Fatal(err) } if !reflect.DeepEqual(got, empty) { t.Fatalf("unmarshaled value does not match original: %+v != %+v", got, empty) } // empty values... want = SetOfTuple(setofZeroLen) err = want.EncodeMsg(enc) if err != nil { t.Fatal(err) } enc.Flush() if err := got.DecodeMsg(dec); err != nil { t.Fatal(err) } if !reflect.DeepEqual(got, want) { t.Fatalf("unmarshaled value does not match original: %+v != %+v", got, want) } } func TestSetOfSorted_MarshalMsg(t *testing.T) { a, err := setofSortedFilled.MarshalMsg(nil) if err != nil { t.Fatal(err) } b, err := setofSortedFilled.MarshalMsg(nil) if err != nil { t.Fatal(err) } if !bytes.Equal(a, b) { t.Fatalf("unmarshaled value does not match original: %+v != %+v", a, b) } } func TestSetOfSorted_EncodeMsg(t *testing.T) { var a, b bytes.Buffer encA := msgp.NewWriter(&a) encB := msgp.NewWriter(&b) err := setofSortedFilled.EncodeMsg(encA) if err != nil { t.Fatal(err) } encA.Flush() err = setofSortedFilled.EncodeMsg(encB) if err != nil { t.Fatal(err) } encB.Flush() if !bytes.Equal(a.Bytes(), b.Bytes()) { t.Fatalf("unmarshaled value does not match original: %+v != %+v", a, b) } } msgp-1.6.1/_generated/vet_copylocks.go000066400000000000000000000002001511433505400177660ustar00rootroot00000000000000package _generated import "sync" //go:generate msgp //go:generate go vet type Foo struct { I struct{} lock sync.Mutex } msgp-1.6.1/gen/000077500000000000000000000000001511433505400132375ustar00rootroot00000000000000msgp-1.6.1/gen/decode.go000066400000000000000000000356031511433505400150200ustar00rootroot00000000000000package gen import ( "fmt" "io" "math" "strconv" "strings" ) func decode(w io.Writer) *decodeGen { return &decodeGen{ p: printer{w: w}, hasfield: false, } } type decodeGen struct { passes p printer hasfield bool ctx *Context } func (d *decodeGen) Method() Method { return Decode } func (d *decodeGen) needsField() { if d.hasfield { return } d.p.print("\nvar field []byte; _ = field") d.hasfield = true } func (d *decodeGen) Execute(p Elem, ctx Context) error { d.ctx = &ctx p = d.applyall(p) if p == nil { return nil } d.hasfield = false if !d.p.ok() { return d.p.err } if !IsPrintable(p) { return nil } d.p.comment("DecodeMsg implements msgp.Decodable") d.p.printf("\nfunc (%s %s) DecodeMsg(dc *msgp.Reader) (err error) {", p.Varname(), methodReceiver(p)) next(d, p) d.p.nakedReturn() unsetReceiver(p) return d.p.err } func (d *decodeGen) gStruct(s *Struct) { if !d.p.ok() { return } if s.AsTuple { d.structAsTuple(s) } else { d.structAsMap(s) } } func (d *decodeGen) assignAndCheck(name string, typ string) { if !d.p.ok() { return } d.p.printf("\n%s, err = dc.Read%s()", name, typ) d.p.wrapErrCheck(d.ctx.ArgsStr()) } func (d *decodeGen) assignArray(name string, typ string, fieldLimit uint32) { if !d.p.ok() { return } d.p.printf("\n%s, err = dc.Read%s()", name, typ) d.p.wrapErrCheck(d.ctx.ArgsStr()) // Determine effective limit: field limit > context field limit > file limit var limit uint32 var limitName string if fieldLimit > 0 { // Explicit field limit passed as parameter limit = fieldLimit limitName = fmt.Sprintf("%d", fieldLimit) } else if d.ctx.currentFieldArrayLimit != math.MaxUint32 { // Field limit from context (set during field processing) limit = d.ctx.currentFieldArrayLimit limitName = fmt.Sprintf("%d", d.ctx.currentFieldArrayLimit) } else if d.ctx.arrayLimit != math.MaxUint32 { // File-level limit limit = d.ctx.arrayLimit limitName = fmt.Sprintf("%slimitArrays", d.ctx.limitPrefix) } if limit > 0 && limit != math.MaxUint32 { d.p.printf("\nif %s > %s {", name, limitName) d.p.printf("\nerr = msgp.ErrLimitExceeded") d.p.printf("\nreturn") d.p.printf("\n}") } } func (d *decodeGen) assignMap(name string, typ string, fieldLimit uint32) { if !d.p.ok() { return } d.p.printf("\n%s, err = dc.Read%s()", name, typ) d.p.wrapErrCheck(d.ctx.ArgsStr()) // Determine effective limit: field limit > context field limit > file limit var limit uint32 var limitName string if fieldLimit > 0 { // Explicit field limit passed as parameter limit = fieldLimit limitName = fmt.Sprintf("%d", fieldLimit) } else if d.ctx.currentFieldMapLimit != math.MaxUint32 { // Field limit from context (set during field processing) limit = d.ctx.currentFieldMapLimit limitName = fmt.Sprintf("%d", d.ctx.currentFieldMapLimit) } else if d.ctx.mapLimit != math.MaxUint32 { // File-level limit limit = d.ctx.mapLimit limitName = fmt.Sprintf("%slimitMaps", d.ctx.limitPrefix) } if limit > 0 && limit != math.MaxUint32 { d.p.printf("\nif %s > %s {", name, limitName) d.p.printf("\nerr = msgp.ErrLimitExceeded") d.p.printf("\nreturn") d.p.printf("\n}") } } // readBytesWithLimit will read bytes into vname. // Returns field to check for nil. func (d *decodeGen) readBytesWithLimit(vname string, fieldLimit uint32) string { if !d.p.ok() { return "" } // Determine effective limit: field limit > context field limit > file limit var limit uint32 var limitName string if fieldLimit > 0 { // Explicit field limit passed as parameter limit = fieldLimit limitName = fmt.Sprintf("%d", fieldLimit) } else if d.ctx.currentFieldArrayLimit != math.MaxUint32 { // Field limit from context (set during field processing) limit = d.ctx.currentFieldArrayLimit limitName = fmt.Sprintf("%d", d.ctx.currentFieldArrayLimit) } else if d.ctx.arrayLimit != math.MaxUint32 { // File-level limit limit = d.ctx.arrayLimit limitName = fmt.Sprintf("%slimitArrays", d.ctx.limitPrefix) } // Choose reading strategy based on whether limits exist if limit > 0 && limit != math.MaxUint32 { // Limits exist - use header-first security approach sz := randIdent() d.p.printf("\nvar %s uint32", sz) d.p.printf("\n%s, err = dc.ReadBytesHeader()", sz) d.p.wrapErrCheck(d.ctx.ArgsStr()) // Check size against limit before allocating d.p.printf("\nif %s > %s {", sz, limitName) d.p.printf("\nerr = msgp.ErrLimitExceeded") d.p.printf("\nreturn") d.p.printf("\n}") // Allocate and read the data // regular field - ensure always allocated, even for size 0 d.p.printf("\nif %s == nil || uint32(cap(%s)) < %s {", vname, vname, sz) d.p.printf("\n%s = make([]byte, %s)", vname, sz) d.p.printf("\n} else {") d.p.printf("\n%s = %s[:%s]", vname, vname, sz) d.p.printf("\n}") d.p.printf("\n_, err = dc.ReadFull(%s)", vname) return "" } else { // No limits - use original direct reading approach for efficiency d.p.printf("\n%s, err = dc.ReadBytes(%s)", vname, vname) return vname } } func (d *decodeGen) structAsTuple(s *Struct) { sz := randIdent() d.p.declare(sz, u32) d.assignArray(sz, arrayHeader, 0) if s.AsVarTuple { d.p.printf("\nif %[1]s == 0 { return }", sz) } else { d.p.arrayCheck(strconv.Itoa(len(s.Fields)), sz) } for i := range s.Fields { if !d.p.ok() { return } fieldElem := s.Fields[i].FieldElem anField := s.Fields[i].HasTagPart("allownil") && fieldElem.AllowNil() // Set field-specific limits in context based on struct field's FieldLimit if s.Fields[i].FieldLimit > 0 { // Apply same limit to both arrays and maps for this field d.ctx.SetFieldLimits(s.Fields[i].FieldLimit, s.Fields[i].FieldLimit) } else { d.ctx.ClearFieldLimits() } if anField { d.p.print("\nif dc.IsNil() {") d.p.print("\nerr = dc.ReadNil()") d.p.wrapErrCheck(d.ctx.ArgsStr()) d.p.printf("\n%s = nil\n} else {", s.Fields[i].FieldElem.Varname()) } SetIsAllowNil(fieldElem, anField) d.ctx.PushString(s.Fields[i].FieldName) setTypeParams(fieldElem, s.typeParams) next(d, fieldElem) // Clear field limits after processing d.ctx.ClearFieldLimits() d.ctx.Pop() if anField { d.p.printf("\n}") // close if statement } if s.AsVarTuple { d.p.printf("\nif %[1]s--; %[1]s == 0 { return }", sz) } } if s.AsVarTuple { d.p.printf("\nfor ; %[1]s > 0; %[1]s-- {\nif err = dc.Skip(); err != nil {\nerr = msgp.WrapError(err)\nreturn\n}\n}", sz) } } func (d *decodeGen) structAsMap(s *Struct) { d.needsField() sz := randIdent() d.p.declare(sz, u32) d.assignMap(sz, mapHeader, 0) oeCount := s.CountFieldTagPart("omitempty") + s.CountFieldTagPart("omitzero") if !d.ctx.clearOmitted { oeCount = 0 } bm := bmask{ bitlen: oeCount, varname: sz + "Mask", } if oeCount > 0 { // Declare mask d.p.printf("\n%s", bm.typeDecl()) d.p.printf("\n_ = %s", bm.varname) } // Index to field idx of each emitted oeEmittedIdx := []int{} d.p.printf("\nfor %s > 0 {\n%s--", sz, sz) d.assignAndCheck("field", mapKey) d.p.print("\nswitch msgp.UnsafeString(field) {") for i := range s.Fields { d.ctx.PushString(s.Fields[i].FieldName) d.p.printf("\ncase %q:", s.Fields[i].FieldTag) fieldElem := s.Fields[i].FieldElem anField := s.Fields[i].HasTagPart("allownil") && fieldElem.AllowNil() // Set field-specific limits in context based on struct field's FieldLimit if s.Fields[i].FieldLimit > 0 { // Apply same limit to both arrays and maps for this field d.ctx.SetFieldLimits(s.Fields[i].FieldLimit, s.Fields[i].FieldLimit) } else { d.ctx.ClearFieldLimits() } if anField { d.p.print("\nif dc.IsNil() {") d.p.print("\nerr = dc.ReadNil()") d.p.wrapErrCheck(d.ctx.ArgsStr()) d.p.printf("\n%s = nil\n} else {", fieldElem.Varname()) } SetIsAllowNil(fieldElem, anField) setTypeParams(fieldElem, s.typeParams) next(d, fieldElem) // Clear field limits after processing d.ctx.ClearFieldLimits() if oeCount > 0 && (s.Fields[i].HasTagPart("omitempty") || s.Fields[i].HasTagPart("omitzero")) { d.p.printf("\n%s", bm.setStmt(len(oeEmittedIdx))) oeEmittedIdx = append(oeEmittedIdx, i) } d.ctx.Pop() if !d.p.ok() { return } if anField { d.p.printf("\n}") // close if statement } } d.p.print("\ndefault:\nerr = dc.Skip()") d.p.wrapErrCheck(d.ctx.ArgsStr()) d.p.closeblock() // close switch d.p.closeblock() // close for loop if oeCount > 0 { d.p.printf("\n// Clear omitted fields.\n") if bm.bitlen > 1 { d.p.printf("if %s {\n", bm.notAllSet()) } for bitIdx, fieldIdx := range oeEmittedIdx { fieldElem := s.Fields[fieldIdx].FieldElem d.p.printf("if %s == 0 {\n", bm.readExpr(bitIdx)) fze := fieldElem.ZeroExpr() if fze != "" { d.p.printf("%s = %s\n", fieldElem.Varname(), fze) } else { d.p.printf("%s = %s{}\n", fieldElem.Varname(), fieldElem.TypeName()) } d.p.printf("}\n") } if bm.bitlen > 1 { d.p.printf("}") } } } func (d *decodeGen) readBytesConvertWithLimit(tmp string, allowNil bool, receiverVar string) { if !d.p.ok() { return } // Check if limits exist to decide on reading strategy if d.ctx.currentFieldArrayLimit != math.MaxUint32 || d.ctx.arrayLimit != math.MaxUint32 { // Limits exist - use header-first approach for security sz := randIdent() d.p.printf("\nvar %s uint32", sz) d.p.printf("\n%s, err = dc.ReadBytesHeader()", sz) d.p.wrapErrCheck(d.ctx.ArgsStr()) // Check array limits for bytes (use currentFieldArrayLimit or arrayLimit) if d.ctx.currentFieldArrayLimit != math.MaxUint32 { d.p.printf("\nif %s > %d {", sz, d.ctx.currentFieldArrayLimit) d.p.printf("\nerr = msgp.ErrLimitExceeded") d.p.printf("\nreturn") d.p.printf("\n}") } else if d.ctx.arrayLimit != math.MaxUint32 { d.p.printf("\nif %s > %slimitArrays {", sz, d.ctx.limitPrefix) d.p.printf("\nerr = msgp.ErrLimitExceeded") d.p.printf("\nreturn") d.p.printf("\n}") } // Allocate and read with type conversion if tmp != receiverVar { d.p.printf("\n%s = %s", tmp, receiverVar) } d.p.printf("\nif %s == nil || uint32(cap(%s)) < %s {", tmp, tmp, sz) d.p.printf("\n%s = make([]byte, %s)", tmp, sz) d.p.printf("\n} else {") d.p.printf("\n%s = %s[:%s]", tmp, tmp, sz) d.p.printf("\n}") d.p.printf("\n_, err = dc.ReadFull(%s)", tmp) } else { // No limits - use original efficient approach with receiver cast as destination d.p.printf("\n%s, err = dc.ReadBytes(%s)", tmp, receiverVar) } } func (d *decodeGen) gBase(b *BaseElem) { if !d.p.ok() { return } // open block for 'tmp' var tmp string lowered := b.Varname() // passed as argument if b.Convert && b.Value != IDENT { // we don't need block for 'tmp' in case of IDENT tmp = randIdent() lowered = b.ToBase() + "(" + lowered + ")" d.p.printf("\n{ var %s %s", tmp, b.BaseType()) } vname := b.Varname() // e.g. "z.FieldOne" bname := b.BaseName() // e.g. "Float64" checkNil := vname // Name of var to check for nil alwaysRef := vname // make sure we always reference the pointer if strings.Contains(alwaysRef, "*") { alwaysRef = strings.Trim(alwaysRef, "*()") } else if !b.parentIsPtr { alwaysRef = "&" + vname } // handle special cases // for object type. switch b.Value { case Bytes: if b.Convert { d.readBytesConvertWithLimit(tmp, b.AllowNil(), lowered) checkNil = tmp } else { checkNil = d.readBytesWithLimit(vname, 0) } case BinaryMarshaler, BinaryAppender: d.p.printf("\nerr = dc.ReadBinaryUnmarshal(%s)", alwaysRef) case TextMarshalerBin, TextAppenderBin: d.p.printf("\nerr = dc.ReadTextUnmarshal(%s)", alwaysRef) case TextMarshalerString, TextAppenderString: d.p.printf("\nerr = dc.ReadTextUnmarshalString(%s)", alwaysRef) case IDENT: dst := b.BaseType() if b.typeParams.isPtr { dst = "*" + dst } if b.Convert { if remap := b.typeParams.ToPointerMap[stripTypeParams(dst)]; remap != "" { vname = fmt.Sprintf(remap, vname) } lowered := b.ToBase() + "(" + vname + ")" d.p.printf("\nerr = %s.DecodeMsg(dc)", lowered) } else { if remap := b.typeParams.ToPointerMap[stripTypeParams(dst)]; remap != "" { vname = fmt.Sprintf(remap, vname) } d.p.printf("\nerr = %s.DecodeMsg(dc)", vname) } case Ext: d.p.printf("\nerr = dc.ReadExtension(%s)", vname) case AInt64, AInt32, AUint64, AUint32, ABool: tmp := randIdent() t := strings.TrimPrefix(b.BaseName(), "atomic.") d.p.printf("\n var %s %s", tmp, strings.ToLower(t)) d.p.printf("\n%s, err = dc.Read%s()", tmp, t) d.p.printf("\n%s.Store(%s)", strings.TrimPrefix(vname, "*"), tmp) default: if b.Value == Time && d.ctx.asUTC { bname += "UTC" } if b.Convert { d.p.printf("\n%s, err = dc.Read%s()", tmp, bname) } else { d.p.printf("\n%s, err = dc.Read%s()", vname, bname) } } d.p.wrapErrCheck(d.ctx.ArgsStr()) if checkNil != "" && b.AllowNil() { // Ensure that 0 sized slices are allocated. d.p.printf("\nif %s == nil {\n%s = make([]byte, 0)\n}", checkNil, checkNil) } // close block for 'tmp' if b.Convert && b.Value != IDENT { if b.ShimMode == Cast && !b.ShimErrs { d.p.printf("\n%s = %s(%s)\n}", vname, b.FromBase(), tmp) } else { d.p.printf("\n%s, err = %s(%s)\n}", vname, b.FromBase(), tmp) d.p.wrapErrCheck(d.ctx.ArgsStr()) } } } func (d *decodeGen) gMap(m *Map) { if !d.p.ok() { return } sz := randIdent() // resize or allocate map d.p.declare(sz, u32) d.assignMap(sz, mapHeader, 0) d.p.resizeMap(sz, m) // for element in map, read string/value // pair and assign d.needsField() d.p.printf("\nfor %s > 0 {\n%s--", sz, sz) m.readKey(d.ctx, d.p, d, d.assignAndCheck) d.p.declare(m.Validx, m.Value.TypeName()) d.ctx.PushVar(m.Keyidx) m.Value.SetIsAllowNil(false) setTypeParams(m.Value, m.typeParams) next(d, m.Value) d.p.mapAssign(m) d.ctx.Pop() d.p.closeblock() } func (d *decodeGen) gSlice(s *Slice) { if !d.p.ok() { return } sz := randIdent() d.p.declare(sz, u32) d.assignArray(sz, arrayHeader, 0) if s.isAllowNil { d.p.resizeSliceNoNil(sz, s) } else { d.p.resizeSlice(sz, s) } setTypeParams(s.Els, s.typeParams) d.p.rangeBlock(d.ctx, s.Index, s.Varname(), d, s.Els) } func (d *decodeGen) gArray(a *Array) { if !d.p.ok() { return } // special case if we have [const]byte if be, ok := a.Els.(*BaseElem); ok && (be.Value == Byte || be.Value == Uint8) { d.p.printf("\nerr = dc.ReadExactBytes((%s)[:])", a.Varname()) d.p.wrapErrCheck(d.ctx.ArgsStr()) return } sz := randIdent() d.p.declare(sz, u32) d.assignAndCheck(sz, arrayHeader) d.p.arrayCheck(coerceArraySize(a.Size), sz) setTypeParams(a.Els, a.typeParams) d.p.rangeBlock(d.ctx, a.Index, a.Varname(), d, a.Els) } func (d *decodeGen) gPtr(p *Ptr) { if !d.p.ok() { return } d.p.print("\nif dc.IsNil() {") d.p.print("\nerr = dc.ReadNil()") d.p.wrapErrCheck(d.ctx.ArgsStr()) d.p.printf("\n%s = nil\n} else {", p.Varname()) d.p.initPtr(p) if p.typeParams.TypeParams != "" { tp := p.typeParams tp.isPtr = true p.Value.SetTypeParams(tp) } if be, ok := p.Value.(*BaseElem); ok { be.parentIsPtr = true defer func() { be.parentIsPtr = false }() } next(d, p.Value) d.p.closeblock() } msgp-1.6.1/gen/elem.go000066400000000000000000000563301511433505400145170ustar00rootroot00000000000000package gen import ( "fmt" "slices" "strings" ) var ( identNext = 0 identPrefix = "za" ) func resetIdent(prefix string) { identPrefix = prefix identNext = 0 } // generate a random identifier name func randIdent() string { identNext++ return fmt.Sprintf("%s%04d", identPrefix, identNext) } // This code defines the type declaration tree. // // Consider the following: // // type Marshaler struct { // Thing1 *float64 `msg:"thing1"` // Body []byte `msg:"body"` // } // // A parser using this generator as a backend // should parse the above into: // // var val Elem = &Ptr{ // name: "z", // Value: &Struct{ // Name: "Marshaler", // Fields: []StructField{ // { // FieldTag: "thing1", // FieldElem: &Ptr{ // name: "z.Thing1", // Value: &BaseElem{ // name: "*z.Thing1", // Value: Float64, // Convert: false, // }, // }, // }, // { // FieldTag: "body", // FieldElem: &BaseElem{ // name: "z.Body", // Value: Bytes, // Convert: false, // }, // }, // }, // }, // } // Base is one of the // base types type Primitive uint8 // this is effectively the // list of currently available // ReadXxxx / WriteXxxx methods. const ( Invalid Primitive = iota Bytes String Float32 Float64 Complex64 Complex128 Uint Uint8 Uint16 Uint32 Uint64 Byte Int Int8 Int16 Int32 Int64 Bool Intf // interface{} Time // time.Time Duration // time.Duration Ext // extension JsonNumber // json.Number AInt64 AUint64 AInt32 AUint32 ABool // Binary marshaler types BinaryMarshaler // encoding.BinaryMarshaler/BinaryUnmarshaler BinaryAppender // encoding.BinaryAppender/BinaryUnmarshaler // Text marshaler types (stored as binary by default) TextMarshalerBin // encoding.TextMarshaler/TextUnmarshaler -> bin TextAppenderBin // encoding.TextAppender/TextUnmarshaler -> bin // Text marshaler types (stored as string) TextMarshalerString // encoding.TextMarshaler/TextUnmarshaler -> string TextAppenderString // encoding.TextAppender/TextUnmarshaler -> string IDENT // IDENT means an unrecognized identifier ) // all of the recognized identities // that map to primitive types var primitives = map[string]Primitive{ "[]byte": Bytes, "string": String, "float32": Float32, "float64": Float64, "complex64": Complex64, "complex128": Complex128, "uint": Uint, "uint8": Uint8, "uint16": Uint16, "uint32": Uint32, "uint64": Uint64, "byte": Byte, "rune": Int32, "int": Int, "int8": Int8, "int16": Int16, "int32": Int32, "int64": Int64, "bool": Bool, "interface{}": Intf, "any": Intf, "time.Time": Time, "time.Duration": Duration, "msgp.Extension": Ext, "json.Number": JsonNumber, "atomic.Int64": AInt64, "atomic.Uint64": AUint64, "atomic.Int32": AInt32, "atomic.Uint32": AUint32, "atomic.Bool": ABool, } // types built into the library // that satisfy all of the // interfaces. var builtins = map[string]struct{}{ "msgp.Raw": {}, "msgp.Number": {}, } // common data/methods for every Elem type common struct { vname, alias string ptrRcv bool typeParams GenericTypeParams // Generic type parameters, e.g., "[T]" } // GenericTypeParams is a struct that contains the generic type parameters for an element. type GenericTypeParams struct { TypeParams string ToPointerMap map[string]string isPtr bool } func (c *common) SetVarname(s string) { c.vname = s } func (c *common) Varname() string { return c.vname } // typeNameWithParams returns the type name with generic parameters appended if they exist // stripTypeParams removes type parameters from a type name for lookup purposes // e.g. "MyType[T, U]" becomes "MyType", "*SomeType[A]" becomes "*SomeType" func stripTypeParams(typeName string) string { if idx := strings.Index(typeName, "["); idx != -1 { return typeName[:idx] } return typeName } func (c *common) typeNameWithParams(baseName string) string { if c.typeParams.TypeParams != "" && !strings.Contains(baseName, "[") { // Check if baseName is a single identifier without dots (likely a type parameter) if !strings.Contains(baseName, ".") && len(baseName) <= 2 && len(baseName) > 0 { // This looks like a simple type parameter, don't add type parameters return baseName } return baseName + c.typeParams.TypeParams } return baseName } // baseTypeName returns the type name without generic parameters (for use in method receivers) func (c *common) baseTypeName() string { return c.alias } func (c *common) Alias(typ string) { c.alias = typ } func (c *common) hidden() {} func (c *common) AllowNil() bool { return false } func (c *common) SetIsAllowNil(bool) {} func (c *common) SetTypeParams(tp GenericTypeParams) { c.typeParams = tp } func (c *common) TypeParams() GenericTypeParams { return c.typeParams } func (c *common) BaseTypeName() string { return c.baseTypeName() } func (c *common) AlwaysPtr(set *bool) bool { if c != nil && set != nil { c.ptrRcv = *set } return c.ptrRcv } func IsPrintable(e Elem) bool { if be, ok := e.(*BaseElem); ok && !be.Printable() { return false } return true } // Elem is a go type capable of being // serialized into MessagePack. It is // implemented by *Ptr, *Struct, *Array, // *Slice, *Map, and *BaseElem. type Elem interface { // SetVarname sets this nodes // variable name and recursively // sets the names of all its children. // In general, this should only be // called on the parent of the tree. SetVarname(s string) // Varname returns the variable // name of the element. Varname() string // TypeName is the canonical // go type name of the node // e.g. "string", "int", "map[string]float64" // OR the alias name, if it has been set. TypeName() string // Alias sets a type (alias) name Alias(typ string) // Copy should perform a deep copy of the object Copy() Elem // Complexity returns a measure of the // complexity of element (greater than // or equal to 1.) Complexity() int // ZeroExpr returns the expression for the correct zero/empty // value. Can be used for assignment. // Returns "" if zero/empty not supported for this Elem. ZeroExpr() string // AllowNil will return true for types that can be nil but doesn't automatically check. // This is true for slices and maps. AllowNil() bool // SetIsAllowNil will set the allownil value, if the type supports it. SetIsAllowNil(bool) // AlwaysPtr will return true if receiver should always be a pointer. AlwaysPtr(set *bool) bool // IfZeroExpr returns the expression to compare to an empty value // for this type, per the rules of the `omitempty` feature. // It is meant to be used in an if statement // and may include the simple statement form followed by // semicolon and then the expression. // Returns "" if zero/empty not supported for this Elem. // Note that this is NOT used by the `omitzero` feature. IfZeroExpr() string // SetTypeParams sets the generic type parameters for this element SetTypeParams(tp GenericTypeParams) // TypeParams returns the generic type parameters for this element TypeParams() GenericTypeParams // BaseTypeName returns the type name without generic parameters BaseTypeName() string hidden() } // Ident returns the *BaseElem that corresponds // to the provided identity. func Ident(id string) *BaseElem { p, ok := primitives[id] if ok { return &BaseElem{Value: p} } be := &BaseElem{Value: IDENT} be.Alias(id) return be } type Array struct { common Index string // index variable name Size string // array size Els Elem // child } func (a *Array) SetVarname(s string) { a.common.SetVarname(s) ridx: a.Index = randIdent() // try to avoid using the same // index as a parent slice if strings.Contains(a.Varname(), a.Index) { goto ridx } a.Els.SetVarname(fmt.Sprintf("%s[%s]", a.Varname(), a.Index)) } func (a *Array) TypeName() string { if a.alias != "" { return a.typeNameWithParams(a.alias) } a.Alias(fmt.Sprintf("[%s]%s", a.Size, a.Els.TypeName())) return a.typeNameWithParams(a.alias) } func (a *Array) Copy() Elem { b := *a b.Els = a.Els.Copy() return &b } func (a *Array) Complexity() int { // We consider the complexity constant and leave the children to decide on their own. return 2 } // ZeroExpr returns the zero/empty expression or empty string if not supported. Unsupported for this case. func (a *Array) ZeroExpr() string { return "" } // IfZeroExpr unsupported func (a *Array) IfZeroExpr() string { return "" } // Map is a map[string]Elem type Map struct { common Keyidx string // key variable name Validx string // value variable name Key Elem // key element (if not string) Value Elem // value element AllowMapShims bool // Allow map keys to be shimmed (default true) AllowBinMaps bool // Allow maps with binary keys to be used (default false) AutoMapShims bool // Automatically shim map keys of builtin types(default false) isAllowNil bool } func (m *Map) SetVarname(s string) { m.common.SetVarname(s) ridx: m.Keyidx = randIdent() m.Validx = randIdent() // just in case if m.Keyidx == m.Validx { goto ridx } m.Value.SetVarname(m.Validx) } func (m *Map) TypeName() string { if m.alias != "" { return m.typeNameWithParams(m.alias) } keyType := "string" if m.Key != nil { keyType = m.Key.TypeName() } m.Alias("map[" + keyType + "]" + m.Value.TypeName()) return m.typeNameWithParams(m.alias) } func (m *Map) Copy() Elem { g := *m g.Value = m.Value.Copy() return &g } // readKey will read the key into the variable named by m.Keyidx. func (m *Map) readKey(ctx *Context, p printer, t traversal, assignAndCheck func(name string, base string)) { if m.Key != nil && m.AllowBinMaps { p.declare(m.Keyidx, m.Key.TypeName()) ctx.PushVar(m.Keyidx) m.Key.SetVarname(m.Keyidx) next(t, m.Key) ctx.Pop() return } // No key, so we assume the key as a string. p.declare(m.Keyidx, "string") assignAndCheck(m.Keyidx, stringTyp) } func (m *Map) Complexity() int { // Complexity of maps are considered constant. Children should decide on their own. return 3 } // ZeroExpr returns the zero/empty expression or empty string if not supported. Always "nil" for this case. func (m *Map) ZeroExpr() string { return "nil" } // IfZeroExpr returns the expression to compare to zero/empty. func (m *Map) IfZeroExpr() string { return m.Varname() + " == nil" } // AllowNil is true for maps. func (m *Map) AllowNil() bool { return true } // SetIsAllowNil sets whether the map is allowed to be nil. func (m *Map) SetIsAllowNil(b bool) { m.isAllowNil = b } type Slice struct { common Index string isAllowNil bool Els Elem // The type of each element } func (s *Slice) SetVarname(a string) { s.common.SetVarname(a) s.Index = randIdent() varName := s.Varname() if varName[0] == '*' { // Pointer-to-slice requires parenthesis for slicing. varName = "(" + varName + ")" } s.Els.SetVarname(fmt.Sprintf("%s[%s]", varName, s.Index)) } func (s *Slice) TypeName() string { if s.alias != "" { return s.typeNameWithParams(s.alias) } s.Alias("[]" + s.Els.TypeName()) return s.typeNameWithParams(s.alias) } func (s *Slice) Copy() Elem { z := *s z.Els = s.Els.Copy() return &z } func (s *Slice) Complexity() int { // We leave the inlining decision to the slice children. return 2 } // ZeroExpr returns the zero/empty expression or empty string if not supported. Always "nil" for this case. func (s *Slice) ZeroExpr() string { return "nil" } // IfZeroExpr returns the expression to compare to zero/empty. func (s *Slice) IfZeroExpr() string { return s.Varname() + " == nil" } // AllowNil is true for slices. func (s *Slice) AllowNil() bool { return true } // SetIsAllowNil sets whether the slice is allowed to be nil. func (s *Slice) SetIsAllowNil(b bool) { s.isAllowNil = b } // SetIsAllowNil will set whether the element is allowed to be nil. func SetIsAllowNil(e Elem, b bool) { type i interface { SetIsAllowNil(b bool) } if x, ok := e.(i); ok { x.SetIsAllowNil(b) } } type Ptr struct { common Value Elem } func (s *Ptr) SetVarname(a string) { s.common.SetVarname(a) // struct fields are dereferenced // automatically... switch x := s.Value.(type) { case *Struct: // struct fields are automatically dereferenced x.SetVarname(a) return case *BaseElem: // identities have pointer receivers // marshaler types also have pointer receivers if x.Value == IDENT || x.Value == BinaryMarshaler || x.Value == BinaryAppender || x.Value == TextMarshalerBin || x.Value == TextAppenderBin || x.Value == TextMarshalerString || x.Value == TextAppenderString { // replace directive sets Convert=true and Needsref=true // since BaseElem is behind a pointer we set Needsref=false if x.Convert { x.Needsref(false) } x.SetVarname(a) } else { x.SetVarname("*" + a) } return default: s.Value.SetVarname("*" + a) return } } func (s *Ptr) TypeName() string { if s.alias != "" { return s.typeNameWithParams(s.alias) } s.Alias("*" + s.Value.TypeName()) return s.typeNameWithParams(s.alias) } func (s *Ptr) Copy() Elem { v := *s v.Value = s.Value.Copy() return &v } func (s *Ptr) Complexity() int { return 1 + s.Value.Complexity() } func (s *Ptr) Needsinit() bool { if be, ok := s.Value.(*BaseElem); ok && be.needsref { return false } return true } // ZeroExpr returns the zero/empty expression or empty string if not supported. Always "nil" for this case. func (s *Ptr) ZeroExpr() string { return "nil" } // IfZeroExpr returns the expression to compare to zero/empty. func (s *Ptr) IfZeroExpr() string { return s.Varname() + " == nil" } type Struct struct { common Fields []StructField // field list AsTuple bool // write as an array instead of a map AsVarTuple bool // write as an array of variable length instead of a map } func (s *Struct) TypeName() string { if s.alias != "" { return s.alias } str := "struct{\n" for i := range s.Fields { str += s.Fields[i].FieldName + " " + s.Fields[i].FieldElem.TypeName() + " " + s.Fields[i].RawTag + ";\n" } str += "}" s.Alias(str) return s.alias } func (s *Struct) SetVarname(a string) { s.common.SetVarname(a) writeStructFields(s.Fields, a) } func (s *Struct) Copy() Elem { g := *s g.Fields = make([]StructField, len(s.Fields)) copy(g.Fields, s.Fields) for i := range s.Fields { g.Fields[i].FieldElem = s.Fields[i].FieldElem.Copy() } return &g } func (s *Struct) Complexity() int { c := 1 for i := range s.Fields { c += s.Fields[i].FieldElem.Complexity() } return c } // ZeroExpr returns the zero/empty expression or empty string if not supported. func (s *Struct) ZeroExpr() string { if s.alias == "" { return "" // structs with no names not supported (for now) } return "(" + s.TypeName() + "{})" } // IfZeroExpr returns the expression to compare to zero/empty. func (s *Struct) IfZeroExpr() string { if s.alias == "" { return "" // structs with no names not supported (for now) } return s.Varname() + " == " + s.ZeroExpr() } // AnyHasTagPart returns true if HasTagPart(p) is true for any field. func (s *Struct) AnyHasTagPart(pname string) bool { for _, sf := range s.Fields { if sf.HasTagPart(pname) { return true } } return false } // CountFieldTagPart the count of HasTagPart(p) is true for any field. func (s *Struct) CountFieldTagPart(pname string) int { var n int for _, sf := range s.Fields { if sf.HasTagPart(pname) { n++ } } return n } type StructField struct { FieldTag string // the string inside the `msg:""` tag up to the first comma FieldTagParts []string // the string inside the `msg:""` tag split by commas RawTag string // the full struct tag FieldName string // the name of the struct field FieldElem Elem // the field type FieldLimit uint32 // field-specific size limit for slices/maps (0 = no limit) } // HasTagPart returns true if the specified tag part (option) is present. func (sf *StructField) HasTagPart(pname string) bool { if len(sf.FieldTagParts) < 2 { return false } return slices.Contains(sf.FieldTagParts[1:], pname) } // GetTagValue returns the value for a tag part with the format "key=value". // Returns the value string and true if found, empty string and false if not found. func (sf *StructField) GetTagValue(key string) (string, bool) { if len(sf.FieldTagParts) < 2 { return "", false } prefix := key + "=" for _, part := range sf.FieldTagParts[1:] { if strings.HasPrefix(part, prefix) { return strings.TrimPrefix(part, prefix), true } } return "", false } type ShimMode int const ( Cast ShimMode = iota Convert ) // BaseElem is an element that // can be represented by a primitive // MessagePack type. type BaseElem struct { common ShimMode ShimMode // Method used to shim ShimToBase string // shim to base type, or empty ShimFromBase string // shim from base type, or empty ShimErrs bool // ShimToBase has errors on function Value Primitive // Type of element Convert bool // should we do an explicit conversion? zerocopy bool // Allow zerocopy for byte slices in unmarshal. mustinline bool // must inline; not printable needsref bool // needs reference for shim parentIsPtr bool // parent is a pointer allowNil *bool // Override from parent. } func (s *BaseElem) Printable() bool { return !s.mustinline } func (s *BaseElem) Alias(typ string) { s.common.Alias(typ) if s.Value != IDENT { s.Convert = true } if strings.Contains(typ, ".") { s.mustinline = true } } func (s *BaseElem) AllowNil() bool { if s.allowNil == nil { return s.Value == Bytes } return *s.allowNil } // SetIsAllowNil will override allownil when tag has been parsed. func (s *BaseElem) SetIsAllowNil(b bool) { s.allowNil = &b } func (s *BaseElem) SetVarname(a string) { // extensions whose parents // are not pointers need to // be explicitly referenced if s.Value == Ext || s.needsref { if strings.HasPrefix(a, "*") { s.common.SetVarname(a[1:]) return } s.common.SetVarname("&" + a) return } s.common.SetVarname(a) } // TypeName returns the syntactically correct Go // type name for the base element. func (s *BaseElem) TypeName() string { if s.alias != "" { return s.typeNameWithParams(s.alias) } s.common.Alias(s.BaseType()) return s.typeNameWithParams(s.alias) } // ToBase, used if Convert==true, is used as tmp = {{ToBase}}({{Varname}}) func (s *BaseElem) ToBase() string { if s.ShimToBase != "" { return s.ShimToBase } return s.BaseType() } // FromBase, used if Convert==true, is used as {{Varname}} = {{FromBase}}(tmp) func (s *BaseElem) FromBase() string { if s.ShimFromBase != "" { return s.ShimFromBase } return s.TypeName() } // BaseName returns the string form of the // base type (e.g. Float64, Ident, etc) func (s *BaseElem) BaseName() string { // time.Time and time.Duration are special cases; // we strip the package prefix if s.Value == Time { return "Time" } if s.Value == Duration { return "Duration" } if s.Value == JsonNumber { return "JSONNumber" } return s.Value.String() } func (s *BaseElem) BaseType() string { switch s.Value { case IDENT: return s.alias // exceptions to the naming/capitalization // rule: case Intf: return "interface{}" case Bytes: return "[]byte" case Time: return "time.Time" case Duration: return "time.Duration" case JsonNumber: return "json.Number" case AInt64: return "atomic.Int64" case AUint64: return "atomic.Uint64" case AInt32: return "atomic.Int32" case AUint32: return "atomic.Uint32" case ABool: return "atomic.Bool" case Ext: return "msgp.Extension" // everything else is base.String() with // the first letter as lowercase default: return strings.ToLower(s.BaseName()) } } func (s *BaseElem) Needsref(b bool) { s.needsref = b } func (s *BaseElem) Copy() Elem { g := *s return &g } func (s *BaseElem) Complexity() int { if s.Convert && !s.mustinline { return 2 } // we need to return 1 if !printable(), // in order to make sure that stuff gets // inlined appropriately return 1 } // Resolved returns whether or not // the type of the element is // a primitive or a builtin provided // by the package. func (s *BaseElem) Resolved() bool { if s.Value == IDENT { _, ok := builtins[s.TypeName()] return ok } return true } // ZeroExpr returns the zero/empty expression or empty string if not supported. func (s *BaseElem) ZeroExpr() string { switch s.Value { case Bytes: return "nil" case String: return "\"\"" case Complex64, Complex128: return "complex(0,0)" case Float32, Float64, Uint, Uint8, Uint16, Uint32, Uint64, Byte, Int, Int8, Int16, Int32, Int64, Duration: return "0" case Bool: return "false" case Time: return "(time.Time{})" case JsonNumber: return `""` case Intf: return "nil" } return "" } // IfZeroExpr returns the expression to compare to zero/empty. func (s *BaseElem) IfZeroExpr() string { switch s.Value { case AInt64, AUint64, AInt32, AUint32: return fmt.Sprintf("%s.Load() == 0", s.Varname()) case ABool: return fmt.Sprintf("!%s.Load()", s.Varname()) } z := s.ZeroExpr() if z == "" { return "" } return s.Varname() + " == " + z } func (k Primitive) String() string { switch k { case String: return "String" case Bytes: return "Bytes" case Float32: return "Float32" case Float64: return "Float64" case Complex64: return "Complex64" case Complex128: return "Complex128" case Uint: return "Uint" case Uint8: return "Uint8" case Uint16: return "Uint16" case Uint32: return "Uint32" case Uint64: return "Uint64" case Byte: return "Byte" case Int: return "Int" case Int8: return "Int8" case Int16: return "Int16" case Int32: return "Int32" case Int64: return "Int64" case Bool: return "Bool" case Intf: return "Intf" case Time: return "time.Time" case Duration: return "time.Duration" case Ext: return "Extension" case JsonNumber: return "json.Number" case AInt64: return "atomic.Int64" case AUint64: return "atomic.Uint64" case AInt32: return "atomic.Int32" case AUint32: return "atomic.Uint32" case ABool: return "atomic.Bool" case BinaryMarshaler: return "BinaryMarshaler" case BinaryAppender: return "BinaryAppender" case TextMarshalerBin: return "TextMarshalerBin" case TextAppenderBin: return "TextAppenderBin" case TextMarshalerString: return "TextMarshalerString" case TextAppenderString: return "TextAppenderString" case IDENT: return "Ident" default: return "INVALID" } } // writeStructFields is a trampoline for writeBase for // all of the fields in a struct func writeStructFields(s []StructField, name string) { for i := range s { s[i].FieldElem.SetVarname(fmt.Sprintf("%s.%s", name, s[i].FieldName)) } } // coerceArraySize ensures we can compare constant array lengths. // // msgpack array headers are 32 bit unsigned, which is reflected in the // ArrayHeader implementation in this library using uint32. On the Go side, we // can declare array lengths as any constant integer width, which breaks when // attempting a direct comparison to an array header's uint32. func coerceArraySize(asz string) string { return fmt.Sprintf("uint32(%s)", asz) } msgp-1.6.1/gen/encode.go000066400000000000000000000243701511433505400150310ustar00rootroot00000000000000package gen import ( "fmt" "io" "math" "strings" "github.com/tinylib/msgp/msgp" ) func encode(w io.Writer) *encodeGen { return &encodeGen{ p: printer{w: w}, } } type encodeGen struct { passes p printer fuse []byte ctx *Context } func (e *encodeGen) Method() Method { return Encode } func (e *encodeGen) Apply(dirs []string) error { return nil } func (e *encodeGen) writeAndCheck(typ string, argfmt string, arg any) { if e.ctx.compFloats && typ == "Float64" { typ = "Float" } if e.ctx.newTime && typ == "Time" { typ = "TimeExt" } e.p.printf("\nerr = en.Write%s(%s)", typ, fmt.Sprintf(argfmt, arg)) e.p.wrapErrCheck(e.ctx.ArgsStr()) } func (e *encodeGen) writeAndCheckWithArrayLimit(typ string, argfmt string, arg any) { e.writeAndCheck(typ, argfmt, arg) if e.ctx.marshalLimits && e.ctx.arrayLimit != math.MaxUint32 { e.p.printf("\nif %s > %slimitArrays {", fmt.Sprintf(argfmt, arg), e.ctx.limitPrefix) e.p.printf("\nerr = msgp.ErrLimitExceeded") e.p.printf("\nreturn") e.p.printf("\n}") } } func (e *encodeGen) writeAndCheckWithMapLimit(typ string, argfmt string, arg any) { e.writeAndCheck(typ, argfmt, arg) if e.ctx.marshalLimits && e.ctx.mapLimit != math.MaxUint32 { e.p.printf("\nif %s > %slimitMaps {", fmt.Sprintf(argfmt, arg), e.ctx.limitPrefix) e.p.printf("\nerr = msgp.ErrLimitExceeded") e.p.printf("\nreturn") e.p.printf("\n}") } } func (e *encodeGen) fuseHook() { if len(e.fuse) > 0 { e.appendraw(e.fuse) e.fuse = e.fuse[:0] } } func (e *encodeGen) Fuse(b []byte) { if len(e.fuse) > 0 { e.fuse = append(e.fuse, b...) } else { e.fuse = b } } // binaryEncodeCall generates code for marshaler interfaces func (e *encodeGen) binaryEncodeCall(vname, method, writeType, arg string) { bts := randIdent() e.p.printf("\nvar %s []byte", bts) if arg == "" { e.p.printf("\n%s, err = %s.%s()", bts, vname, method) } else { e.p.printf("\n%s, err = %s.%s(%s)", bts, vname, method, arg) } e.p.wrapErrCheck(e.ctx.ArgsStr()) if writeType == "String" { e.writeAndCheck(writeType, literalFmt, "string("+bts+")") } else { e.writeAndCheck(writeType, literalFmt, bts) } } func (e *encodeGen) Execute(p Elem, ctx Context) error { e.ctx = &ctx if !e.p.ok() { return e.p.err } p = e.applyall(p) if p == nil { return nil } if !IsPrintable(p) { return nil } e.p.comment("EncodeMsg implements msgp.Encodable") rcv := imutMethodReceiver(p) ogVar := p.Varname() if p.AlwaysPtr(nil) { rcv = methodReceiver(p) } e.p.printf("\nfunc (%s %s) EncodeMsg(en *msgp.Writer) (err error) {", ogVar, rcv) next(e, p) if p.AlwaysPtr(nil) { p.SetVarname(ogVar) } e.p.nakedReturn() return e.p.err } func (e *encodeGen) gStruct(s *Struct) { if !e.p.ok() { return } if s.AsTuple { e.tuple(s) } else { e.structmap(s) } } func (e *encodeGen) tuple(s *Struct) { nfields := len(s.Fields) data := msgp.AppendArrayHeader(nil, uint32(nfields)) e.p.printf("\n// array header, size %d", nfields) e.Fuse(data) e.fuseHook() for i := range s.Fields { if !e.p.ok() { return } fieldElem := s.Fields[i].FieldElem anField := s.Fields[i].HasTagPart("allownil") && fieldElem.AllowNil() if anField { e.p.printf("\nif %s { // allownil: if nil", fieldElem.IfZeroExpr()) e.p.printf("\nerr = en.WriteNil(); if err != nil { return; }") e.p.printf("\n} else {") } SetIsAllowNil(fieldElem, anField) e.ctx.PushString(s.Fields[i].FieldName) setTypeParams(s.Fields[i].FieldElem, s.typeParams) next(e, s.Fields[i].FieldElem) e.ctx.Pop() if anField { e.p.print("\n}") // close if statement } } } func (e *encodeGen) appendraw(bts []byte) { e.p.print("\nerr = en.Append(") for i, b := range bts { if i != 0 { e.p.print(", ") } e.p.printf("0x%x", b) } e.p.print(")\nif err != nil { return }") } func (e *encodeGen) structmap(s *Struct) { oeIdentPrefix := randIdent() var data []byte nfields := len(s.Fields) bm := bmask{ bitlen: nfields, varname: oeIdentPrefix + "Mask", } omitempty := s.AnyHasTagPart("omitempty") omitzero := s.AnyHasTagPart("omitzero") var closeZero bool var fieldNVar string if omitempty || omitzero { fieldNVar = oeIdentPrefix + "Len" e.p.printf("\n// check for omitted fields") e.p.printf("\n%s := uint32(%d)", fieldNVar, nfields) e.p.printf("\n%s", bm.typeDecl()) e.p.printf("\n_ = %s", bm.varname) for i, sf := range s.Fields { if !e.p.ok() { return } if ize := sf.FieldElem.IfZeroExpr(); ize != "" && sf.HasTagPart("omitempty") { e.p.printf("\nif %s {", ize) e.p.printf("\n%s--", fieldNVar) e.p.printf("\n%s", bm.setStmt(i)) e.p.printf("\n}") } else if sf.HasTagPart("omitzero") { e.p.printf("\nif %s.IsZero() {", sf.FieldElem.Varname()) e.p.printf("\n%s--", fieldNVar) e.p.printf("\n%s", bm.setStmt(i)) e.p.printf("\n}") } } e.p.printf("\n// variable map header, size %s", fieldNVar) e.p.varWriteMapHeader("en", fieldNVar, nfields) e.p.print("\nif err != nil { return }") if !e.p.ok() { return } // Skip block, if no fields are set. if nfields > 1 { e.p.printf("\n\n// skip if no fields are to be emitted") e.p.printf("\nif %s != 0 {", fieldNVar) closeZero = true } } else { // non-omit version data = msgp.AppendMapHeader(nil, uint32(nfields)) e.p.printf("\n// map header, size %d", nfields) e.Fuse(data) if len(s.Fields) == 0 { e.p.printf("\n_ = %s", s.vname) e.fuseHook() } } for i := range s.Fields { if !e.p.ok() { return } // if field is omitempty or omitzero, wrap with if statement based on the emptymask oeField := (omitempty || omitzero) && ((s.Fields[i].HasTagPart("omitempty") && s.Fields[i].FieldElem.IfZeroExpr() != "") || s.Fields[i].HasTagPart("omitzero")) if oeField { e.p.printf("\nif %s == 0 { // if not omitted", bm.readExpr(i)) } data = msgp.AppendString(nil, s.Fields[i].FieldTag) e.p.printf("\n// write %q", s.Fields[i].FieldTag) e.Fuse(data) e.fuseHook() fieldElem := s.Fields[i].FieldElem anField := !oeField && s.Fields[i].HasTagPart("allownil") && fieldElem.AllowNil() if anField { e.p.printf("\nif %s { // allownil: if nil", s.Fields[i].FieldElem.IfZeroExpr()) e.p.printf("\nerr = en.WriteNil(); if err != nil { return; }") e.p.printf("\n} else {") } SetIsAllowNil(fieldElem, anField) e.ctx.PushString(s.Fields[i].FieldName) setTypeParams(s.Fields[i].FieldElem, s.typeParams) next(e, s.Fields[i].FieldElem) e.ctx.Pop() if oeField || anField { e.p.print("\n}") // close if statement } } if closeZero { e.p.printf("\n}") // close if statement } } func (e *encodeGen) gMap(m *Map) { if !e.p.ok() { return } e.fuseHook() vname := m.Varname() e.writeAndCheckWithMapLimit(mapHeader, lenAsUint32, vname) e.p.printf("\nfor %s, %s := range %s {", m.Keyidx, m.Validx, vname) if m.Key != nil { if m.AllowBinMaps { e.ctx.PushVar(m.Keyidx) m.Key.SetVarname(m.Keyidx) next(e, m.Key) e.ctx.Pop() } else { keyIdx := m.Keyidx if key, ok := m.Key.(*BaseElem); ok { if m.AutoMapShims && CanAutoShim[key.Value] { keyIdx = fmt.Sprintf("msgp.AutoShim{}.%sString(%s(%s))", key.Value.String(), strings.ToLower(key.Value.String()), keyIdx) } else if key.Value == String { keyIdx = fmt.Sprintf("%s(%s)", key.ToBase(), keyIdx) } else if key.alias != "" { keyIdx = fmt.Sprintf("string(%s)", keyIdx) } } e.writeAndCheck(stringTyp, literalFmt, keyIdx) } } else { e.writeAndCheck(stringTyp, literalFmt, m.Keyidx) } e.ctx.PushVar(m.Keyidx) m.Value.SetIsAllowNil(false) setTypeParams(m.Value, m.typeParams) next(e, m.Value) e.ctx.Pop() e.p.closeblock() } func (e *encodeGen) gPtr(s *Ptr) { if !e.p.ok() { return } e.fuseHook() e.p.printf("\nif %s == nil { err = en.WriteNil(); if err != nil { return; } } else {", s.Varname()) if s.typeParams.TypeParams != "" { tp := s.typeParams tp.isPtr = true s.Value.SetTypeParams(tp) } next(e, s.Value) e.p.closeblock() } func (e *encodeGen) gSlice(s *Slice) { if !e.p.ok() { return } e.fuseHook() e.writeAndCheckWithArrayLimit(arrayHeader, lenAsUint32, s.Varname()) setTypeParams(s.Els, s.typeParams) e.p.rangeBlock(e.ctx, s.Index, s.Varname(), e, s.Els) } func (e *encodeGen) gArray(a *Array) { if !e.p.ok() { return } e.fuseHook() // shortcut for [const]byte if be, ok := a.Els.(*BaseElem); ok && (be.Value == Byte || be.Value == Uint8) { e.p.printf("\nerr = en.WriteBytes((%s)[:])", a.Varname()) e.p.wrapErrCheck(e.ctx.ArgsStr()) return } e.writeAndCheck(arrayHeader, literalFmt, coerceArraySize(a.Size)) setTypeParams(a.Els, a.typeParams) e.p.rangeBlock(e.ctx, a.Index, a.Varname(), e, a.Els) } func (e *encodeGen) gBase(b *BaseElem) { if !e.p.ok() { return } e.fuseHook() vname := b.Varname() if b.Convert { if b.ShimMode == Cast { vname = tobaseConvert(b) } else { vname = randIdent() e.p.printf("\nvar %s %s", vname, b.BaseType()) e.p.printf("\n%s, err = %s", vname, tobaseConvert(b)) e.p.wrapErrCheck(e.ctx.ArgsStr()) } } switch b.Value { case AInt64, AInt32, AUint64, AUint32, ABool: t := strings.TrimPrefix(b.BaseName(), "atomic.") e.writeAndCheck(t, literalFmt, strings.TrimPrefix(vname, "*")+".Load()") case BinaryMarshaler: e.binaryEncodeCall(vname, "MarshalBinary", "Bytes", "") case TextMarshalerBin: e.binaryEncodeCall(vname, "MarshalText", "Bytes", "") case TextMarshalerString: e.binaryEncodeCall(vname, "MarshalText", "String", "") case BinaryAppender: // We do not know if the interface is implemented on pointer or value. vname = strings.Trim(vname, "*()") e.writeAndCheck("BinaryAppender", literalFmt, vname) case TextAppenderBin: vname = strings.Trim(vname, "*()") e.writeAndCheck("TextAppender", literalFmt, vname) case TextAppenderString: vname = strings.Trim(vname, "*()") e.writeAndCheck("TextAppenderString", literalFmt, vname) case IDENT: // unknown identity dst := b.BaseType() if b.typeParams.isPtr { dst = "*" + dst } // Strip type parameters from dst for lookup in ToPointerMap lookupKey := stripTypeParams(dst) if idx := strings.Index(dst, "["); idx != -1 { lookupKey = dst[:idx] } if remap := b.typeParams.ToPointerMap[lookupKey]; remap != "" { vname = fmt.Sprintf(remap, vname) } e.p.printf("\nerr = %s.EncodeMsg(en)", vname) e.p.wrapErrCheck(e.ctx.ArgsStr()) default: e.writeAndCheck(b.BaseName(), literalFmt, vname) } } msgp-1.6.1/gen/marshal.go000066400000000000000000000255741511433505400152320ustar00rootroot00000000000000package gen import ( "fmt" "io" "math" "strings" "github.com/tinylib/msgp/msgp" ) func marshal(w io.Writer) *marshalGen { return &marshalGen{ p: printer{w: w}, } } type marshalGen struct { passes p printer fuse []byte ctx *Context } func (m *marshalGen) Method() Method { return Marshal } func (m *marshalGen) Apply(dirs []string) error { return nil } func (m *marshalGen) Execute(p Elem, ctx Context) error { m.ctx = &ctx if !m.p.ok() { return m.p.err } p = m.applyall(p) if p == nil { return nil } if !IsPrintable(p) { return nil } m.p.comment("MarshalMsg implements msgp.Marshaler") // save the vname before // calling methodReceiver so // that z.Msgsize() is printed correctly c := p.Varname() rcv := imutMethodReceiver(p) ogVar := p.Varname() if p.AlwaysPtr(nil) { rcv = methodReceiver(p) } m.p.printf("\nfunc (%s %s) MarshalMsg(b []byte) (o []byte, err error) {", ogVar, rcv) m.p.printf("\no = msgp.Require(b, %s.Msgsize())", c) next(m, p) if p.AlwaysPtr(nil) { p.SetVarname(ogVar) } m.p.nakedReturn() return m.p.err } func (m *marshalGen) rawAppend(typ string, argfmt string, arg any) { if m.ctx.compFloats && typ == "Float64" { typ = "Float" } if m.ctx.newTime && typ == "Time" { typ = "TimeExt" } m.p.printf("\no = msgp.Append%s(o, %s)", typ, fmt.Sprintf(argfmt, arg)) } func (m *marshalGen) rawAppendWithArrayLimit(typ string, argfmt string, arg any) { m.rawAppend(typ, argfmt, arg) if m.ctx.marshalLimits && m.ctx.arrayLimit != math.MaxUint32 { m.p.printf("\nif %s > %slimitArrays {", fmt.Sprintf(argfmt, arg), m.ctx.limitPrefix) m.p.printf("\nreturn nil, msgp.ErrLimitExceeded") m.p.printf("\n}") } } func (m *marshalGen) rawAppendWithMapLimit(typ string, argfmt string, arg any) { m.rawAppend(typ, argfmt, arg) if m.ctx.marshalLimits && m.ctx.mapLimit != math.MaxUint32 { m.p.printf("\nif %s > %slimitMaps {", fmt.Sprintf(argfmt, arg), m.ctx.limitPrefix) m.p.printf("\nreturn nil, msgp.ErrLimitExceeded") m.p.printf("\n}") } } func (m *marshalGen) fuseHook() { if len(m.fuse) > 0 { m.rawbytes(m.fuse) m.fuse = m.fuse[:0] } } func (m *marshalGen) Fuse(b []byte) { if len(m.fuse) == 0 { m.fuse = b } else { m.fuse = append(m.fuse, b...) } } func (m *marshalGen) gStruct(s *Struct) { if !m.p.ok() { return } if s.AsTuple { m.tuple(s) } else { m.mapstruct(s) } } func (m *marshalGen) tuple(s *Struct) { data := make([]byte, 0, 5) data = msgp.AppendArrayHeader(data, uint32(len(s.Fields))) m.p.printf("\n// array header, size %d", len(s.Fields)) m.Fuse(data) m.fuseHook() for i := range s.Fields { if !m.p.ok() { return } fieldElem := s.Fields[i].FieldElem anField := s.Fields[i].HasTagPart("allownil") && fieldElem.AllowNil() if anField { m.p.printf("\nif %s { // allownil: if nil", fieldElem.IfZeroExpr()) m.p.printf("\no = msgp.AppendNil(o)") m.p.printf("\n} else {") } m.ctx.PushString(s.Fields[i].FieldName) SetIsAllowNil(fieldElem, anField) setTypeParams(fieldElem, s.typeParams) next(m, fieldElem) m.ctx.Pop() if anField { m.p.printf("\n}") // close if statement } } } func (m *marshalGen) mapstruct(s *Struct) { oeIdentPrefix := randIdent() var data []byte nfields := len(s.Fields) bm := bmask{ bitlen: nfields, varname: oeIdentPrefix + "Mask", } omitempty := s.AnyHasTagPart("omitempty") omitzero := s.AnyHasTagPart("omitzero") var closeZero bool var fieldNVar string if omitempty || omitzero { fieldNVar = oeIdentPrefix + "Len" m.p.printf("\n// check for omitted fields") m.p.printf("\n%s := uint32(%d)", fieldNVar, nfields) m.p.printf("\n%s", bm.typeDecl()) m.p.printf("\n_ = %s", bm.varname) for i, sf := range s.Fields { if !m.p.ok() { return } if ize := sf.FieldElem.IfZeroExpr(); ize != "" && sf.HasTagPart("omitempty") { m.p.printf("\nif %s {", ize) m.p.printf("\n%s--", fieldNVar) m.p.printf("\n%s", bm.setStmt(i)) m.p.printf("\n}") } else if sf.HasTagPart("omitzero") { m.p.printf("\nif %s.IsZero() {", sf.FieldElem.Varname()) m.p.printf("\n%s--", fieldNVar) m.p.printf("\n%s", bm.setStmt(i)) m.p.printf("\n}") } } m.p.printf("\n// variable map header, size %s", fieldNVar) m.p.varAppendMapHeader("o", fieldNVar, nfields) if !m.p.ok() { return } // Skip block, if no fields are set. if nfields > 1 { m.p.printf("\n\n// skip if no fields are to be emitted") m.p.printf("\nif %s != 0 {", fieldNVar) closeZero = true } } else { // non-omitempty version data = make([]byte, 0, 64) data = msgp.AppendMapHeader(data, uint32(len(s.Fields))) m.p.printf("\n// map header, size %d", len(s.Fields)) m.Fuse(data) if len(s.Fields) == 0 { m.p.printf("\n_ = %s", s.vname) m.fuseHook() } } for i := range s.Fields { if !m.p.ok() { return } // if field is omitempty or omitzero, wrap with if statement based on the emptymask oeField := (omitempty || omitzero) && ((s.Fields[i].HasTagPart("omitempty") && s.Fields[i].FieldElem.IfZeroExpr() != "") || s.Fields[i].HasTagPart("omitzero")) if oeField { m.p.printf("\nif %s == 0 { // if not omitted", bm.readExpr(i)) } data = msgp.AppendString(nil, s.Fields[i].FieldTag) m.p.printf("\n// string %q", s.Fields[i].FieldTag) m.Fuse(data) m.fuseHook() fieldElem := s.Fields[i].FieldElem anField := !oeField && s.Fields[i].HasTagPart("allownil") && fieldElem.AllowNil() if anField { m.p.printf("\nif %s { // allownil: if nil", fieldElem.IfZeroExpr()) m.p.printf("\no = msgp.AppendNil(o)") m.p.printf("\n} else {") } m.ctx.PushString(s.Fields[i].FieldName) SetIsAllowNil(fieldElem, anField) setTypeParams(fieldElem, s.typeParams) next(m, fieldElem) m.ctx.Pop() if oeField || anField { m.p.printf("\n}") // close if statement } } if closeZero { m.p.printf("\n}") // close if statement } } // append raw data func (m *marshalGen) rawbytes(bts []byte) { m.p.print("\no = append(o, ") for _, b := range bts { m.p.printf("0x%x,", b) } m.p.print(")") } func (m *marshalGen) gMap(s *Map) { if !m.p.ok() { return } m.fuseHook() vname := s.Varname() m.rawAppendWithMapLimit(mapHeader, lenAsUint32, vname) m.p.printf("\nfor %s, %s := range %s {", s.Keyidx, s.Validx, vname) // Shim key to base type if necessary. if s.Key != nil { if s.AllowBinMaps { m.ctx.PushVar(s.Keyidx) s.Key.SetVarname(s.Keyidx) next(m, s.Key) m.ctx.Pop() } else { keyIdx := s.Keyidx if key, ok := s.Key.(*BaseElem); ok { if s.AutoMapShims && CanAutoShim[key.Value] { keyIdx = fmt.Sprintf("msgp.AutoShim{}.%sString(%s(%s))", key.Value.String(), strings.ToLower(key.Value.String()), keyIdx) } else if key.Value == String { keyIdx = fmt.Sprintf("%s(%s)", key.ToBase(), keyIdx) } else if key.alias != "" { keyIdx = fmt.Sprintf("string(%s)", keyIdx) } } m.rawAppend(stringTyp, literalFmt, keyIdx) } } else { m.rawAppend(stringTyp, literalFmt, s.Keyidx) } m.ctx.PushVar(s.Keyidx) s.Value.SetIsAllowNil(false) setTypeParams(s.Value, s.typeParams) next(m, s.Value) m.ctx.Pop() m.p.closeblock() } func (m *marshalGen) gSlice(s *Slice) { if !m.p.ok() { return } m.fuseHook() vname := s.Varname() setTypeParams(s.Els, s.typeParams) m.rawAppendWithArrayLimit(arrayHeader, lenAsUint32, vname) m.p.rangeBlock(m.ctx, s.Index, vname, m, s.Els) } func (m *marshalGen) gArray(a *Array) { if !m.p.ok() { return } m.fuseHook() if be, ok := a.Els.(*BaseElem); ok && be.Value == Byte { m.rawAppend("Bytes", "(%s)[:]", a.Varname()) return } setTypeParams(a.Els, a.typeParams) m.rawAppend(arrayHeader, literalFmt, coerceArraySize(a.Size)) m.p.rangeBlock(m.ctx, a.Index, a.Varname(), m, a.Els) } func setTypeParams(e Elem, tp GenericTypeParams) { if e == nil { return } tp.isPtr = false e.SetTypeParams(tp) } func (m *marshalGen) gPtr(p *Ptr) { if !m.p.ok() { return } m.fuseHook() m.p.printf("\nif %s == nil {\no = msgp.AppendNil(o)\n} else {", p.Varname()) if p.typeParams.TypeParams != "" { tp := p.typeParams tp.isPtr = true p.Value.SetTypeParams(tp) } next(m, p.Value) m.p.closeblock() } func (m *marshalGen) gBase(b *BaseElem) { if !m.p.ok() { return } m.fuseHook() vname := b.Varname() if b.Convert { if b.ShimMode == Cast { vname = tobaseConvert(b) } else { vname = randIdent() m.p.printf("\nvar %s %s", vname, b.BaseType()) m.p.printf("\n%s, err = %s", vname, tobaseConvert(b)) m.p.wrapErrCheck(m.ctx.ArgsStr()) } } var echeck bool switch b.Value { case BinaryMarshaler: echeck = true m.binaryMarshalCall(vname, "MarshalBinary", "", "msgp.AppendBytes") case BinaryAppender: echeck = false m.binaryAppendCall(vname, "AppendBinary", "msgp.AppendBytes") case TextMarshalerBin: echeck = true m.binaryMarshalCall(vname, "MarshalText", "", "msgp.AppendBytes") case TextAppenderBin: echeck = false m.binaryAppendCall(vname, "AppendText", "msgp.AppendBytes") case TextMarshalerString: echeck = true m.binaryMarshalCall(vname, "MarshalText", "string", "msgp.AppendString") case TextAppenderString: echeck = false m.binaryAppendCall(vname, "AppendText", "msgp.AppendString") case IDENT: dst := b.BaseType() if b.typeParams.isPtr { dst = "*" + dst } if remap := b.typeParams.ToPointerMap[stripTypeParams(dst)]; remap != "" { vname = fmt.Sprintf(remap, vname) } echeck = true m.p.printf("\no, err = %s.MarshalMsg(o)", vname) case Intf, Ext, JsonNumber: echeck = true m.p.printf("\no, err = msgp.Append%s(o, %s)", b.BaseName(), vname) case AInt64, AInt32, AUint64, AUint32, ABool: t := strings.TrimPrefix(b.BaseName(), "atomic.") echeck = false m.p.printf("\no = msgp.Append%s(o, %s.Load())", t, strings.TrimPrefix(vname, "*")) default: m.rawAppend(b.BaseName(), literalFmt, vname) } if echeck { m.p.wrapErrCheck(m.ctx.ArgsStr()) } } // binaryMarshalCall generates code for marshaler interfaces that return []byte func (m *marshalGen) binaryMarshalCall(vname, method, convert, appendFunc string) { bts := randIdent() vname = strings.Trim(vname, "(*)") m.p.printf("\nvar %s []byte", bts) m.p.printf("\n%s, err = %s.%s()", bts, vname, method) m.p.wrapErrCheck(m.ctx.ArgsStr()) if convert != "" { m.p.printf("\no = %s(o, %s(%s))", appendFunc, convert, bts) } else { m.p.printf("\no = %s(o, %s)", appendFunc, bts) } } // binaryAppendCall generates code for appender interfaces that use pre-allocated buffer. // We optimize for cases where the size is 0-256 bytes. func (m *marshalGen) binaryAppendCall(vname, method, appendFunc string) { sz := randIdent() vname = strings.Trim(vname, "(*)") // Reserve 2 bytes for the header bin8 or str8. m.p.printf("\no = append(o, 0, 0); %s := len(o)", sz) m.p.printf("\no, err = %s.%s(o)", vname, method) m.p.wrapErrCheck(m.ctx.ArgsStr()) m.p.printf("\n%s = len(o) - %s", sz, sz) if appendFunc == "msgp.AppendString" { m.p.printf("\no = msgp.AppendBytesStringTwoPrefixed(o, %s)", sz) } else { m.p.printf("\no = msgp.AppendBytesTwoPrefixed(o, %s)", sz) } } msgp-1.6.1/gen/size.go000066400000000000000000000166651511433505400145560ustar00rootroot00000000000000package gen import ( "fmt" "io" "strconv" "strings" "github.com/tinylib/msgp/msgp" ) type sizeState uint8 const ( // need to write "s = ..." assign sizeState = iota // need to write "s += ..." add // can just append "+ ..." expr ) func sizes(w io.Writer) *sizeGen { return &sizeGen{ p: printer{w: w}, state: assign, } } type sizeGen struct { passes p printer state sizeState ctx *Context } func (s *sizeGen) Method() Method { return Size } func (s *sizeGen) Apply(dirs []string) error { return nil } func builtinSize(typ string) string { return "msgp." + typ + "Size" } // this lets us chain together addition // operations where possible func (s *sizeGen) addConstant(sz string) { if !s.p.ok() { return } switch s.state { case assign: s.p.print("\ns = " + sz) s.state = expr return case add: s.p.print("\ns += " + sz) s.state = expr return case expr: s.p.print(" + " + sz) return } panic("unknown size state") } func (s *sizeGen) Execute(p Elem, ctx Context) error { s.ctx = &ctx if !s.p.ok() { return s.p.err } p = s.applyall(p) if p == nil { return nil } if !IsPrintable(p) { return nil } s.ctx.PushString(p.TypeName()) s.p.comment("Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message") rcv := imutMethodReceiver(p) ogVar := p.Varname() if p.AlwaysPtr(nil) { rcv = methodReceiver(p) } s.p.printf("\nfunc (%s %s) Msgsize() (s int) {", ogVar, rcv) s.state = assign next(s, p) if p.AlwaysPtr(nil) { p.SetVarname(ogVar) } s.p.nakedReturn() return s.p.err } func (s *sizeGen) gStruct(st *Struct) { if !s.p.ok() { return } nfields := uint32(len(st.Fields)) if st.AsTuple { data := msgp.AppendArrayHeader(nil, nfields) s.addConstant(strconv.Itoa(len(data))) for i := range st.Fields { if !s.p.ok() { return } setTypeParams(st.Fields[i].FieldElem, st.typeParams) next(s, st.Fields[i].FieldElem) } } else { data := msgp.AppendMapHeader(nil, nfields) s.addConstant(strconv.Itoa(len(data))) for i := range st.Fields { data = data[:0] data = msgp.AppendString(data, st.Fields[i].FieldTag) s.addConstant(strconv.Itoa(len(data))) setTypeParams(st.Fields[i].FieldElem, st.typeParams) next(s, st.Fields[i].FieldElem) } } } func (s *sizeGen) gPtr(p *Ptr) { s.state = add // inner must use add s.p.printf("\nif %s == nil {\ns += msgp.NilSize\n} else {", p.Varname()) if p.typeParams.TypeParams != "" { tp := p.typeParams tp.isPtr = true p.Value.SetTypeParams(tp) } next(s, p.Value) s.state = add // closing block; reset to add s.p.closeblock() } func (s *sizeGen) gSlice(sl *Slice) { if !s.p.ok() { return } s.addConstant(builtinSize(arrayHeader)) // if the slice's element is a fixed size // (e.g. float64, [32]int, etc.), then // print the length times the element size directly if str, ok := fixedsizeExpr(sl.Els); ok { s.addConstant(fmt.Sprintf("(%s * (%s))", lenExpr(sl), str)) return } // add inside the range block, and immediately after setTypeParams(sl.Els, sl.typeParams) s.state = add s.p.rangeBlock(s.ctx, sl.Index, sl.Varname(), s, sl.Els) s.state = add } func (s *sizeGen) gArray(a *Array) { if !s.p.ok() { return } s.addConstant(builtinSize(arrayHeader)) // if the array's children are a fixed // size, we can compile an expression // that always represents the array's wire size if str, ok := fixedsizeExpr(a); ok { s.addConstant(str) return } setTypeParams(a.Els, a.typeParams) s.state = add s.p.rangeBlock(s.ctx, a.Index, a.Varname(), s, a.Els) s.state = add } func (s *sizeGen) gMap(m *Map) { s.addConstant(builtinSize(mapHeader)) vn := m.Varname() s.p.printf("\nif %s != nil {", vn) s.p.printf("\nfor %s, %s := range %s {", m.Keyidx, m.Validx, vn) s.p.printf("\n_ = %s", m.Validx) // we may not use the value keyIdx := m.Keyidx if key, ok := m.Key.(*BaseElem); ok { switch key.Value { case String, IDENT, Bytes: if toBase := key.ToBase(); toBase != "" { keyIdx = fmt.Sprintf("%s(%s)", toBase, keyIdx) s.p.printf("\ns += msgp.StringPrefixSize + len(%s)", keyIdx) } else if key.Value == IDENT && key.ShimToBase == "" && m.AllowBinMaps { //TODO: Generic keys? s.p.printf("\ns += %s.Msgsize()", keyIdx) } default: // A bit clunky - we likely have a fixed size s.p.printf("\n_ = %s", m.Keyidx) // we will not use the key s.p.printf("\ns += %s", builtinSize(key.Value.String())) } } else { s.p.printf("\ns += msgp.StringPrefixSize + len(%s)", keyIdx) } s.state = expr s.ctx.PushVar(m.Keyidx) setTypeParams(m.Value, m.typeParams) next(s, m.Value) s.ctx.Pop() s.p.closeblock() s.p.closeblock() s.state = add } func (s *sizeGen) gBase(b *BaseElem) { if !s.p.ok() { return } if b.Convert && b.ShimMode == Convert { s.state = add vname := randIdent() s.p.printf("\nvar %s %s", vname, b.BaseType()) // ensure we don't get "unused variable" warnings from outer slice iterations s.p.printf("\n_ = %s", b.Varname()) s.p.printf("\ns += %s", basesizeExpr(b.Value, vname, b.BaseName())) s.state = expr } else { vname := b.Varname() if b.Convert { vname = tobaseConvert(b) } dst := b.BaseType() if b.typeParams.isPtr { dst = "*" + dst } // Strip type parameters from dst for lookup in ToPointerMap lookupKey := stripTypeParams(dst) if idx := strings.Index(dst, "["); idx != -1 { lookupKey = dst[:idx] } if remap := b.typeParams.ToPointerMap[lookupKey]; remap != "" { vname = fmt.Sprintf(remap, vname) } s.addConstant(basesizeExpr(b.Value, vname, b.BaseName())) } } // returns "len(slice)" func lenExpr(sl *Slice) string { return "len(" + sl.Varname() + ")" } // is a given primitive always the same (max) // size on the wire? func fixedSize(p Primitive) bool { switch p { case Intf, Ext, IDENT, Bytes, String: return false default: return true } } // strip reference from string func stripRef(s string) string { if s[0] == '&' { return s[1:] } return s } // return a fixed-size expression, if possible. // only possible for *BaseElem and *Array. // returns (expr, ok) func fixedsizeExpr(e Elem) (string, bool) { switch e := e.(type) { case *Array: if str, ok := fixedsizeExpr(e.Els); ok { return fmt.Sprintf("(%s * (%s))", e.Size, str), true } case *BaseElem: if fixedSize(e.Value) { return builtinSize(strings.TrimPrefix(e.BaseName(), "atomic.")), true } case *Struct: var str string for _, f := range e.Fields { if fs, ok := fixedsizeExpr(f.FieldElem); ok { if str == "" { str = fs } else { str += "+" + fs } } else { return "", false } } var hdrlen int mhdr := msgp.AppendMapHeader(nil, uint32(len(e.Fields))) hdrlen += len(mhdr) var strbody []byte for _, f := range e.Fields { strbody = msgp.AppendString(strbody[:0], f.FieldTag) hdrlen += len(strbody) } return fmt.Sprintf("%d + %s", hdrlen, str), true } return "", false } // print size expression of a variable name func basesizeExpr(value Primitive, vname, basename string) string { switch value { case Ext: return "msgp.ExtensionPrefixSize + " + stripRef(vname) + ".Len()" case Intf: return "msgp.GuessSize(" + vname + ")" case IDENT: return vname + ".Msgsize()" case Bytes: return "msgp.BytesPrefixSize + len(" + vname + ")" case String: return "msgp.StringPrefixSize + len(" + vname + ")" case AInt64, AInt32, AUint64, AUint32, ABool: return builtinSize(strings.TrimPrefix(basename, "atomic.")) default: return builtinSize(basename) } } msgp-1.6.1/gen/spec.go000066400000000000000000000367121511433505400145310ustar00rootroot00000000000000package gen import ( "bytes" "fmt" "io" "math" "regexp" "strings" ) const ( lenAsUint32 = "uint32(len(%s))" literalFmt = "%s" intFmt = "%d" quotedFmt = `"%s"` mapHeader = "MapHeader" arrayHeader = "ArrayHeader" mapKey = "MapKeyPtr" stringTyp = "String" u32 = "uint32" ) // Method is a bitfield representing something that the // generator knows how to print. type Method uint8 // are the bits in 'f' set in 'm'? func (m Method) isset(f Method) bool { return (m&f == f) } // String implements fmt.Stringer func (m Method) String() string { switch m { case 0, invalidmeth: return "" case Decode: return "decode" case Encode: return "encode" case Marshal: return "marshal" case Unmarshal: return "unmarshal" case Size: return "size" case Test: return "test" default: // return e.g. "decode+encode+test" modes := [...]Method{Decode, Encode, Marshal, Unmarshal, Size, Test} any := false nm := "" for _, mm := range modes { if m.isset(mm) { if any { nm += "+" + mm.String() } else { nm += mm.String() any = true } } } return nm } } const ( Decode Method = 1 << iota // msgp.Decodable Encode // msgp.Encodable Marshal // msgp.Marshaler Unmarshal // msgp.Unmarshaler Size // msgp.Sizer Test // generate tests invalidmeth // this isn't a method encodetest = Encode | Decode | Test // tests for Encodable and Decodable marshaltest = Marshal | Unmarshal | Test // tests for Marshaler and Unmarshaler ) type Printer struct { gens []generator CompactFloats bool ClearOmitted bool NewTime bool AsUTC bool ArrayLimit uint32 MapLimit uint32 MarshalLimits bool LimitPrefix string } func NewPrinter(m Method, out io.Writer, tests io.Writer) *Printer { if m.isset(Test) && tests == nil { panic("cannot print tests with 'nil' tests argument!") } gens := make([]generator, 0, 7) if m.isset(Decode) { gens = append(gens, decode(out)) } if m.isset(Encode) { gens = append(gens, encode(out)) } if m.isset(Marshal) { gens = append(gens, marshal(out)) } if m.isset(Unmarshal) { gens = append(gens, unmarshal(out)) } if m.isset(Size) { gens = append(gens, sizes(out)) } if m.isset(marshaltest) { gens = append(gens, mtest(tests)) } if m.isset(encodetest) { gens = append(gens, etest(tests)) } if len(gens) == 0 { panic("NewPrinter called with invalid method flags") } return &Printer{gens: gens} } // TransformPass is a pass that transforms individual // elements. (Note that if the returned is different from // the argument, it should not point to the same objects.) type TransformPass func(Elem) Elem // IgnoreTypename is a pass that just ignores // types of a given name. func IgnoreTypename(name string) TransformPass { if name, ok := strings.CutPrefix(name, "regex:"); ok { name = strings.TrimPrefix(name, "regex:") rx, err := regexp.Compile(name) if err != nil { panic(fmt.Sprintf("Error compiling ignore regex %q: %v", name, err)) } return func(e Elem) Elem { if rx.MatchString(e.TypeName()) { return nil } return e } } return func(e Elem) Elem { if e.TypeName() == name { return nil } return e } } // ApplyDirective applies a directive to a named pass // and all of its dependents. func (p *Printer) ApplyDirective(pass Method, t TransformPass) { for _, g := range p.gens { if g.Method().isset(pass) { g.Add(t) } } } // Print prints an Elem. func (p *Printer) Print(e Elem) error { e.SetIsAllowNil(false) for _, g := range p.gens { // Elem.SetVarname() is called before the Print() step in parse.FileSet.PrintTo(). // Elem.SetVarname() generates identifiers as it walks the Elem. This can cause // collisions between idents created during SetVarname and idents created during Print, // hence the separate prefixes. resetIdent("zb") err := g.Execute(e, Context{ compFloats: p.CompactFloats, clearOmitted: p.ClearOmitted, newTime: p.NewTime, asUTC: p.AsUTC, arrayLimit: p.ArrayLimit, mapLimit: p.MapLimit, marshalLimits: p.MarshalLimits, limitPrefix: p.LimitPrefix, currentFieldArrayLimit: math.MaxUint32, // Initialize to "no field limit" currentFieldMapLimit: math.MaxUint32, // Initialize to "no field limit" }) resetIdent("za") if err != nil { return err } } return nil } type contextItem interface { Arg() string } type contextString string func (c contextString) Arg() string { return fmt.Sprintf("%q", c) } type contextVar string func (c contextVar) Arg() string { return string(c) } type Context struct { path []contextItem compFloats bool clearOmitted bool newTime bool asUTC bool arrayLimit uint32 mapLimit uint32 marshalLimits bool limitPrefix string currentFieldArrayLimit uint32 // Current field's array limit (0 = no field-level limit) currentFieldMapLimit uint32 // Current field's map limit (0 = no field-level limit) } func (c *Context) PushString(s string) { c.path = append(c.path, contextString(s)) } func (c *Context) PushVar(s string) { c.path = append(c.path, contextVar(s)) } func (c *Context) Pop() { c.path = c.path[:len(c.path)-1] } // SetFieldLimits sets the current field-specific limits for the context func (c *Context) SetFieldLimits(arrayLimit, mapLimit uint32) { c.currentFieldArrayLimit = arrayLimit c.currentFieldMapLimit = mapLimit } // ClearFieldLimits clears the current field-specific limits (use file limits) func (c *Context) ClearFieldLimits() { c.currentFieldArrayLimit = math.MaxUint32 c.currentFieldMapLimit = math.MaxUint32 } func (c *Context) ArgsStr() string { var out string for idx, p := range c.path { if idx > 0 { out += ", " } out += p.Arg() } return out } // generator is the interface through // which code is generated. type generator interface { Method() Method Add(p TransformPass) Execute(Elem, Context) error // execute writes the method for the provided object. } type passes []TransformPass func (p *passes) Add(t TransformPass) { *p = append(*p, t) } func (p *passes) applyall(e Elem) Elem { for _, t := range *p { e = t(e) if e == nil { return nil } } return e } type traversal interface { gMap(*Map) gSlice(*Slice) gArray(*Array) gPtr(*Ptr) gBase(*BaseElem) gStruct(*Struct) } // type-switch dispatch to the correct // method given the type of 'e' func next(t traversal, e Elem) { switch e := e.(type) { case *Map: t.gMap(e) case *Struct: t.gStruct(e) case *Slice: t.gSlice(e) case *Array: t.gArray(e) case *Ptr: t.gPtr(e) case *BaseElem: t.gBase(e) default: panic("bad element type") } } // possibly-immutable method receiver func imutMethodReceiver(p Elem) string { typeName := p.BaseTypeName() typeParams := p.TypeParams() switch e := p.(type) { case *Struct: // TODO(HACK): actually do real math here. if len(e.Fields) <= 3 { for i := range e.Fields { if be, ok := e.Fields[i].FieldElem.(*BaseElem); !ok || (be.Value == IDENT || be.Value == Bytes) { goto nope } } return typeName + typeParams.TypeParams } nope: return "*" + typeName + typeParams.TypeParams // gets dereferenced automatically case *Array: return "*" + typeName + typeParams.TypeParams // everything else can be // by-value. default: return typeName + typeParams.TypeParams } } // if necessary, wraps a type // so that its method receiver // is of the write type. func methodReceiver(p Elem) string { typeName := p.BaseTypeName() typeParams := p.TypeParams() switch p.(type) { // structs and arrays are // dereferenced automatically, // so no need to alter varname case *Struct, *Array: return "*" + typeName + typeParams.TypeParams // set variable name to // *varname default: p.SetVarname("(*" + p.Varname() + ")") return "*" + typeName + typeParams.TypeParams } } func unsetReceiver(p Elem) { switch p.(type) { case *Struct, *Array: default: p.SetVarname("z") } } // shared utility for generators type printer struct { w io.Writer err error } // writes "var {{name}} {{typ}};" func (p *printer) declare(name string, typ string) { p.printf("\nvar %s %s", name, typ) } // does: // // if m == nil { // m = make(type, size) // } else if len(m) > 0 { // // for key := range m { delete(m, key) } // } func (p *printer) resizeMap(size string, m *Map) { vn := m.Varname() if !p.ok() { return } p.printf("\nif %s == nil {", vn) p.printf("\n%s = make(%s, %s)", vn, m.TypeName(), size) p.printf("\n} else if len(%s) > 0 {", vn) p.clearMap(vn) p.closeblock() } // CanAutoShim contains the primitives that can be auto-shimmed. var CanAutoShim = map[Primitive]bool{Uint: true, Uint8: true, Uint16: true, Uint32: true, Uint64: true, Int: true, Int8: true, Int16: true, Int32: true, Int64: true, Bool: true, Float32: true, Float64: true, Byte: true} // assign key to value based on varnames func (p *printer) mapAssign(m *Map) { if !p.ok() { return } if key, ok := m.Key.(*BaseElem); ok { fromBase := key.FromBase() shimErr := key.ShimErrs if m.AutoMapShims && CanAutoShim[key.Value] { fromBase = "msgp.AutoShim{}.Parse" + key.Value.String() shimErr = true } if !m.AllowBinMaps && fromBase != "" { if key.Value == String && key.ShimFromBase != "" { p.printf("\nvar %sTmp %s", m.Keyidx, key.TypeName()) if key.ShimErrs { p.printf("\n%sTmp, err = %s(%s)", m.Keyidx, fromBase, m.Keyidx) p.wrapErrCheck("\"shim: " + fromBase + "\"") } else { p.printf("\n%sTmp = %s(%s)", m.Keyidx, fromBase, m.Keyidx) } p.printf("\n%s[%sTmp] = %s", m.Varname(), m.Keyidx, m.Validx) return } else if key.Value == IDENT { p.printf("\n%s[%s(%s)] = %s", m.Varname(), fromBase, m.Keyidx, m.Validx) return } else { if shimErr { p.printf("\nvar %sTmp %s", m.Keyidx, strings.ToLower(key.Value.String())) p.printf("\n%sTmp, err = %s(%s)", m.Keyidx, fromBase, m.Keyidx) p.wrapErrCheck("\"shim: " + m.Varname() + "\"") p.printf("\n%s[%s(%sTmp)] = %s", m.Varname(), key.FromBase(), m.Keyidx, m.Validx) } else { p.printf("\n%s[%s(%s)] = %s", m.Varname(), fromBase, m.Keyidx, m.Validx) } return } } } p.printf("\n%s[%s] = %s", m.Varname(), m.Keyidx, m.Validx) } // clear map keys func (p *printer) clearMap(name string) { p.printf("\nclear(%[1]s)", name) } func (p *printer) wrapErrCheck(ctx string) { p.print("\nif err != nil {") if ctx != "" { p.printf("\nerr = msgp.WrapError(err, %s)", ctx) } else { p.print("\nerr = msgp.WrapError(err)") } p.printf("\nreturn") p.print("\n}") } func (p *printer) resizeSlice(size string, s *Slice) { p.printf("\nif cap(%[1]s) >= int(%[2]s) { %[1]s = (%[1]s)[:%[2]s] } else { %[1]s = make(%[3]s, %[2]s) }", s.Varname(), size, s.TypeName()) } // resizeSliceNoNil will resize a slice and will not allow nil slices. func (p *printer) resizeSliceNoNil(size string, s *Slice) { p.printf("\nif %[1]s != nil && cap(%[1]s) >= int(%[2]s) {", s.Varname(), size) p.printf("\n%[1]s = (%[1]s)[:%[2]s]", s.Varname(), size) p.printf("\n} else { %[1]s = make(%[3]s, %[2]s) }", s.Varname(), size, s.TypeName()) } func (p *printer) arrayCheck(want string, got string) { p.printf("\nif %[1]s != %[2]s { err = msgp.ArrayError{Wanted: %[2]s, Got: %[1]s}; return }", got, want) } func (p *printer) closeblock() { p.print("\n}") } // does: // // for idx := range iter { // {{generate inner}} // } func (p *printer) rangeBlock(ctx *Context, idx string, iter string, t traversal, inner Elem) { ctx.PushVar(idx) // Tags on slices do not extend to the elements, so we always disable allownil on elements. // If we want this to happen in the future, it should be a unique tag. inner.SetIsAllowNil(false) p.printf("\n for %s := range %s {", idx, iter) next(t, inner) p.closeblock() ctx.Pop() } func (p *printer) nakedReturn() { if p.ok() { p.print("\nreturn\n}\n") } } func (p *printer) comment(s string) { p.print("\n// " + s) } func (p *printer) printf(format string, args ...any) { if p.err == nil { _, p.err = fmt.Fprintf(p.w, format, args...) } } func (p *printer) print(format string) { if p.err == nil { _, p.err = io.WriteString(p.w, format) } } func (p *printer) initPtr(pt *Ptr) { if pt.Needsinit() { vname := pt.Varname() p.printf("\nif %s == nil { %s = new(%s); }", vname, vname, pt.Value.TypeName()) } } func (p *printer) ok() bool { return p.err == nil } func tobaseConvert(b *BaseElem) string { return b.ToBase() + "(" + b.Varname() + ")" } func (p *printer) varWriteMapHeader(receiver string, sizeVarname string, maxSize int) { if maxSize <= 15 { p.printf("\nerr = %s.Append(0x80 | uint8(%s))", receiver, sizeVarname) } else { p.printf("\nerr = %s.WriteMapHeader(%s)", receiver, sizeVarname) } } func (p *printer) varAppendMapHeader(sliceVarname string, sizeVarname string, maxSize int) { if maxSize <= 15 { p.printf("\n%s = append(%s, 0x80 | uint8(%s))", sliceVarname, sliceVarname, sizeVarname) } else { p.printf("\n%s = msgp.AppendMapHeader(%s, %s)", sliceVarname, sliceVarname, sizeVarname) } } // bmask is a bitmask of a the specified number of bits type bmask struct { bitlen int varname string } // typeDecl returns the variable declaration as a var statement func (b *bmask) typeDecl() string { return fmt.Sprintf("var %s %s /* %d bits */", b.varname, b.typeName(), b.bitlen) } // typeName returns the type, e.g. "uint8" or "[2]uint64" func (b *bmask) typeName() string { if b.bitlen <= 8 { return "uint8" } if b.bitlen <= 16 { return "uint16" } if b.bitlen <= 32 { return "uint32" } if b.bitlen <= 64 { return "uint64" } return fmt.Sprintf("[%d]uint64", (b.bitlen+64-1)/64) } // readExpr returns the expression to read from a position in the bitmask. // Compare ==0 for false or !=0 for true. func (b *bmask) readExpr(bitoffset int) string { if bitoffset < 0 || bitoffset >= b.bitlen { panic(fmt.Errorf("bitoffset %d out of range for bitlen %d", bitoffset, b.bitlen)) } var buf bytes.Buffer buf.Grow(len(b.varname) + 16) buf.WriteByte('(') buf.WriteString(b.varname) if b.bitlen > 64 { fmt.Fprintf(&buf, "[%d]", (bitoffset / 64)) } buf.WriteByte('&') fmt.Fprintf(&buf, "0x%X", (uint64(1) << (uint64(bitoffset) % 64))) buf.WriteByte(')') return buf.String() } // setStmt returns the statement to set the specified bit in the bitmask. func (b *bmask) setStmt(bitoffset int) string { var buf bytes.Buffer buf.Grow(len(b.varname) + 16) buf.WriteString(b.varname) if b.bitlen > 64 { fmt.Fprintf(&buf, "[%d]", (bitoffset / 64)) } fmt.Fprintf(&buf, " |= 0x%X", (uint64(1) << (uint64(bitoffset) % 64))) return buf.String() } // notAllSet returns a check against all fields having been set in set. func (b *bmask) notAllSet() string { var buf bytes.Buffer buf.Grow(len(b.varname) + 16) buf.WriteString(b.varname) if b.bitlen > 64 { var bytes []string remain := b.bitlen for remain >= 8 { bytes = append(bytes, "0xff") } if remain > 0 { bytes = append(bytes, fmt.Sprintf("0x%X", remain)) } fmt.Fprintf(&buf, " != [%d]byte{%s}\n", (b.bitlen+63)/64, strings.Join(bytes, ",")) } fmt.Fprintf(&buf, " != 0x%x", uint64(1< 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 BenchmarkMarshalMsg{{.TypeName}}(b *testing.B) { v := {{.TypeName}}{} b.ReportAllocs() b.ResetTimer() for i:=0; i m { t.Log("WARNING: TestEncodeDecode{{.TypeName}} Msgsize() is inaccurate") } vn := {{.TypeName}}{} 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 BenchmarkEncode{{.TypeName}}(b *testing.B) { v := {{.TypeName}}{} 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 context field limit > file limit var limit uint32 var limitName string if fieldLimit > 0 { // Explicit field limit passed as parameter limit = fieldLimit limitName = fmt.Sprintf("%d", fieldLimit) } else if u.ctx.currentFieldArrayLimit != math.MaxUint32 { // Field limit from context (set during field processing) limit = u.ctx.currentFieldArrayLimit limitName = fmt.Sprintf("%d", u.ctx.currentFieldArrayLimit) } else if u.ctx.arrayLimit != math.MaxUint32 { // File-level limit limit = u.ctx.arrayLimit limitName = fmt.Sprintf("%slimitArrays", u.ctx.limitPrefix) } if limit > 0 && limit != math.MaxUint32 { u.p.printf("\nif %s > %s {", name, limitName) u.p.printf("\nerr = msgp.ErrLimitExceeded") u.p.printf("\nreturn") u.p.printf("\n}") } } func (u *unmarshalGen) assignMap(name string, base string, fieldLimit uint32) { if !u.p.ok() { return } u.p.printf("\n%s, bts, err = msgp.Read%sBytes(bts)", name, base) u.p.wrapErrCheck(u.ctx.ArgsStr()) // Determine effective limit: field limit > context field limit > file limit var limit uint32 var limitName string if fieldLimit > 0 { // Explicit field limit passed as parameter limit = fieldLimit limitName = fmt.Sprintf("%d", fieldLimit) } else if u.ctx.currentFieldMapLimit != math.MaxUint32 { // Field limit from context (set during field processing) limit = u.ctx.currentFieldMapLimit limitName = fmt.Sprintf("%d", u.ctx.currentFieldMapLimit) } else if u.ctx.mapLimit != math.MaxUint32 { // File-level limit limit = u.ctx.mapLimit limitName = fmt.Sprintf("%slimitMaps", u.ctx.limitPrefix) } if limit > 0 && limit != math.MaxUint32 { u.p.printf("\nif %s > %s {", name, limitName) u.p.printf("\nerr = msgp.ErrLimitExceeded") u.p.printf("\nreturn") u.p.printf("\n}") } } // Returns whether a nil check should be done func (u *unmarshalGen) readBytesWithLimit(refname, lowered string, zerocopy bool, fieldLimit uint32) bool { if !u.p.ok() { return false } // Determine effective limit: field limit > context field limit > file limit var limit uint32 var limitName string if fieldLimit > 0 { // Explicit field limit passed as parameter limit = fieldLimit limitName = fmt.Sprintf("%d", fieldLimit) } else if u.ctx.currentFieldArrayLimit != math.MaxUint32 { // Field limit from context (set during field processing) limit = u.ctx.currentFieldArrayLimit limitName = fmt.Sprintf("%d", u.ctx.currentFieldArrayLimit) } else if u.ctx.arrayLimit != math.MaxUint32 { // File-level limit limit = u.ctx.arrayLimit limitName = fmt.Sprintf("%slimitArrays", u.ctx.limitPrefix) } // Choose reading strategy based on whether limits exist if limit > 0 && limit != math.MaxUint32 { // Limits exist - use header-first security approach sz := randIdent() u.p.printf("\nvar %s uint32", sz) u.p.printf("\n%s, bts, err = msgp.ReadBytesHeader(bts)", sz) u.p.wrapErrCheck(u.ctx.ArgsStr()) // Check size against limit before allocating u.p.printf("\nif %s > %s {", sz, limitName) u.p.printf("\nerr = msgp.ErrLimitExceeded") u.p.printf("\nreturn") u.p.printf("\n}") // Now safely read the data if zerocopy { u.p.printf("\nif uint32(len(bts)) < %s {", sz) u.p.printf("\nerr = msgp.ErrShortBytes") u.p.printf("\nreturn") u.p.printf("\n}") u.p.printf("\n%s = bts[:%s]", refname, sz) u.p.printf("\nbts = bts[%s:]", sz) } else { if refname != lowered { u.p.printf("\n%s = %s", refname, lowered) } u.p.printf("\nif %s == nil || uint32(cap(%s)) < %s {", refname, refname, sz) u.p.printf("\n%s = make([]byte, %s)", refname, sz) u.p.printf("\n} else {") u.p.printf("\n%s = %s[:%s]", refname, refname, sz) u.p.printf("\n}") u.p.printf("\nif uint32(len(bts)) < %s {", sz) u.p.printf("\nerr = msgp.ErrShortBytes") u.p.printf("\nreturn") u.p.printf("\n}") u.p.printf("\ncopy(%s, bts[:%s])", refname, sz) u.p.printf("\nbts = bts[%s:]", sz) } return false } else { // No limits - use original direct reading approach for efficiency if zerocopy { u.p.printf("\n%s, bts, err = msgp.ReadBytesZC(bts)", refname) } else { u.p.printf("\n%s, bts, err = msgp.ReadBytesBytes(bts, %s)", refname, lowered) } u.p.wrapErrCheck(u.ctx.ArgsStr()) return !zerocopy } } func (u *unmarshalGen) gStruct(s *Struct) { if !u.p.ok() { return } if s.AsTuple { u.tuple(s) } else { u.mapstruct(s) } } func (u *unmarshalGen) tuple(s *Struct) { // open block sz := randIdent() u.p.declare(sz, u32) u.assignAndCheck(sz, arrayHeader) if s.AsVarTuple { u.p.printf("\nif %[1]s == 0 {\no = bts\nreturn\n}", sz) } else { u.p.arrayCheck(strconv.Itoa(len(s.Fields)), sz) } for i := range s.Fields { if !u.p.ok() { return } u.ctx.PushString(s.Fields[i].FieldName) fieldElem := s.Fields[i].FieldElem anField := s.Fields[i].HasTagPart("allownil") && fieldElem.AllowNil() // Set field-specific limits in context based on struct field's FieldLimit if s.Fields[i].FieldLimit > 0 { // Apply same limit to both arrays and maps for this field u.ctx.SetFieldLimits(s.Fields[i].FieldLimit, s.Fields[i].FieldLimit) } else { u.ctx.ClearFieldLimits() } if anField { u.p.printf("\nif msgp.IsNil(bts) {\nbts = bts[1:]\n%s = nil\n} else {", fieldElem.Varname()) } SetIsAllowNil(fieldElem, anField) if s.Fields[i].HasTagPart("zerocopy") { setRecursiveZC(fieldElem, true) } setTypeParams(fieldElem, s.typeParams) next(u, fieldElem) // Clear field limits after processing u.ctx.ClearFieldLimits() if s.Fields[i].HasTagPart("zerocopy") { setRecursiveZC(fieldElem, false) } u.ctx.Pop() if anField { u.p.printf("\n}") } if s.AsVarTuple { u.p.printf("\nif %[1]s--; %[1]s == 0 {\no = bts\nreturn\n}", sz) } } if s.AsVarTuple { u.p.printf("\nfor ; %[1]s > 0; %[1]s-- {\nbts, err = msgp.Skip(bts)\nif err != nil {\nerr = msgp.WrapError(err)\nreturn\n}\n}", sz) } } // setRecursiveZC will alloc zerocopy for byte fields that are present. func setRecursiveZC(e Elem, enable bool) { if base, ok := e.(*BaseElem); ok { base.zerocopy = enable } if el, ok := e.(*Slice); ok { setRecursiveZC(el.Els, enable) } if el, ok := e.(*Array); ok { setRecursiveZC(el.Els, enable) } if el, ok := e.(*Map); ok { setRecursiveZC(el.Value, enable) } } func (u *unmarshalGen) mapstruct(s *Struct) { u.needsField() sz := randIdent() u.p.declare(sz, u32) u.assignMap(sz, mapHeader, 0) oeCount := s.CountFieldTagPart("omitempty") + s.CountFieldTagPart("omitzero") if !u.ctx.clearOmitted { oeCount = 0 } bm := bmask{ bitlen: oeCount, varname: sz + "Mask", } if oeCount > 0 { // Declare mask u.p.printf("\n%s", bm.typeDecl()) u.p.printf("\n_ = %s", bm.varname) } // Index to field idx of each emitted oeEmittedIdx := []int{} u.p.printf("\nfor %s > 0 {", sz) u.p.printf("\n%s--; field, bts, err = msgp.ReadMapKeyZC(bts)", sz) u.p.wrapErrCheck(u.ctx.ArgsStr()) u.p.print("\nswitch msgp.UnsafeString(field) {") for i := range s.Fields { if !u.p.ok() { return } u.p.printf("\ncase %q:", s.Fields[i].FieldTag) u.ctx.PushString(s.Fields[i].FieldName) fieldElem := s.Fields[i].FieldElem anField := s.Fields[i].HasTagPart("allownil") && fieldElem.AllowNil() // Set field-specific limits in context based on struct field's FieldLimit if s.Fields[i].FieldLimit > 0 { // Apply same limit to both arrays and maps for this field u.ctx.SetFieldLimits(s.Fields[i].FieldLimit, s.Fields[i].FieldLimit) } else { u.ctx.ClearFieldLimits() } if anField { u.p.printf("\nif msgp.IsNil(bts) {\nbts = bts[1:]\n%s = nil\n} else {", fieldElem.Varname()) } SetIsAllowNil(fieldElem, anField) if s.Fields[i].HasTagPart("zerocopy") { setRecursiveZC(fieldElem, true) } setTypeParams(fieldElem, s.typeParams) next(u, fieldElem) // Clear field limits after processing u.ctx.ClearFieldLimits() if s.Fields[i].HasTagPart("zerocopy") { setRecursiveZC(fieldElem, false) } u.ctx.Pop() if oeCount > 0 && (s.Fields[i].HasTagPart("omitempty") || s.Fields[i].HasTagPart("omitzero")) { u.p.printf("\n%s", bm.setStmt(len(oeEmittedIdx))) oeEmittedIdx = append(oeEmittedIdx, i) } if anField { u.p.printf("\n}") } } u.p.print("\ndefault:\nbts, err = msgp.Skip(bts)") u.p.wrapErrCheck(u.ctx.ArgsStr()) u.p.print("\n}\n}") // close switch and for loop if oeCount > 0 { u.p.printf("\n// Clear omitted fields.\n") if bm.bitlen > 1 { u.p.printf("if %s {\n", bm.notAllSet()) } for bitIdx, fieldIdx := range oeEmittedIdx { fieldElem := s.Fields[fieldIdx].FieldElem u.p.printf("if %s == 0 {\n", bm.readExpr(bitIdx)) fze := fieldElem.ZeroExpr() if fze != "" { u.p.printf("%s = %s\n", fieldElem.Varname(), fze) } else { u.p.printf("%s = %s{}\n", fieldElem.Varname(), fieldElem.TypeName()) } u.p.printf("}\n") } if bm.bitlen > 1 { u.p.printf("}") } } } // binaryUnmarshalCall generates code for unmarshaling marshaler/appender interfaces func (u *unmarshalGen) binaryUnmarshalCall(refname, unmarshalMethod, readType string) { tmpBytes := randIdent() refname = strings.Trim(refname, "(*)") u.p.printf("\nvar %s []byte", tmpBytes) if readType == "String" { u.p.printf("\n%s, bts, err = msgp.ReadStringZC(bts)", tmpBytes) } else { u.p.printf("\n%s, bts, err = msgp.ReadBytesZC(bts)", tmpBytes) } u.p.wrapErrCheck(u.ctx.ArgsStr()) u.p.printf("\nerr = %s.%s(%s)", refname, unmarshalMethod, tmpBytes) } func (u *unmarshalGen) gBase(b *BaseElem) { if !u.p.ok() { return } refname := b.Varname() // assigned to lowered := b.Varname() // passed as argument // begin 'tmp' block if b.Convert && b.Value != IDENT { // we don't need block for 'tmp' in case of IDENT refname = randIdent() lowered = b.ToBase() + "(" + lowered + ")" u.p.printf("\n{\nvar %s %s", refname, b.BaseType()) } nilCheck := false switch b.Value { case Bytes: nilCheck = u.readBytesWithLimit(refname, lowered, b.zerocopy, 0) case Ext: u.p.printf("\nbts, err = msgp.ReadExtensionBytes(bts, %s)", lowered) case BinaryMarshaler, BinaryAppender: u.binaryUnmarshalCall(refname, "UnmarshalBinary", "Bytes") case TextMarshalerBin, TextAppenderBin: u.binaryUnmarshalCall(refname, "UnmarshalText", "Bytes") case TextMarshalerString, TextAppenderString: u.binaryUnmarshalCall(refname, "UnmarshalText", "String") case IDENT: if b.Convert { lowered = b.ToBase() + "(" + lowered + ")" } dst := b.BaseType() if b.typeParams.isPtr { dst = "*" + dst } if remap := b.typeParams.ToPointerMap[stripTypeParams(dst)]; remap != "" { lowered = fmt.Sprintf(remap, lowered) } u.p.printf("\nbts, err = %s.UnmarshalMsg(bts)", lowered) case Time: if u.ctx.asUTC { u.p.printf("\n%s, bts, err = msgp.Read%sUTCBytes(bts)", refname, b.BaseName()) } else { u.p.printf("\n%s, bts, err = msgp.Read%sBytes(bts)", refname, b.BaseName()) } case AInt64, AInt32, AUint64, AUint32, ABool: tmp := randIdent() t := strings.TrimPrefix(b.BaseName(), "atomic.") u.p.printf("\n var %s %s", tmp, strings.ToLower(t)) u.p.printf("\n%s, bts, err = msgp.Read%sBytes(bts)", tmp, t) u.p.printf("\n%s.Store(%s)", strings.TrimPrefix(refname, "*"), tmp) default: u.p.printf("\n%s, bts, err = msgp.Read%sBytes(bts)", refname, b.BaseName()) } if b.Value != Bytes { u.p.wrapErrCheck(u.ctx.ArgsStr()) } if nilCheck && b.AllowNil() { // Ensure that 0 sized slices are allocated. // We are inside the path where the value wasn't nil. u.p.printf("\nif %s == nil {\n%s = make([]byte, 0)\n}", refname, refname) } // close 'tmp' block if b.Convert && b.Value != IDENT { if b.ShimMode == Cast && !b.ShimErrs { u.p.printf("\n%s = %s(%s)\n", b.Varname(), b.FromBase(), refname) } else { u.p.printf("\n%s, err = %s(%s)\n", b.Varname(), b.FromBase(), refname) u.p.wrapErrCheck(u.ctx.ArgsStr()) } u.p.printf("}") } } func (u *unmarshalGen) gArray(a *Array) { if !u.p.ok() { return } // special case for [const]byte objects // see decode.go for symmetry if be, ok := a.Els.(*BaseElem); ok && be.Value == Byte { u.p.printf("\nbts, err = msgp.ReadExactBytes(bts, (%s)[:])", a.Varname()) u.p.wrapErrCheck(u.ctx.ArgsStr()) return } sz := randIdent() u.p.declare(sz, u32) u.assignAndCheck(sz, arrayHeader) u.p.arrayCheck(coerceArraySize(a.Size), sz) setTypeParams(a.Els, a.typeParams) u.p.rangeBlock(u.ctx, a.Index, a.Varname(), u, a.Els) } func (u *unmarshalGen) gSlice(s *Slice) { if !u.p.ok() { return } sz := randIdent() u.p.declare(sz, u32) u.assignArray(sz, arrayHeader, 0) if s.isAllowNil { u.p.resizeSliceNoNil(sz, s) } else { u.p.resizeSlice(sz, s) } setTypeParams(s.Els, s.typeParams) u.p.rangeBlock(u.ctx, s.Index, s.Varname(), u, s.Els) } func (u *unmarshalGen) gMap(m *Map) { if !u.p.ok() { return } sz := randIdent() u.p.declare(sz, u32) u.assignMap(sz, mapHeader, 0) // allocate or clear map u.p.resizeMap(sz, m) // We likely need a field. // Add now to not be inside for scope. u.needsField() // loop and get key,value u.p.printf("\nfor %s > 0 {", sz) u.p.printf("\nvar %s %s; %s--", m.Validx, m.Value.TypeName(), sz) m.readKey(u.ctx, u.p, u, u.assignAndCheck) u.ctx.PushVar(m.Keyidx) m.Value.SetIsAllowNil(false) setTypeParams(m.Value, m.typeParams) next(u, m.Value) u.ctx.Pop() u.p.mapAssign(m) u.p.closeblock() } func (u *unmarshalGen) gPtr(p *Ptr) { u.p.printf("\nif msgp.IsNil(bts) { bts, err = msgp.ReadNilBytes(bts); if err != nil { return }; %s = nil; } else { ", p.Varname()) u.p.initPtr(p) if p.typeParams.TypeParams != "" { tp := p.typeParams tp.isPtr = true p.Value.SetTypeParams(tp) } next(u, p.Value) u.p.closeblock() } msgp-1.6.1/go.mod000066400000000000000000000002401511433505400135700ustar00rootroot00000000000000module github.com/tinylib/msgp go 1.24 require ( github.com/philhofer/fwd v1.2.0 golang.org/x/tools v0.22.0 ) require golang.org/x/mod v0.18.0 // indirect msgp-1.6.1/go.sum000066400000000000000000000011661511433505400136250ustar00rootroot00000000000000github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM= github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= msgp-1.6.1/helper_test.go000066400000000000000000000026421511433505400153370ustar00rootroot00000000000000package main import ( "os" "os/exec" "path/filepath" "strings" "testing" "github.com/tinylib/msgp/gen" ) const showGeneratedFile = false func generate(t *testing.T, content string) (string, error) { tempDir := t.TempDir() mainFilename := filepath.Join(tempDir, "main.go") fd, err := os.OpenFile(mainFilename, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0o600) if err != nil { return "", err } defer fd.Close() if _, err := fd.WriteString(content); err != nil { return "", err } mode := gen.Encode | gen.Decode | gen.Size | gen.Marshal | gen.Unmarshal | gen.Test if err := Run(mainFilename, mode, false); err != nil { return "", err } if showGeneratedFile { mainGenFilename := strings.TrimSuffix(mainFilename, ".go") + "_gen.go" content, err := os.ReadFile(mainGenFilename) if err != nil { return "", err } t.Logf("generated %s content:\n%s", mainGenFilename, content) } return mainFilename, nil } func goExec(t *testing.T, mainFilename string, test bool) { mainGenFilename := strings.TrimSuffix(mainFilename, ".go") + "_gen.go" args := []string{"run", mainFilename, mainGenFilename} if test { mainGenTestFilename := strings.TrimSuffix(mainFilename, ".go") + "_gen_test.go" args = []string{"test", mainFilename, mainGenFilename, mainGenTestFilename} } output, err := exec.Command("go", args...).CombinedOutput() if err != nil { t.Fatalf("go run failed: %v, output:\n%s", err, output) } } msgp-1.6.1/issue185_test.go000066400000000000000000000152351511433505400154500ustar00rootroot00000000000000package main import ( "fmt" "go/ast" "go/parser" "go/token" "os" "path/filepath" "reflect" "sort" "testing" "text/template" "github.com/tinylib/msgp/gen" ) // When stuff's going wrong, you'll be glad this is here! const debugTemp = false // Ensure that consistent identifiers are generated on a per-method basis by msgp. // // Also ensure that no duplicate identifiers appear in a method. // // structs are currently processed alphabetically by msgp. this test relies on // that property. func TestIssue185Idents(t *testing.T) { identCases := []struct { tpl *template.Template expectedChanged []string }{ {tpl: issue185IdentsTpl, expectedChanged: []string{"Test1"}}, {tpl: issue185ComplexIdentsTpl, expectedChanged: []string{"Test2"}}, } methods := []string{"DecodeMsg", "EncodeMsg", "Msgsize", "MarshalMsg", "UnmarshalMsg"} for idx, identCase := range identCases { // generate the code, extract the generated variable names, mapped to function name var tplData issue185TplData varsBefore, err := loadVars(t, identCase.tpl, tplData) if err != nil { t.Fatalf("%d: could not extract before vars: %v", idx, err) } // regenerate the code with extra field(s), extract the generated variable // names, mapped to function name tplData.Extra = true varsAfter, err := loadVars(t, identCase.tpl, tplData) if err != nil { t.Fatalf("%d: could not extract after vars: %v", idx, err) } // ensure that all declared variable names inside each of the methods we // expect to change have actually changed for _, stct := range identCase.expectedChanged { for _, method := range methods { fn := fmt.Sprintf("%s.%s", stct, method) bv, av := varsBefore.Value(fn), varsAfter.Value(fn) if len(bv) > 0 && len(av) > 0 && reflect.DeepEqual(bv, av) { t.Fatalf("%d vars identical! expected vars to change for %s", idx, fn) } delete(varsBefore, fn) delete(varsAfter, fn) } } // all of the remaining keys should not have changed for bmethod, bvars := range varsBefore { avars := varsAfter.Value(bmethod) if !reflect.DeepEqual(bvars, avars) { t.Fatalf("%d: vars changed! expected vars identical for %s", idx, bmethod) } delete(varsBefore, bmethod) delete(varsAfter, bmethod) } if len(varsBefore) > 0 || len(varsAfter) > 0 { t.Fatalf("%d: unexpected methods remaining", idx) } } } type issue185TplData struct { Extra bool } func TestIssue185Overlap(t *testing.T) { overlapCases := []struct { tpl *template.Template data issue185TplData }{ {tpl: issue185IdentsTpl, data: issue185TplData{Extra: false}}, {tpl: issue185IdentsTpl, data: issue185TplData{Extra: true}}, {tpl: issue185ComplexIdentsTpl, data: issue185TplData{Extra: false}}, {tpl: issue185ComplexIdentsTpl, data: issue185TplData{Extra: true}}, } for idx, o := range overlapCases { // regenerate the code with extra field(s), extract the generated variable // names, mapped to function name mvars, err := loadVars(t, o.tpl, o.data) if err != nil { t.Fatalf("%d: could not extract after vars: %v", idx, err) } identCnt := 0 for fn, vars := range mvars { sort.Strings(vars) // Loose sanity check to make sure the tests expectations aren't broken. // If the prefix ever changes, this needs to change. for _, v := range vars { if v[0] == 'z' { identCnt++ } } for i := 0; i < len(vars)-1; i++ { if vars[i] == vars[i+1] { t.Fatalf("%d: duplicate var %s in function %s", idx, vars[i], fn) } } } // one last sanity check: if there aren't any vars that start with 'z', // this test's expectations are unsatisfiable. if identCnt == 0 { t.Fatalf("%d: no generated identifiers found", idx) } } } func loadVars(t *testing.T, tpl *template.Template, tplData any) (vars extractedVars, err error) { tempDir := t.TempDir() if !debugTemp { defer os.RemoveAll(tempDir) } else { fmt.Println(tempDir) } tfile := filepath.Join(tempDir, "msg.go") genFile := newFilename(tfile, "") if err = goGenerateTpl(tempDir, tfile, tpl, tplData); err != nil { err = fmt.Errorf("could not generate code: %v", err) return } vars, err = extractVars(genFile) if err != nil { err = fmt.Errorf("could not extract after vars: %v", err) return } return } type varVisitor struct { vars []string fset *token.FileSet } func (v *varVisitor) Visit(node ast.Node) (w ast.Visitor) { gen, ok := node.(*ast.GenDecl) if !ok { return v } for _, spec := range gen.Specs { if vspec, ok := spec.(*ast.ValueSpec); ok { for _, n := range vspec.Names { v.vars = append(v.vars, n.Name) } } } return v } type extractedVars map[string][]string func (e extractedVars) Value(key string) []string { if v, ok := e[key]; ok { return v } panic(fmt.Errorf("unknown key %s", key)) } func extractVars(file string) (extractedVars, error) { fset := token.NewFileSet() f, err := parser.ParseFile(fset, file, nil, 0) if err != nil { return nil, err } vars := make(map[string][]string) for _, d := range f.Decls { switch d := d.(type) { case *ast.FuncDecl: sn := "" switch rt := d.Recv.List[0].Type.(type) { case *ast.Ident: sn = rt.Name case *ast.StarExpr: sn = rt.X.(*ast.Ident).Name default: panic("unknown receiver type") } key := fmt.Sprintf("%s.%s", sn, d.Name.Name) vis := &varVisitor{fset: fset} ast.Walk(vis, d.Body) vars[key] = vis.vars } } return vars, nil } func goGenerateTpl(cwd, tfile string, tpl *template.Template, tplData any) error { outf, err := os.OpenFile(tfile, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0o600) if err != nil { return err } defer outf.Close() if err := tpl.Execute(outf, tplData); err != nil { return err } mode := gen.Encode | gen.Decode | gen.Size | gen.Marshal | gen.Unmarshal return Run(tfile, mode, false) } var issue185IdentsTpl = template.Must(template.New("").Parse(` package issue185 //go:generate msgp type Test1 struct { Foo string Bar string {{ if .Extra }}Baz []string{{ end }} Qux string } type Test2 struct { Foo string Bar string Baz string } `)) var issue185ComplexIdentsTpl = template.Must(template.New("").Parse(` package issue185 //go:generate msgp type Test1 struct { Foo string Bar string Baz string } type Test2 struct { Foo string Bar string Baz []string Qux map[string]string Yep map[string]map[string]string Quack struct { Quack struct { Quack struct { {{ if .Extra }}Extra []string{{ end }} Quack string } } } Nup struct { Foo string Bar string Baz []string Qux map[string]string Yep map[string]map[string]string } Ding struct { Dong struct { Dung struct { Thing string } } } } type Test3 struct { Foo string Bar string Baz string } `)) msgp-1.6.1/issue275_test.go000066400000000000000000000047721511433505400154540ustar00rootroot00000000000000package main import "testing" func TestIssue275Tuples(t *testing.T) { mainFilename, err := generate(t, issue275Tuples) if err != nil { t.Fatalf("generate failed: %v", err) } goExec(t, mainFilename, false) // exec go run goExec(t, mainFilename, true) // exec go test } var issue275Tuples = `package main import ( "fmt" "os" ) //go:generate msgp //msgp:tuple Test1 type Test1 struct { Foo string } //msgp:tuple Test2 type Test2 struct { Foo string Bar string } //msgp:tuple Test3 type Test3 struct { Foo string Bar string Baz string } //msgp:vartuple Test type Test struct { Foo string Bar string } func main() { t1 := Test1{Foo: "Foo1"} d1, err := t1.MarshalMsg(nil) if err != nil { fmt.Println("Test1 MarshalMsg failed:", err) os.Exit(1) } t2 := Test2{Foo: "Foo2", Bar: "Bar2"} d2, err := t2.MarshalMsg(nil) if err != nil { fmt.Println("Test2 MarshalMsg failed:", err) os.Exit(1) } t3 := Test3{Foo: "Foo3", Bar: "Bar3", Baz: "Baz3"} d3, err := t3.MarshalMsg(nil) if err != nil { fmt.Println("Test3 MarshalMsg failed:", err) os.Exit(1) } var msg Test msg = Test{} if _, err := msg.UnmarshalMsg(d1); err != nil { fmt.Println("Test UnmarshalMsg from Test1 failed:", err) os.Exit(1) } if msg.Foo != "Foo1" { fmt.Println("Test UnmarshalMsg from Test1 bad msg:", msg) os.Exit(1) } msg = Test{} if _, err := msg.UnmarshalMsg(d2); err != nil { fmt.Println("Test UnmarshalMsg from Test2 failed:", err) os.Exit(1) } if msg.Foo != "Foo2" || msg.Bar != "Bar2" { fmt.Println("Test UnmarshalMsg from Test2 bad msg:", msg) os.Exit(1) } msg = Test{} if _, err := msg.UnmarshalMsg(d3); err != nil { fmt.Println("Test UnmarshalMsg from Test3 failed:", err) os.Exit(1) } if msg.Foo != "Foo3" || msg.Bar != "Bar3" { fmt.Println("Test UnmarshalMsg from Test3 bad msg:", msg) os.Exit(1) } var msg1 Test1 if _, err := msg1.UnmarshalMsg(d2); err != nil { if err.Error() != "msgp: wanted array of size 1; got 2" { fmt.Println("Test1 UnmarshalMsg from Test2 failed:", err) os.Exit(1) } } var msg2 Test2 if _, err := msg2.UnmarshalMsg(d2); err != nil { fmt.Println("Test2 UnmarshalMsg from Test2 failed:", err) os.Exit(1) } if msg2.Foo != "Foo2" || msg2.Bar != "Bar2" { fmt.Println("Test3 UnmarshalMsg from Test2 bad msg:", msg) os.Exit(1) } var msg3 Test3 if _, err := msg3.UnmarshalMsg(d2); err != nil { if err.Error() != "msgp: wanted array of size 3; got 2" { fmt.Println("Test3 UnmarshalMsg from Test2 failed:", err) os.Exit(1) } } } ` msgp-1.6.1/issue395_test.go000066400000000000000000000016401511433505400154460ustar00rootroot00000000000000package main import "testing" func TestIssue395TupleAllownil(t *testing.T) { mainFilename, err := generate(t, issue395TupleAllownil) if err != nil { t.Fatalf("generate failed: %v", err) } goExec(t, mainFilename, false) // exec go run goExec(t, mainFilename, true) // exec go test } var issue395TupleAllownil = `package main import ( "fmt" "os" ) //go:generate msgp //msgp:tuple User type User struct { ID []byte ` + "`msgpack:\",allownil\"`" + ` Name string Email string IsActive bool } func main() { u := User{ID: nil, Name: "user"} data, err := u.MarshalMsg(nil) if err != nil { fmt.Println("User MarshalMsg failed:", err) os.Exit(1) } var user User if _, err := user.UnmarshalMsg(data); err != nil { fmt.Println("User UnmarshalMsg failed:", err) os.Exit(1) } if user.ID != nil || user.Name != "user" { fmt.Println("User UnmarshalMsg bad user:", user) os.Exit(1) } } ` msgp-1.6.1/main.go000066400000000000000000000101341511433505400137400ustar00rootroot00000000000000// msgp is a code generation tool for // creating methods to serialize and de-serialize // Go data structures to and from MessagePack. // // This package is targeted at the `go generate` tool. // To use it, include the following directive in a // go source file with types requiring source generation: // // //go:generate msgp // // The go generate tool should set the proper environment variables for // the generator to execute without any command-line flags. However, the // following options are supported, if you need them: // // -o = output file name (default is {input}_gen.go) // -file = input file name (or directory; default is $GOFILE, which is set by the `go generate` command) // -io = satisfy the `msgp.Decodable` and `msgp.Encodable` interfaces (default is true) // -marshal = satisfy the `msgp.Marshaler` and `msgp.Unmarshaler` interfaces (default is true) // -tests = generate tests and benchmarks (default is true) // // For more information, please read README.md, and the wiki at github.com/tinylib/msgp package main import ( "flag" "fmt" "os" "path/filepath" "strings" "github.com/tinylib/msgp/gen" "github.com/tinylib/msgp/parse" "github.com/tinylib/msgp/printer" ) var ( out = flag.String("o", "", "output file") file = flag.String("file", "", "input file") encode = flag.Bool("io", true, "create Encode and Decode methods") marshal = flag.Bool("marshal", true, "create Marshal and Unmarshal methods") tests = flag.Bool("tests", true, "create tests and benchmarks") unexported = flag.Bool("unexported", false, "also process unexported types and fields") verbose = flag.Bool("v", false, "verbose diagnostics") directives = stringArrFlags{} ) func diagf(f string, args ...any) { if !*verbose { return } if f[len(f)-1] != '\n' { f += "\n" } fmt.Fprintf(os.Stderr, f, args...) } func exitln(res string) { fmt.Fprintln(os.Stderr, res) os.Exit(1) } func main() { flag.Var(&directives, "d", "apply directive to all files. Multiple -d flags allowed. 'msgp:' can be omitted") flag.Parse() if *verbose { printer.Logf = diagf parse.Logf = diagf } for i, v := range directives { // Trim prefix and whitespace, if any. directives[i] = strings.TrimPrefix(strings.TrimSpace(v), "msgp:") } // GOFILE is set by go generate if *file == "" { *file = os.Getenv("GOFILE") if *file == "" { exitln("No file to parse.") } } var mode gen.Method if *encode { mode |= (gen.Encode | gen.Decode | gen.Size) } if *marshal { mode |= (gen.Marshal | gen.Unmarshal | gen.Size) } if *tests { mode |= gen.Test } if mode&^gen.Test == 0 { exitln("No methods to generate; -io=false && -marshal=false") } if err := Run(*file, mode, *unexported); err != nil { exitln(err.Error()) } } // Run writes all methods using the associated file or path, e.g. // // err := msgp.Run("path/to/myfile.go", gen.Size|gen.Marshal|gen.Unmarshal|gen.Test, false) func Run(gofile string, mode gen.Method, unexported bool) error { if mode&^gen.Test == 0 { return nil } diagf("Input: \"%s\"\n", gofile) fs, err := parse.File(gofile, unexported, directives) if err != nil { return err } if len(fs.Identities) == 0 { diagf("No types requiring code generation were found!") } return printer.PrintFile(newFilename(gofile, fs.Package), fs, mode) } // picks a new file name based on input flags and input filename(s). func newFilename(old string, pkg string) string { if *out != "" { if pre := strings.TrimPrefix(*out, old); len(pre) > 0 && !strings.HasSuffix(*out, ".go") { return filepath.Join(old, *out) } return *out } if fi, err := os.Stat(old); err == nil && fi.IsDir() { old = filepath.Join(old, pkg) } // new file name is old file name + _gen.go return strings.TrimSuffix(old, ".go") + "_gen.go" } // stringArrFlags is a flag.Value that accepts multiple values type stringArrFlags []string // String is an implementation of the flag.Value interface func (i *stringArrFlags) String() string { return fmt.Sprintf("%v", *i) } // Set is an implementation of the flag.Value interface func (i *stringArrFlags) Set(value string) error { *i = append(*i, value) return nil } msgp-1.6.1/msgp/000077500000000000000000000000001511433505400134345ustar00rootroot00000000000000msgp-1.6.1/msgp/advise_linux.go000066400000000000000000000006611511433505400164600ustar00rootroot00000000000000//go:build linux && !appengine && !tinygo package msgp import ( "os" "syscall" ) func adviseRead(mem []byte) { syscall.Madvise(mem, syscall.MADV_SEQUENTIAL|syscall.MADV_WILLNEED) } func adviseWrite(mem []byte) { syscall.Madvise(mem, syscall.MADV_SEQUENTIAL) } func fallocate(f *os.File, sz int64) error { err := syscall.Fallocate(int(f.Fd()), 0, 0, sz) if err == syscall.ENOTSUP { return f.Truncate(sz) } return err } msgp-1.6.1/msgp/advise_other.go000066400000000000000000000003761511433505400164450ustar00rootroot00000000000000//go:build (!linux && !tinygo && !windows) || appengine package msgp import ( "os" ) // TODO: darwin, BSD support func adviseRead(mem []byte) {} func adviseWrite(mem []byte) {} func fallocate(f *os.File, sz int64) error { return f.Truncate(sz) } msgp-1.6.1/msgp/autoshim.go000066400000000000000000000107001511433505400156120ustar00rootroot00000000000000package msgp import "strconv" // AutoShim provides helper functions for converting between string and // numeric types. type AutoShim struct{} // ParseUint converts a string to a uint. func (a AutoShim) ParseUint(s string) (uint, error) { v, err := strconv.ParseUint(s, 10, strconv.IntSize) return uint(v), err } // ParseUint8 converts a string to a uint8. func (a AutoShim) ParseUint8(s string) (uint8, error) { v, err := strconv.ParseUint(s, 10, 8) return uint8(v), err } // ParseUint16 converts a string to a uint16. func (a AutoShim) ParseUint16(s string) (uint16, error) { v, err := strconv.ParseUint(s, 10, 16) return uint16(v), err } // ParseUint32 converts a string to a uint32. func (a AutoShim) ParseUint32(s string) (uint32, error) { v, err := strconv.ParseUint(s, 10, 32) return uint32(v), err } // ParseUint64 converts a string to a uint64. func (a AutoShim) ParseUint64(s string) (uint64, error) { v, err := strconv.ParseUint(s, 10, 64) return v, err } // ParseInt converts a string to an int. func (a AutoShim) ParseInt(s string) (int, error) { v, err := strconv.ParseInt(s, 10, strconv.IntSize) return int(v), err } // ParseInt8 converts a string to an int8. func (a AutoShim) ParseInt8(s string) (int8, error) { v, err := strconv.ParseInt(s, 10, 8) return int8(v), err } // ParseInt16 converts a string to an int16. func (a AutoShim) ParseInt16(s string) (int16, error) { v, err := strconv.ParseInt(s, 10, 16) return int16(v), err } // ParseInt32 converts a string to an int32. func (a AutoShim) ParseInt32(s string) (int32, error) { v, err := strconv.ParseInt(s, 10, 32) return int32(v), err } // ParseInt64 converts a string to an int64. func (a AutoShim) ParseInt64(s string) (int64, error) { v, err := strconv.ParseInt(s, 10, 64) return v, err } // ParseBool converts a string to a bool. func (a AutoShim) ParseBool(s string) (bool, error) { return strconv.ParseBool(s) } // ParseFloat64 converts a string to a float64. func (a AutoShim) ParseFloat64(s string) (float64, error) { return strconv.ParseFloat(s, 64) } // ParseFloat32 converts a string to a float32. func (a AutoShim) ParseFloat32(s string) (float32, error) { v, err := strconv.ParseFloat(s, 32) return float32(v), err } // ParseByte converts a string to a byte. func (a AutoShim) ParseByte(s string) (byte, error) { v, err := strconv.ParseUint(s, 10, 8) return byte(v), err } // Uint8String returns the string representation of a uint8. func (a AutoShim) Uint8String(v uint8) string { return strconv.FormatUint(uint64(v), 10) } // UintString returns the string representation of a uint. func (a AutoShim) UintString(v uint) string { return strconv.FormatUint(uint64(v), 10) } // Uint16String returns the string representation of a uint16. func (a AutoShim) Uint16String(v uint16) string { return strconv.FormatUint(uint64(v), 10) } // Uint32String returns the string representation of a uint32. func (a AutoShim) Uint32String(v uint32) string { return strconv.FormatUint(uint64(v), 10) } // Uint64String returns the string representation of a uint64. func (a AutoShim) Uint64String(v uint64) string { return strconv.FormatUint(v, 10) } // IntString returns the string representation of an int. func (a AutoShim) IntString(v int) string { return strconv.FormatInt(int64(v), 10) } // Int8String returns the string representation of an int8. func (a AutoShim) Int8String(v int8) string { return strconv.FormatInt(int64(v), 10) } // Int16String returns the string representation of an int16. func (a AutoShim) Int16String(v int16) string { return strconv.FormatInt(int64(v), 10) } // Int32String returns the string representation of an int32. func (a AutoShim) Int32String(v int32) string { return strconv.FormatInt(int64(v), 10) } // Int64String returns the string representation of an int64. func (a AutoShim) Int64String(v int64) string { return strconv.FormatInt(v, 10) } // BoolString returns the string representation of a bool. func (a AutoShim) BoolString(v bool) string { return strconv.FormatBool(v) } // Float64String returns the string representation of a float64. func (a AutoShim) Float64String(v float64) string { return strconv.FormatFloat(v, 'g', -1, 64) } // Float32String returns the string representation of a float32. func (a AutoShim) Float32String(v float32) string { return strconv.FormatFloat(float64(v), 'g', -1, 32) } // ByteString returns the string representation of a byte. func (a AutoShim) ByteString(v byte) string { return strconv.FormatUint(uint64(v), 10) } msgp-1.6.1/msgp/circular.go000066400000000000000000000017301511433505400155700ustar00rootroot00000000000000package msgp type timer interface { StartTimer() StopTimer() } // EndlessReader is an io.Reader // that loops over the same data // endlessly. It is used for benchmarking. type EndlessReader struct { tb timer data []byte offset int } // NewEndlessReader returns a new endless reader. // Buffer b cannot be empty func NewEndlessReader(b []byte, tb timer) *EndlessReader { if len(b) == 0 { panic("EndlessReader cannot be of zero length") } // Double until we reach 4K. for len(b) < 4<<10 { b = append(b, b...) } return &EndlessReader{tb: tb, data: b, offset: 0} } // Read implements io.Reader. In practice, it // always returns (len(p), nil), although it // fills the supplied slice while the benchmark // timer is stopped. func (c *EndlessReader) Read(p []byte) (int, error) { var n int l := len(p) m := len(c.data) nn := copy(p[n:], c.data[c.offset:]) n += nn for n < l { n += copy(p[n:], c.data[:]) } c.offset = (c.offset + l) % m return n, nil } msgp-1.6.1/msgp/defs.go000066400000000000000000000073041511433505400147100ustar00rootroot00000000000000// This package is the support library for the msgp code generator (http://github.com/tinylib/msgp). // // This package defines the utilites used by the msgp code generator for encoding and decoding MessagePack // from []byte and io.Reader/io.Writer types. Much of this package is devoted to helping the msgp code // generator implement the Marshaler/Unmarshaler and Encodable/Decodable interfaces. // // This package defines four "families" of functions: // - AppendXxxx() appends an object to a []byte in MessagePack encoding. // - ReadXxxxBytes() reads an object from a []byte and returns the remaining bytes. // - (*Writer).WriteXxxx() writes an object to the buffered *Writer type. // - (*Reader).ReadXxxx() reads an object from a buffered *Reader type. // // Once a type has satisfied the `Encodable` and `Decodable` interfaces, // it can be written and read from arbitrary `io.Writer`s and `io.Reader`s using // // msgp.Encode(io.Writer, msgp.Encodable) // // and // // msgp.Decode(io.Reader, msgp.Decodable) // // There are also methods for converting MessagePack to JSON without // an explicit de-serialization step. // // For additional tips, tricks, and gotchas, please visit // the wiki at http://github.com/tinylib/msgp package msgp // RT is the runtime interface for all types that can be encoded and decoded. type RT interface { Decodable Encodable Sizer Unmarshaler Marshaler } // PtrTo is the runtime interface for all types that can be encoded and decoded. type PtrTo[T any] interface { ~*T } // RTFor is the runtime interface for all types that can be encoded and decoded. // Use for generic types. type RTFor[T any] interface { PtrTo[T] RT } const ( last4 = 0x0f first4 = 0xf0 last5 = 0x1f first3 = 0xe0 last7 = 0x7f // recursionLimit is the limit of recursive calls. // This limits the call depth of dynamic code, like Skip and interface conversions. recursionLimit = 100000 ) func isfixint(b byte) bool { return b>>7 == 0 } func isnfixint(b byte) bool { return b&first3 == mnfixint } func isfixmap(b byte) bool { return b&first4 == mfixmap } func isfixarray(b byte) bool { return b&first4 == mfixarray } func isfixstr(b byte) bool { return b&first3 == mfixstr } func wfixint(u uint8) byte { return u & last7 } func rfixint(b byte) uint8 { return b } func wnfixint(i int8) byte { return byte(i) | mnfixint } func rnfixint(b byte) int8 { return int8(b) } func rfixmap(b byte) uint8 { return b & last4 } func wfixmap(u uint8) byte { return mfixmap | (u & last4) } func rfixstr(b byte) uint8 { return b & last5 } func wfixstr(u uint8) byte { return (u & last5) | mfixstr } func rfixarray(b byte) uint8 { return (b & last4) } func wfixarray(u uint8) byte { return (u & last4) | mfixarray } // These are all the byte // prefixes defined by the // msgpack standard const ( // 0XXXXXXX mfixint uint8 = 0x00 // 111XXXXX mnfixint uint8 = 0xe0 // 1000XXXX mfixmap uint8 = 0x80 // 1001XXXX mfixarray uint8 = 0x90 // 101XXXXX mfixstr uint8 = 0xa0 mnil uint8 = 0xc0 mfalse uint8 = 0xc2 mtrue uint8 = 0xc3 mbin8 uint8 = 0xc4 mbin16 uint8 = 0xc5 mbin32 uint8 = 0xc6 mext8 uint8 = 0xc7 mext16 uint8 = 0xc8 mext32 uint8 = 0xc9 mfloat32 uint8 = 0xca mfloat64 uint8 = 0xcb muint8 uint8 = 0xcc muint16 uint8 = 0xcd muint32 uint8 = 0xce muint64 uint8 = 0xcf mint8 uint8 = 0xd0 mint16 uint8 = 0xd1 mint32 uint8 = 0xd2 mint64 uint8 = 0xd3 mfixext1 uint8 = 0xd4 mfixext2 uint8 = 0xd5 mfixext4 uint8 = 0xd6 mfixext8 uint8 = 0xd7 mfixext16 uint8 = 0xd8 mstr8 uint8 = 0xd9 mstr16 uint8 = 0xda mstr32 uint8 = 0xdb marray16 uint8 = 0xdc marray32 uint8 = 0xdd mmap16 uint8 = 0xde mmap32 uint8 = 0xdf ) msgp-1.6.1/msgp/defs_test.go000066400000000000000000000003461511433505400157460ustar00rootroot00000000000000package msgp_test //go:generate msgp -o=defgen_test.go -tests=false type Blobs []Blob type Blob struct { Name string `msg:"name"` Float float64 `msg:"float"` Bytes []byte `msg:"bytes"` Amount int64 `msg:"amount"` } msgp-1.6.1/msgp/edit.go000066400000000000000000000127661511433505400147240ustar00rootroot00000000000000package msgp import ( "math" ) // Locate returns a []byte pointing to the field // in a messagepack map with the provided key. (The returned []byte // points to a sub-slice of 'raw'; Locate does no allocations.) If the // key doesn't exist in the map, a zero-length []byte will be returned. func Locate(key string, raw []byte) []byte { s, n := locate(raw, key) return raw[s:n] } // Replace takes a key ("key") in a messagepack map ("raw") // and replaces its value with the one provided and returns // the new []byte. The returned []byte may point to the same // memory as "raw". Replace makes no effort to evaluate the validity // of the contents of 'val'. It may use up to the full capacity of 'raw.' // Replace returns 'nil' if the field doesn't exist or if the object in 'raw' // is not a map. func Replace(key string, raw []byte, val []byte) []byte { start, end := locate(raw, key) if start == end { return nil } return replace(raw, start, end, val, true) } // CopyReplace works similarly to Replace except that the returned // byte slice does not point to the same memory as 'raw'. CopyReplace // returns 'nil' if the field doesn't exist or 'raw' isn't a map. func CopyReplace(key string, raw []byte, val []byte) []byte { start, end := locate(raw, key) if start == end { return nil } return replace(raw, start, end, val, false) } // Remove removes a key-value pair from 'raw'. It returns // 'raw' unchanged if the key didn't exist. func Remove(key string, raw []byte) []byte { start, end := locateKV(raw, key) if start == end { return raw } raw = raw[:start+copy(raw[start:], raw[end:])] return resizeMap(raw, -1) } // HasKey returns whether the map in 'raw' has // a field with key 'key' func HasKey(key string, raw []byte) bool { sz, bts, err := ReadMapHeaderBytes(raw) if err != nil { return false } var field []byte for range sz { field, bts, err = ReadStringZC(bts) if err != nil { return false } if UnsafeString(field) == key { return true } } return false } func replace(raw []byte, start int, end int, val []byte, inplace bool) []byte { ll := end - start // length of segment to replace lv := len(val) if inplace { extra := lv - ll // fastest case: we're doing // a 1:1 replacement if extra == 0 { copy(raw[start:], val) return raw } else if extra < 0 { // 'val' smaller than replaced value // copy in place and shift back x := copy(raw[start:], val) y := copy(raw[start+x:], raw[end:]) return raw[:start+x+y] } else if extra < cap(raw)-len(raw) { // 'val' less than (cap-len) extra bytes // copy in place and shift forward raw = raw[0 : len(raw)+extra] // shift end forward copy(raw[end+extra:], raw[end:]) copy(raw[start:], val) return raw } } // we have to allocate new space out := make([]byte, len(raw)+len(val)-ll) x := copy(out, raw[:start]) y := copy(out[x:], val) copy(out[x+y:], raw[end:]) return out } // locate does a naive O(n) search for the map key; returns start, end // (returns 0,0 on error) func locate(raw []byte, key string) (start int, end int) { var ( sz uint32 bts []byte field []byte err error ) sz, bts, err = ReadMapHeaderBytes(raw) if err != nil { return } // loop and locate field for i := uint32(0); i < sz; i++ { field, bts, err = ReadStringZC(bts) if err != nil { return 0, 0 } if UnsafeString(field) == key { // start location l := len(raw) start = l - len(bts) bts, err = Skip(bts) if err != nil { return 0, 0 } end = l - len(bts) return } bts, err = Skip(bts) if err != nil { return 0, 0 } } return 0, 0 } // locate key AND value func locateKV(raw []byte, key string) (start int, end int) { var ( sz uint32 bts []byte field []byte err error ) sz, bts, err = ReadMapHeaderBytes(raw) if err != nil { return 0, 0 } for i := uint32(0); i < sz; i++ { tmp := len(bts) field, bts, err = ReadStringZC(bts) if err != nil { return 0, 0 } if UnsafeString(field) == key { start = len(raw) - tmp bts, err = Skip(bts) if err != nil { return 0, 0 } end = len(raw) - len(bts) return } bts, err = Skip(bts) if err != nil { return 0, 0 } } return 0, 0 } // delta is delta on map size func resizeMap(raw []byte, delta int64) []byte { var sz int64 switch raw[0] { case mmap16: sz = int64(big.Uint16(raw[1:])) if sz+delta <= math.MaxUint16 { big.PutUint16(raw[1:], uint16(sz+delta)) return raw } if cap(raw)-len(raw) >= 2 { raw = raw[0 : len(raw)+2] copy(raw[5:], raw[3:]) raw[0] = mmap32 big.PutUint32(raw[1:], uint32(sz+delta)) return raw } n := make([]byte, 0, len(raw)+5) n = AppendMapHeader(n, uint32(sz+delta)) return append(n, raw[3:]...) case mmap32: sz = int64(big.Uint32(raw[1:])) big.PutUint32(raw[1:], uint32(sz+delta)) return raw default: sz = int64(rfixmap(raw[0])) if sz+delta < 16 { raw[0] = wfixmap(uint8(sz + delta)) return raw } else if sz+delta <= math.MaxUint16 { if cap(raw)-len(raw) >= 2 { raw = raw[0 : len(raw)+2] copy(raw[3:], raw[1:]) raw[0] = mmap16 big.PutUint16(raw[1:], uint16(sz+delta)) return raw } n := make([]byte, 0, len(raw)+5) n = AppendMapHeader(n, uint32(sz+delta)) return append(n, raw[1:]...) } if cap(raw)-len(raw) >= 4 { raw = raw[0 : len(raw)+4] copy(raw[5:], raw[1:]) raw[0] = mmap32 big.PutUint32(raw[1:], uint32(sz+delta)) return raw } n := make([]byte, 0, len(raw)+5) n = AppendMapHeader(n, uint32(sz+delta)) return append(n, raw[1:]...) } } msgp-1.6.1/msgp/edit_test.go000066400000000000000000000106011511433505400157450ustar00rootroot00000000000000package msgp import ( "bytes" "reflect" "testing" ) func TestRemove(t *testing.T) { var buf bytes.Buffer w := NewWriter(&buf) w.WriteMapHeader(3) w.WriteString("first") w.WriteFloat64(-3.1) w.WriteString("second") w.WriteString("DELETE ME!!!") w.WriteString("third") w.WriteBytes([]byte("blah")) w.Flush() raw := Remove("second", buf.Bytes()) m, _, err := ReadMapStrIntfBytes(raw, nil) if err != nil { t.Fatal(err) } if len(m) != 2 { t.Errorf("expected %d fields; found %d", 2, len(m)) } if _, ok := m["first"]; !ok { t.Errorf("field %q not found", "first") } if _, ok := m["third"]; !ok { t.Errorf("field %q not found", "third") } if _, ok := m["second"]; ok { t.Errorf("field %q (deleted field) still present", "second") } } func TestLocate(t *testing.T) { var buf bytes.Buffer en := NewWriter(&buf) en.WriteMapHeader(2) en.WriteString("thing_one") en.WriteString("value_one") en.WriteString("thing_two") en.WriteFloat64(2.0) en.Flush() field := Locate("thing_one", buf.Bytes()) if len(field) == 0 { t.Fatal("field not found") } if !HasKey("thing_one", buf.Bytes()) { t.Fatal("field not found") } var zbuf bytes.Buffer w := NewWriter(&zbuf) w.WriteString("value_one") w.Flush() if !bytes.Equal(zbuf.Bytes(), field) { t.Errorf("got %q; wanted %q", field, zbuf.Bytes()) } zbuf.Reset() w.WriteFloat64(2.0) w.Flush() field = Locate("thing_two", buf.Bytes()) if len(field) == 0 { t.Fatal("field not found") } if !bytes.Equal(zbuf.Bytes(), field) { t.Errorf("got %q; wanted %q", field, zbuf.Bytes()) } field = Locate("nope", buf.Bytes()) if len(field) != 0 { t.Fatalf("wanted a zero-length returned slice") } } func TestReplace(t *testing.T) { // there are 4 cases that need coverage: // - new value is smaller than old value // - new value is the same size as the old value // - new value is larger than old, but fits within cap(b) // - new value is larger than old, and doesn't fit within cap(b) var buf bytes.Buffer en := NewWriter(&buf) en.WriteMapHeader(3) en.WriteString("thing_one") en.WriteString("value_one") en.WriteString("thing_two") en.WriteFloat64(2.0) en.WriteString("some_bytes") en.WriteBytes([]byte("here are some bytes")) en.Flush() // same-size replacement var fbuf bytes.Buffer w := NewWriter(&fbuf) w.WriteFloat64(4.0) w.Flush() // replace 2.0 with 4.0 in field two raw := Replace("thing_two", buf.Bytes(), fbuf.Bytes()) if len(raw) == 0 { t.Fatal("field not found") } var err error m := make(map[string]any) m, _, err = ReadMapStrIntfBytes(raw, m) if err != nil { t.Logf("%q", raw) t.Fatal(err) } if !reflect.DeepEqual(m["thing_two"], 4.0) { t.Errorf("wanted %v; got %v", 4.0, m["thing_two"]) } // smaller-size replacement // replace 2.0 with []byte("hi!") fbuf.Reset() w.WriteBytes([]byte("hi!")) w.Flush() raw = Replace("thing_two", raw, fbuf.Bytes()) if len(raw) == 0 { t.Fatal("field not found") } m, _, err = ReadMapStrIntfBytes(raw, m) if err != nil { t.Logf("%q", raw) t.Fatal(err) } if !reflect.DeepEqual(m["thing_two"], []byte("hi!")) { t.Errorf("wanted %v; got %v", []byte("hi!"), m["thing_two"]) } // larger-size replacement fbuf.Reset() w.WriteBytes([]byte("some even larger bytes than before")) w.Flush() raw = Replace("some_bytes", raw, fbuf.Bytes()) if len(raw) == 0 { t.Logf("%q", raw) t.Fatal(err) } m, _, err = ReadMapStrIntfBytes(raw, m) if err != nil { t.Logf("%q", raw) t.Fatal(err) } if !reflect.DeepEqual(m["some_bytes"], []byte("some even larger bytes than before")) { t.Errorf("wanted %v; got %v", []byte("hello there!"), m["some_bytes"]) } // identical in-place replacement field := Locate("some_bytes", raw) newraw := CopyReplace("some_bytes", raw, field) if !bytes.Equal(newraw, raw) { t.Logf("in: %q", raw) t.Logf("out: %q", newraw) t.Error("bytes not equal after copyreplace") } } func BenchmarkLocate(b *testing.B) { var buf bytes.Buffer en := NewWriter(&buf) en.WriteMapHeader(3) en.WriteString("thing_one") en.WriteString("value_one") en.WriteString("thing_two") en.WriteFloat64(2.0) en.WriteString("thing_three") en.WriteBytes([]byte("hello!")) en.Flush() raw := buf.Bytes() // bytes/s will be the number of bytes traversed per unit of time field := Locate("thing_three", raw) b.SetBytes(int64(len(raw) - len(field))) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { Locate("thing_three", raw) } } msgp-1.6.1/msgp/elsize.go000066400000000000000000000075671511433505400152750ustar00rootroot00000000000000package msgp func calcBytespec(v byte) bytespec { // single byte values switch v { case mnil: return bytespec{size: 1, extra: constsize, typ: NilType} case mfalse: return bytespec{size: 1, extra: constsize, typ: BoolType} case mtrue: return bytespec{size: 1, extra: constsize, typ: BoolType} case mbin8: return bytespec{size: 2, extra: extra8, typ: BinType} case mbin16: return bytespec{size: 3, extra: extra16, typ: BinType} case mbin32: return bytespec{size: 5, extra: extra32, typ: BinType} case mext8: return bytespec{size: 3, extra: extra8, typ: ExtensionType} case mext16: return bytespec{size: 4, extra: extra16, typ: ExtensionType} case mext32: return bytespec{size: 6, extra: extra32, typ: ExtensionType} case mfloat32: return bytespec{size: 5, extra: constsize, typ: Float32Type} case mfloat64: return bytespec{size: 9, extra: constsize, typ: Float64Type} case muint8: return bytespec{size: 2, extra: constsize, typ: UintType} case muint16: return bytespec{size: 3, extra: constsize, typ: UintType} case muint32: return bytespec{size: 5, extra: constsize, typ: UintType} case muint64: return bytespec{size: 9, extra: constsize, typ: UintType} case mint8: return bytespec{size: 2, extra: constsize, typ: IntType} case mint16: return bytespec{size: 3, extra: constsize, typ: IntType} case mint32: return bytespec{size: 5, extra: constsize, typ: IntType} case mint64: return bytespec{size: 9, extra: constsize, typ: IntType} case mfixext1: return bytespec{size: 3, extra: constsize, typ: ExtensionType} case mfixext2: return bytespec{size: 4, extra: constsize, typ: ExtensionType} case mfixext4: return bytespec{size: 6, extra: constsize, typ: ExtensionType} case mfixext8: return bytespec{size: 10, extra: constsize, typ: ExtensionType} case mfixext16: return bytespec{size: 18, extra: constsize, typ: ExtensionType} case mstr8: return bytespec{size: 2, extra: extra8, typ: StrType} case mstr16: return bytespec{size: 3, extra: extra16, typ: StrType} case mstr32: return bytespec{size: 5, extra: extra32, typ: StrType} case marray16: return bytespec{size: 3, extra: array16v, typ: ArrayType} case marray32: return bytespec{size: 5, extra: array32v, typ: ArrayType} case mmap16: return bytespec{size: 3, extra: map16v, typ: MapType} case mmap32: return bytespec{size: 5, extra: map32v, typ: MapType} } switch { // fixint case v >= mfixint && v < 0x80: return bytespec{size: 1, extra: constsize, typ: IntType} // fixstr gets constsize, since the prefix yields the size case v >= mfixstr && v < 0xc0: return bytespec{size: 1 + rfixstr(v), extra: constsize, typ: StrType} // fixmap case v >= mfixmap && v < 0x90: return bytespec{size: 1, extra: varmode(2 * rfixmap(v)), typ: MapType} // fixarray case v >= mfixarray && v < 0xa0: return bytespec{size: 1, extra: varmode(rfixarray(v)), typ: ArrayType} // nfixint case v >= mnfixint && uint16(v) < 0x100: return bytespec{size: 1, extra: constsize, typ: IntType} } // 0xC1 is unused per the spec and falls through to here, // everything else is covered above return bytespec{} } func getType(v byte) Type { return getBytespec(v).typ } // a valid bytespsec has // non-zero 'size' and // non-zero 'typ' type bytespec struct { size uint8 // prefix size information extra varmode // extra size information typ Type // type _ byte // makes bytespec 4 bytes (yes, this matters) } // size mode // if positive, # elements for composites type varmode int8 const ( constsize varmode = 0 // constant size (size bytes + uint8(varmode) objects) extra8 varmode = -1 // has uint8(p[1]) extra bytes extra16 varmode = -2 // has be16(p[1:]) extra bytes extra32 varmode = -3 // has be32(p[1:]) extra bytes map16v varmode = -4 // use map16 map32v varmode = -5 // use map32 array16v varmode = -6 // use array16 array32v varmode = -7 // use array32 ) msgp-1.6.1/msgp/elsize_default.go000066400000000000000000000006021511433505400167600ustar00rootroot00000000000000//go:build !tinygo package msgp // size of every object on the wire, // plus type information. gives us // constant-time type information // for traversing composite objects. var sizes [256]bytespec func init() { for i := range 256 { sizes[i] = calcBytespec(byte(i)) } } // getBytespec gets inlined to a simple array index func getBytespec(v byte) bytespec { return sizes[v] } msgp-1.6.1/msgp/elsize_test.go000066400000000000000000000062561511433505400163260ustar00rootroot00000000000000package msgp import "testing" func TestBytespec(t *testing.T) { // verify that bytespec refactor for TinyGo behaves the same as the old code // previous sizes array setup verbatim: // size of every object on the wire, // plus type information. gives us // constant-time type information // for traversing composite objects. // sizes := [256]bytespec{ mnil: {size: 1, extra: constsize, typ: NilType}, mfalse: {size: 1, extra: constsize, typ: BoolType}, mtrue: {size: 1, extra: constsize, typ: BoolType}, mbin8: {size: 2, extra: extra8, typ: BinType}, mbin16: {size: 3, extra: extra16, typ: BinType}, mbin32: {size: 5, extra: extra32, typ: BinType}, mext8: {size: 3, extra: extra8, typ: ExtensionType}, mext16: {size: 4, extra: extra16, typ: ExtensionType}, mext32: {size: 6, extra: extra32, typ: ExtensionType}, mfloat32: {size: 5, extra: constsize, typ: Float32Type}, mfloat64: {size: 9, extra: constsize, typ: Float64Type}, muint8: {size: 2, extra: constsize, typ: UintType}, muint16: {size: 3, extra: constsize, typ: UintType}, muint32: {size: 5, extra: constsize, typ: UintType}, muint64: {size: 9, extra: constsize, typ: UintType}, mint8: {size: 2, extra: constsize, typ: IntType}, mint16: {size: 3, extra: constsize, typ: IntType}, mint32: {size: 5, extra: constsize, typ: IntType}, mint64: {size: 9, extra: constsize, typ: IntType}, mfixext1: {size: 3, extra: constsize, typ: ExtensionType}, mfixext2: {size: 4, extra: constsize, typ: ExtensionType}, mfixext4: {size: 6, extra: constsize, typ: ExtensionType}, mfixext8: {size: 10, extra: constsize, typ: ExtensionType}, mfixext16: {size: 18, extra: constsize, typ: ExtensionType}, mstr8: {size: 2, extra: extra8, typ: StrType}, mstr16: {size: 3, extra: extra16, typ: StrType}, mstr32: {size: 5, extra: extra32, typ: StrType}, marray16: {size: 3, extra: array16v, typ: ArrayType}, marray32: {size: 5, extra: array32v, typ: ArrayType}, mmap16: {size: 3, extra: map16v, typ: MapType}, mmap32: {size: 5, extra: map32v, typ: MapType}, } // set up fixed fields // fixint for i := range uint8(0x80) { sizes[i] = bytespec{size: 1, extra: constsize, typ: IntType} } // nfixint for i := uint16(mnfixint); i < 0x100; i++ { sizes[uint8(i)] = bytespec{size: 1, extra: constsize, typ: IntType} } // fixstr gets constsize, // since the prefix yields the size for i := mfixstr; i < 0xc0; i++ { sizes[i] = bytespec{size: 1 + rfixstr(i), extra: constsize, typ: StrType} } // fixmap for i := mfixmap; i < 0x90; i++ { sizes[i] = bytespec{size: 1, extra: varmode(2 * rfixmap(i)), typ: MapType} } // fixarray for i := mfixarray; i < 0xa0; i++ { sizes[i] = bytespec{size: 1, extra: varmode(rfixarray(i)), typ: ArrayType} } // compare all values to calcBytespec for i := range 256 { sizeb := sizes[byte(i)] cb := calcBytespec(byte(i)) if sizeb != cb { t.Errorf("at index 0x%x calculated sizes array %#v does not match calcBytespec %#v", i, sizeb, cb) } // all except the unused byte C1 should have non-zero size if i != 0xC1 && sizeb.size == 0 { t.Errorf("unexpected zero size for index 0x%x", i) } } } msgp-1.6.1/msgp/elsize_tinygo.go000066400000000000000000000004421511433505400166470ustar00rootroot00000000000000//go:build tinygo package msgp // for tinygo, getBytespec just calls calcBytespec // a simple/slow function with a switch statement - // doesn't require any heap alloc, moves the space // requirements into code instad of ram func getBytespec(v byte) bytespec { return calcBytespec(v) } msgp-1.6.1/msgp/errors.go000066400000000000000000000250221511433505400153000ustar00rootroot00000000000000package msgp import ( "reflect" "strconv" ) const resumableDefault = false var ( // ErrShortBytes is returned when the // slice being decoded is too short to // contain the contents of the message ErrShortBytes error = errShort{} // ErrRecursion is returned when the maximum recursion limit is reached for an operation. // This should only realistically be seen on adversarial data trying to exhaust the stack. ErrRecursion error = errRecursion{} // ErrLimitExceeded is returned when a set limit is exceeded. // Limits can be set on the Reader to prevent excessive memory usage by adversarial data. ErrLimitExceeded error = errLimitExceeded{} // this error is only returned // if we reach code that should // be unreachable fatal error = errFatal{} ) // Error is the interface satisfied // by all of the errors that originate // from this package. type Error interface { error // Resumable returns whether // or not the error means that // the stream of data is malformed // and the information is unrecoverable. Resumable() bool } // contextError allows msgp Error instances to be enhanced with additional // context about their origin. type contextError interface { Error // withContext must not modify the error instance - it must clone and // return a new error with the context added. withContext(ctx string) error } // Cause returns the underlying cause of an error that has been wrapped // with additional context. func Cause(e error) error { out := e if e, ok := e.(errWrapped); ok && e.cause != nil { out = e.cause } return out } // Resumable returns whether or not the error means that the stream of data is // malformed and the information is unrecoverable. func Resumable(e error) bool { if e, ok := e.(Error); ok { return e.Resumable() } return resumableDefault } // WrapError wraps an error with additional context that allows the part of the // serialized type that caused the problem to be identified. Underlying errors // can be retrieved using Cause() // // The input error is not modified - a new error should be returned. // // ErrShortBytes is not wrapped with any context due to backward compatibility // issues with the public API. func WrapError(err error, ctx ...any) error { switch e := err.(type) { case errShort: return e case contextError: return e.withContext(ctxString(ctx)) default: return errWrapped{cause: err, ctx: ctxString(ctx)} } } func addCtx(ctx, add string) string { if ctx != "" { return add + "/" + ctx } else { return add } } // errWrapped allows arbitrary errors passed to WrapError to be enhanced with // context and unwrapped with Cause() type errWrapped struct { cause error ctx string } func (e errWrapped) Error() string { if e.ctx != "" { return e.cause.Error() + " at " + e.ctx } else { return e.cause.Error() } } func (e errWrapped) Resumable() bool { if e, ok := e.cause.(Error); ok { return e.Resumable() } return resumableDefault } // Unwrap returns the cause. func (e errWrapped) Unwrap() error { return e.cause } type errShort struct{} func (e errShort) Error() string { return "msgp: too few bytes left to read object" } func (e errShort) Resumable() bool { return false } type errFatal struct { ctx string } func (f errFatal) Error() string { out := "msgp: fatal decoding error (unreachable code)" if f.ctx != "" { out += " at " + f.ctx } return out } func (f errFatal) Resumable() bool { return false } func (f errFatal) withContext(ctx string) error { f.ctx = addCtx(f.ctx, ctx); return f } type errRecursion struct{} func (e errRecursion) Error() string { return "msgp: recursion limit reached" } func (e errRecursion) Resumable() bool { return false } type errLimitExceeded struct{} func (e errLimitExceeded) Error() string { return "msgp: configured reader limit exceeded" } func (e errLimitExceeded) Resumable() bool { return false } // ArrayError is an error returned // when decoding a fix-sized array // of the wrong size type ArrayError struct { Wanted uint32 Got uint32 ctx string } // Error implements the error interface func (a ArrayError) Error() string { out := "msgp: wanted array of size " + strconv.Itoa(int(a.Wanted)) + "; got " + strconv.Itoa(int(a.Got)) if a.ctx != "" { out += " at " + a.ctx } return out } // Resumable is always 'true' for ArrayErrors func (a ArrayError) Resumable() bool { return true } func (a ArrayError) withContext(ctx string) error { a.ctx = addCtx(a.ctx, ctx); return a } // IntOverflow is returned when a call // would downcast an integer to a type // with too few bits to hold its value. type IntOverflow struct { Value int64 // the value of the integer FailedBitsize int // the bit size that the int64 could not fit into ctx string } // Error implements the error interface func (i IntOverflow) Error() string { str := "msgp: " + strconv.FormatInt(i.Value, 10) + " overflows int" + strconv.Itoa(i.FailedBitsize) if i.ctx != "" { str += " at " + i.ctx } return str } // Resumable is always 'true' for overflows func (i IntOverflow) Resumable() bool { return true } func (i IntOverflow) withContext(ctx string) error { i.ctx = addCtx(i.ctx, ctx); return i } // UintOverflow is returned when a call // would downcast an unsigned integer to a type // with too few bits to hold its value type UintOverflow struct { Value uint64 // value of the uint FailedBitsize int // the bit size that couldn't fit the value ctx string } // Error implements the error interface func (u UintOverflow) Error() string { str := "msgp: " + strconv.FormatUint(u.Value, 10) + " overflows uint" + strconv.Itoa(u.FailedBitsize) if u.ctx != "" { str += " at " + u.ctx } return str } // Resumable is always 'true' for overflows func (u UintOverflow) Resumable() bool { return true } func (u UintOverflow) withContext(ctx string) error { u.ctx = addCtx(u.ctx, ctx); return u } // InvalidTimestamp is returned when an invalid timestamp is encountered type InvalidTimestamp struct { Nanos int64 // value of the nano, if invalid FieldLength int // Unexpected field length. ctx string } // Error implements the error interface func (u InvalidTimestamp) Error() (str string) { if u.Nanos > 0 { str = "msgp: timestamp nanosecond field value " + strconv.FormatInt(u.Nanos, 10) + " exceeds maximum allows of 999999999" } else if u.FieldLength >= 0 { str = "msgp: invalid timestamp field length " + strconv.FormatInt(int64(u.FieldLength), 10) + " - must be 4, 8 or 12" } if u.ctx != "" { str += " at " + u.ctx } return str } // Resumable is always 'true' for overflows func (u InvalidTimestamp) Resumable() bool { return true } func (u InvalidTimestamp) withContext(ctx string) error { u.ctx = addCtx(u.ctx, ctx); return u } // UintBelowZero is returned when a call // would cast a signed integer below zero // to an unsigned integer. type UintBelowZero struct { Value int64 // value of the incoming int ctx string } // Error implements the error interface func (u UintBelowZero) Error() string { str := "msgp: attempted to cast int " + strconv.FormatInt(u.Value, 10) + " to unsigned" if u.ctx != "" { str += " at " + u.ctx } return str } // Resumable is always 'true' for overflows func (u UintBelowZero) Resumable() bool { return true } func (u UintBelowZero) withContext(ctx string) error { u.ctx = ctx return u } // A TypeError is returned when a particular // decoding method is unsuitable for decoding // a particular MessagePack value. type TypeError struct { Method Type // Type expected by method Encoded Type // Type actually encoded ctx string } // Error implements the error interface func (t TypeError) Error() string { out := "msgp: attempted to decode type " + quoteStr(t.Encoded.String()) + " with method for " + quoteStr(t.Method.String()) if t.ctx != "" { out += " at " + t.ctx } return out } // Resumable returns 'true' for TypeErrors func (t TypeError) Resumable() bool { return true } func (t TypeError) withContext(ctx string) error { t.ctx = addCtx(t.ctx, ctx); return t } // returns either InvalidPrefixError or // TypeError depending on whether or not // the prefix is recognized func badPrefix(want Type, lead byte) error { t := getType(lead) if t == InvalidType { return InvalidPrefixError(lead) } return TypeError{Method: want, Encoded: t} } // InvalidPrefixError is returned when a bad encoding // uses a prefix that is not recognized in the MessagePack standard. // This kind of error is unrecoverable. type InvalidPrefixError byte // Error implements the error interface func (i InvalidPrefixError) Error() string { return "msgp: unrecognized type prefix 0x" + strconv.FormatInt(int64(i), 16) } // Resumable returns 'false' for InvalidPrefixErrors func (i InvalidPrefixError) Resumable() bool { return false } // ErrUnsupportedType is returned // when a bad argument is supplied // to a function that takes `interface{}`. type ErrUnsupportedType struct { T reflect.Type ctx string } // Error implements error func (e *ErrUnsupportedType) Error() string { out := "msgp: type " + quoteStr(e.T.String()) + " not supported" if e.ctx != "" { out += " at " + e.ctx } return out } // Resumable returns 'true' for ErrUnsupportedType func (e *ErrUnsupportedType) Resumable() bool { return true } func (e *ErrUnsupportedType) withContext(ctx string) error { o := *e o.ctx = addCtx(o.ctx, ctx) return &o } // simpleQuoteStr is a simplified version of strconv.Quote for TinyGo, // which takes up a lot less code space by escaping all non-ASCII // (UTF-8) bytes with \x. Saves about 4k of code size // (unicode tables, needed for IsPrint(), are big). // It lives in errors.go just so we can test it in errors_test.go func simpleQuoteStr(s string) string { const ( lowerhex = "0123456789abcdef" ) sb := make([]byte, 0, len(s)+2) sb = append(sb, `"`...) l: // loop through string bytes (not UTF-8 characters) for i := 0; i < len(s); i++ { b := s[i] // specific escape chars switch b { case '\\': sb = append(sb, `\\`...) case '"': sb = append(sb, `\"`...) case '\a': sb = append(sb, `\a`...) case '\b': sb = append(sb, `\b`...) case '\f': sb = append(sb, `\f`...) case '\n': sb = append(sb, `\n`...) case '\r': sb = append(sb, `\r`...) case '\t': sb = append(sb, `\t`...) case '\v': sb = append(sb, `\v`...) default: // no escaping needed (printable ASCII) if b >= 0x20 && b <= 0x7E { sb = append(sb, b) continue l } // anything else is \x sb = append(sb, `\x`...) sb = append(sb, lowerhex[b>>4]) sb = append(sb, lowerhex[b&0xF]) continue l } } sb = append(sb, `"`...) return string(sb) } msgp-1.6.1/msgp/errors_default.go000066400000000000000000000005431511433505400170050ustar00rootroot00000000000000//go:build !tinygo package msgp import ( "fmt" "strconv" ) // ctxString converts the incoming interface{} slice into a single string. func ctxString(ctx []any) string { out := "" for idx, cv := range ctx { if idx > 0 { out += "/" } out += fmt.Sprintf("%v", cv) } return out } func quoteStr(s string) string { return strconv.Quote(s) } msgp-1.6.1/msgp/errors_test.go000066400000000000000000000060241511433505400163400ustar00rootroot00000000000000package msgp import ( "errors" "fmt" "io" "strings" "testing" ) func TestWrapVanillaErrorWithNoAdditionalContext(t *testing.T) { err := errors.New("test") w := WrapError(err) if w == err { t.Fatal() } if w.Error() != err.Error() { t.Fatal() } if w.(errWrapped).Resumable() { t.Fatal() } } func TestWrapVanillaErrorWithAdditionalContext(t *testing.T) { err := errors.New("test") w := WrapError(err, "foo", "bar") if w == err { t.Fatal() } if w.Error() == err.Error() { t.Fatal() } if w.(Error).Resumable() { t.Fatal() } if !strings.HasPrefix(w.Error(), err.Error()) { t.Fatal() } rest := w.Error()[len(err.Error()):] if rest != " at foo/bar" { t.Fatal() } } func TestWrapResumableError(t *testing.T) { err := ArrayError{} w := WrapError(err) if !w.(Error).Resumable() { t.Fatal() } } func TestWrapMultiple(t *testing.T) { err := &TypeError{} w := WrapError(WrapError(err, "b"), "a") expected := `msgp: attempted to decode type "" with method for "" at a/b` if expected != w.Error() { t.Fatal() } } func TestCause(t *testing.T) { for idx, err := range []error{ errors.New("test"), ArrayError{}, &ErrUnsupportedType{}, } { t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) { cerr := WrapError(err, "test") if cerr == err { t.Fatal() } if Cause(err) != err { t.Fatal() } }) } } func TestCauseShortByte(t *testing.T) { err := ErrShortBytes cerr := WrapError(err, "test") if cerr != err { t.Fatal() } if Cause(err) != err { t.Fatal() } } func TestUnwrap(t *testing.T) { // check errors that get wrapped for idx, err := range []error{ errors.New("test"), io.EOF, } { t.Run(fmt.Sprintf("wrapped_%d", idx), func(t *testing.T) { cerr := WrapError(err, "test") if cerr == err { t.Fatal() } uwerr := errors.Unwrap(cerr) if uwerr != err { t.Fatal() } if !errors.Is(cerr, err) { t.Fatal() } }) } // check errors where only context is applied for idx, err := range []error{ ArrayError{}, &ErrUnsupportedType{}, } { t.Run(fmt.Sprintf("ctx_only_%d", idx), func(t *testing.T) { cerr := WrapError(err, "test") if cerr == err { t.Fatal() } if errors.Unwrap(cerr) != nil { t.Fatal() } }) } } func TestSimpleQuoteStr(t *testing.T) { // check some cases for simpleQuoteStr type tcase struct { in string out string } tcaseList := []tcase{ { in: ``, out: `""`, }, { in: `abc`, out: `"abc"`, }, { in: `"`, out: `"\""`, }, { in: `'`, out: `"'"`, }, { in: `on🔥!`, out: `"on\xf0\x9f\x94\xa5!"`, }, { in: "line\r\nbr", out: `"line\r\nbr"`, }, { in: "\x00", out: `"\x00"`, }, { // invalid UTF-8 should make no difference but check it regardless in: "not\x80valid", out: `"not\x80valid"`, }, } for i, tc := range tcaseList { t.Run(fmt.Sprint(i), func(t *testing.T) { out := simpleQuoteStr(tc.in) if out != tc.out { t.Errorf("input %q; expected: %s; but got: %s", tc.in, tc.out, out) } }) } } msgp-1.6.1/msgp/errors_tinygo.go000066400000000000000000000011711511433505400166700ustar00rootroot00000000000000//go:build tinygo package msgp import ( "reflect" ) // ctxString converts the incoming interface{} slice into a single string, // without using fmt under tinygo func ctxString(ctx []interface{}) string { out := "" for idx, cv := range ctx { if idx > 0 { out += "/" } out += ifToStr(cv) } return out } type stringer interface { String() string } func ifToStr(i interface{}) string { switch v := i.(type) { case stringer: return v.String() case error: return v.Error() case string: return v default: return reflect.ValueOf(i).String() } } func quoteStr(s string) string { return simpleQuoteStr(s) } msgp-1.6.1/msgp/extension.go000066400000000000000000000312131511433505400157770ustar00rootroot00000000000000package msgp import ( "errors" "math" "strconv" ) const ( // Complex64Extension is the extension number used for complex64 Complex64Extension = 3 // Complex128Extension is the extension number used for complex128 Complex128Extension = 4 // TimeExtension is the extension number used for time.Time TimeExtension = 5 // MsgTimeExtension is the extension number for timestamps as defined in // https://github.com/msgpack/msgpack/blob/master/spec.md#timestamp-extension-type MsgTimeExtension = -1 ) // msgTimeExtension is a painful workaround to avoid "constant -1 overflows byte". var msgTimeExtension = int8(MsgTimeExtension) // our extensions live here var extensionReg = make(map[int8]func() Extension) // RegisterExtension registers extensions so that they // can be initialized and returned by methods that // decode `interface{}` values. This should only // be called during initialization. f() should return // a newly-initialized zero value of the extension. Keep in // mind that extensions 3, 4, and 5 are reserved for // complex64, complex128, and time.Time, respectively, // and that MessagePack reserves extension types from -127 to -1. // // For example, if you wanted to register a user-defined struct: // // msgp.RegisterExtension(10, func() msgp.Extension { &MyExtension{} }) // // RegisterExtension will panic if you call it multiple times // with the same 'typ' argument, or if you use a reserved // type (3, 4, or 5). func RegisterExtension(typ int8, f func() Extension) { switch typ { case Complex64Extension, Complex128Extension, TimeExtension: panic(errors.New("msgp: forbidden extension type: " + strconv.Itoa(int(typ)))) } if _, ok := extensionReg[typ]; ok { panic(errors.New("msgp: RegisterExtension() called with typ " + strconv.Itoa(int(typ)) + " more than once")) } extensionReg[typ] = f } // ExtensionTypeError is an error type returned // when there is a mis-match between an extension type // and the type encoded on the wire type ExtensionTypeError struct { Got int8 Want int8 } // Error implements the error interface func (e ExtensionTypeError) Error() string { return "msgp: error decoding extension: wanted type " + strconv.Itoa(int(e.Want)) + "; got type " + strconv.Itoa(int(e.Got)) } // Resumable returns 'true' for ExtensionTypeErrors func (e ExtensionTypeError) Resumable() bool { return true } func errExt(got int8, wanted int8) error { return ExtensionTypeError{Got: got, Want: wanted} } // Extension is the interface fulfilled // by types that want to define their // own binary encoding. type Extension interface { // ExtensionType should return // a int8 that identifies the concrete // type of the extension. (Types <0 are // officially reserved by the MessagePack // specifications.) ExtensionType() int8 // Len should return the length // of the data to be encoded Len() int // MarshalBinaryTo should copy // the data into the supplied slice, // assuming that the slice has length Len() MarshalBinaryTo([]byte) error UnmarshalBinary([]byte) error } // RawExtension implements the Extension interface type RawExtension struct { Data []byte Type int8 } // ExtensionType implements Extension.ExtensionType, and returns r.Type func (r *RawExtension) ExtensionType() int8 { return r.Type } // Len implements Extension.Len, and returns len(r.Data) func (r *RawExtension) Len() int { return len(r.Data) } // MarshalBinaryTo implements Extension.MarshalBinaryTo, // and returns a copy of r.Data func (r *RawExtension) MarshalBinaryTo(d []byte) error { copy(d, r.Data) return nil } // UnmarshalBinary implements Extension.UnmarshalBinary, // and sets r.Data to the contents of the provided slice func (r *RawExtension) UnmarshalBinary(b []byte) error { if cap(r.Data) >= len(b) { r.Data = r.Data[0:len(b)] } else { r.Data = make([]byte, len(b)) } copy(r.Data, b) return nil } func (mw *Writer) writeExtensionHeader(length int, extType int8) error { switch length { case 0: o, err := mw.require(3) if err != nil { return err } mw.buf[o] = mext8 mw.buf[o+1] = 0 mw.buf[o+2] = byte(extType) case 1: o, err := mw.require(2) if err != nil { return err } mw.buf[o] = mfixext1 mw.buf[o+1] = byte(extType) case 2: o, err := mw.require(2) if err != nil { return err } mw.buf[o] = mfixext2 mw.buf[o+1] = byte(extType) case 4: o, err := mw.require(2) if err != nil { return err } mw.buf[o] = mfixext4 mw.buf[o+1] = byte(extType) case 8: o, err := mw.require(2) if err != nil { return err } mw.buf[o] = mfixext8 mw.buf[o+1] = byte(extType) case 16: o, err := mw.require(2) if err != nil { return err } mw.buf[o] = mfixext16 mw.buf[o+1] = byte(extType) default: switch { case length < math.MaxUint8: o, err := mw.require(3) if err != nil { return err } mw.buf[o] = mext8 mw.buf[o+1] = byte(length) mw.buf[o+2] = byte(extType) case length < math.MaxUint16: o, err := mw.require(4) if err != nil { return err } mw.buf[o] = mext16 big.PutUint16(mw.buf[o+1:], uint16(length)) mw.buf[o+3] = byte(extType) default: o, err := mw.require(6) if err != nil { return err } mw.buf[o] = mext32 big.PutUint32(mw.buf[o+1:], uint32(length)) mw.buf[o+5] = byte(extType) } } return nil } // WriteExtension writes an extension type to the writer func (mw *Writer) WriteExtension(e Extension) error { length := e.Len() err := mw.writeExtensionHeader(length, e.ExtensionType()) if err != nil { return err } // we can only write directly to the // buffer if we're sure that it // fits the object if length <= mw.bufsize() { o, err := mw.require(length) if err != nil { return err } return e.MarshalBinaryTo(mw.buf[o:]) } // here we create a new buffer // just large enough for the body // and save it as the write buffer err = mw.flush() if err != nil { return err } buf := make([]byte, length) err = e.MarshalBinaryTo(buf) if err != nil { return err } mw.buf = buf mw.wloc = length return nil } // WriteExtensionRaw writes an extension type to the writer func (mw *Writer) WriteExtensionRaw(extType int8, payload []byte) error { if err := mw.writeExtensionHeader(len(payload), extType); err != nil { return err } // instead of using mw.Write(), we'll copy the data through the internal // buffer, otherwise the payload would be moved to the heap // (meaning we can use stack-allocated buffers with zero allocations) for len(payload) > 0 { chunkSize := mw.avail() if chunkSize == 0 { if err := mw.flush(); err != nil { return err } chunkSize = mw.avail() } if chunkSize > len(payload) { chunkSize = len(payload) } mw.wloc += copy(mw.buf[mw.wloc:], payload[:chunkSize]) payload = payload[chunkSize:] } return nil } // peek at the extension type, assuming the next // kind to be read is Extension func (m *Reader) peekExtensionType() (int8, error) { _, _, extType, err := m.peekExtensionHeader() return extType, err } // peekExtension peeks at the extension encoding type // (must guarantee at least 1 byte in 'b') func peekExtension(b []byte) (int8, error) { spec := getBytespec(b[0]) size := spec.size if spec.typ != ExtensionType { return 0, badPrefix(ExtensionType, b[0]) } if len(b) < int(size) { return 0, ErrShortBytes } // for fixed extensions, // the type information is in // the second byte if spec.extra == constsize { return int8(b[1]), nil } // otherwise, it's in the last // part of the prefix return int8(b[size-1]), nil } func (m *Reader) peekExtensionHeader() (offset int, length int, extType int8, err error) { var p []byte p, err = m.R.Peek(2) if err != nil { return } offset = 2 lead := p[0] switch lead { case mfixext1: extType = int8(p[1]) length = 1 return case mfixext2: extType = int8(p[1]) length = 2 return case mfixext4: extType = int8(p[1]) length = 4 return case mfixext8: extType = int8(p[1]) length = 8 return case mfixext16: extType = int8(p[1]) length = 16 return case mext8: p, err = m.R.Peek(3) if err != nil { return } offset = 3 extType = int8(p[2]) length = int(p[1]) case mext16: p, err = m.R.Peek(4) if err != nil { return } offset = 4 extType = int8(p[3]) length = int(big.Uint16(p[1:])) case mext32: p, err = m.R.Peek(6) if err != nil { return } offset = 6 extType = int8(p[5]) length = int(big.Uint32(p[1:])) default: err = badPrefix(ExtensionType, lead) return } return } // ReadExtension reads the next object from the reader // as an extension. ReadExtension will fail if the next // object in the stream is not an extension, or if // e.Type() is not the same as the wire type. func (m *Reader) ReadExtension(e Extension) error { offset, length, extType, err := m.peekExtensionHeader() if err != nil { return err } if expectedType := e.ExtensionType(); extType != expectedType { return errExt(extType, expectedType) } if uint32(length) > m.GetMaxElements() { return ErrLimitExceeded } p, err := m.R.Peek(offset + length) if err != nil { return err } err = e.UnmarshalBinary(p[offset:]) if err == nil { // consume the peeked bytes _, err = m.R.Skip(offset + length) } return err } // ReadExtensionRaw reads the next object from the reader // as an extension. The returned slice is only // valid until the next *Reader method call. func (m *Reader) ReadExtensionRaw() (int8, []byte, error) { offset, length, extType, err := m.peekExtensionHeader() if err != nil { return 0, nil, err } if uint32(length) > m.GetMaxElements() { return 0, nil, ErrLimitExceeded } payload, err := m.R.Next(offset + length) if err != nil { return 0, nil, err } return extType, payload[offset:], nil } // AppendExtension appends a MessagePack extension to the provided slice func AppendExtension(b []byte, e Extension) ([]byte, error) { l := e.Len() var o []byte var n int switch l { case 0: o, n = ensure(b, 3) o[n] = mext8 o[n+1] = 0 o[n+2] = byte(e.ExtensionType()) return o[:n+3], nil case 1: o, n = ensure(b, 3) o[n] = mfixext1 o[n+1] = byte(e.ExtensionType()) n += 2 case 2: o, n = ensure(b, 4) o[n] = mfixext2 o[n+1] = byte(e.ExtensionType()) n += 2 case 4: o, n = ensure(b, 6) o[n] = mfixext4 o[n+1] = byte(e.ExtensionType()) n += 2 case 8: o, n = ensure(b, 10) o[n] = mfixext8 o[n+1] = byte(e.ExtensionType()) n += 2 case 16: o, n = ensure(b, 18) o[n] = mfixext16 o[n+1] = byte(e.ExtensionType()) n += 2 default: switch { case l < math.MaxUint8: o, n = ensure(b, l+3) o[n] = mext8 o[n+1] = byte(l) o[n+2] = byte(e.ExtensionType()) n += 3 case l < math.MaxUint16: o, n = ensure(b, l+4) o[n] = mext16 big.PutUint16(o[n+1:], uint16(l)) o[n+3] = byte(e.ExtensionType()) n += 4 default: o, n = ensure(b, l+6) o[n] = mext32 big.PutUint32(o[n+1:], uint32(l)) o[n+5] = byte(e.ExtensionType()) n += 6 } } return o, e.MarshalBinaryTo(o[n:]) } // ReadExtensionBytes reads an extension from 'b' into 'e' // and returns any remaining bytes. // Possible errors: // - ErrShortBytes ('b' not long enough) // - ExtensionTypeError{} (wire type not the same as e.Type()) // - TypeError{} (next object not an extension) // - InvalidPrefixError // - An umarshal error returned from e.UnmarshalBinary func ReadExtensionBytes(b []byte, e Extension) ([]byte, error) { typ, remain, data, err := readExt(b) if err != nil { return b, err } if typ != e.ExtensionType() { return b, errExt(typ, e.ExtensionType()) } return remain, e.UnmarshalBinary(data) } // readExt will read the extension type, and return remaining bytes, // as well as the data of the extension. func readExt(b []byte) (typ int8, remain []byte, data []byte, err error) { l := len(b) if l < 3 { return 0, b, nil, ErrShortBytes } lead := b[0] var ( sz int // size of 'data' off int // offset of 'data' ) switch lead { case mfixext1: typ = int8(b[1]) sz = 1 off = 2 case mfixext2: typ = int8(b[1]) sz = 2 off = 2 case mfixext4: typ = int8(b[1]) sz = 4 off = 2 case mfixext8: typ = int8(b[1]) sz = 8 off = 2 case mfixext16: typ = int8(b[1]) sz = 16 off = 2 case mext8: sz = int(b[1]) typ = int8(b[2]) off = 3 if sz == 0 { return typ, b[3:], b[3:3], nil } case mext16: if l < 4 { return 0, b, nil, ErrShortBytes } sz = int(big.Uint16(b[1:])) typ = int8(b[3]) off = 4 case mext32: if l < 6 { return 0, b, nil, ErrShortBytes } sz = int(big.Uint32(b[1:])) typ = int8(b[5]) off = 6 default: return 0, b, nil, badPrefix(ExtensionType, lead) } // the data of the extension starts // at 'off' and is 'sz' bytes long tot := off + sz if len(b[off:]) < sz { return 0, b, nil, ErrShortBytes } return typ, b[tot:], b[off:tot:tot], nil } msgp-1.6.1/msgp/extension_test.go000066400000000000000000000111151511433505400170350ustar00rootroot00000000000000package msgp import ( "bytes" "math/rand" "testing" ) var extSizes = [...]int{0, 1, 2, 4, 8, 16, int(tint8), int(tuint16), int(tuint32)} func randomExt() RawExtension { e := RawExtension{} e.Type = int8(rand.Int()) e.Data = RandBytes(extSizes[rand.Intn(len(extSizes))]) return e } func TestReadWriteExtension(t *testing.T) { var buf bytes.Buffer en := NewWriter(&buf) dc := NewReader(&buf) t.Run("interface", func(t *testing.T) { for range 25 { buf.Reset() e := randomExt() en.WriteExtension(&e) en.Flush() err := dc.ReadExtension(&e) if err != nil { t.Errorf("error with extension (length %d): %s", len(buf.Bytes()), err) } } }) t.Run("raw", func(t *testing.T) { for range 25 { buf.Reset() e := randomExt() en.WriteExtensionRaw(e.Type, e.Data) en.Flush() typ, payload, err := dc.ReadExtensionRaw() if err != nil { t.Errorf("error with extension (length %d): %s", len(buf.Bytes()), err) } if typ != e.Type || !bytes.Equal(payload, e.Data) { t.Errorf("extension mismatch: %d %x != %d %x", typ, payload, e.Type, e.Data) } } }) } func TestReadWriteLargeExtensionRaw(t *testing.T) { var buf bytes.Buffer en := NewWriter(&buf) dc := NewReader(&buf) largeExt := RawExtension{Type: int8(rand.Int()), Data: RandBytes(int(tuint32))} err := en.WriteExtensionRaw(largeExt.Type, largeExt.Data) if err != nil { t.Errorf("error with large extension write: %s", err) } // write a nil as a marker err = en.WriteNil() if err != nil { t.Errorf("error with large extension write: %s", err) } en.Flush() typ, payload, err := dc.ReadExtensionRaw() if err != nil { t.Errorf("error with large extension read: %s", err) } if typ != largeExt.Type || !bytes.Equal(payload, largeExt.Data) { t.Errorf("large extension mismatch: %d %x != %d %x", typ, payload, largeExt.Type, largeExt.Data) } err = dc.ReadNil() if err != nil { t.Errorf("error with large extension read: %s", err) } } func TestExtensionRawStackBuffer(t *testing.T) { var buf bytes.Buffer en := NewWriter(&buf) dc := NewReader(&buf) const bufSize = 128 e := &RawExtension{Type: int8(rand.Int()), Data: RandBytes(bufSize)} allocs := testing.AllocsPerRun(100, func() { buf.Reset() var staticBuf [bufSize]byte slc := e.Data[:rand.Intn(bufSize)] copy(staticBuf[:], slc) err := en.WriteExtensionRaw(e.Type, staticBuf[:len(slc)]) if err != nil { t.Errorf("error writing extension: %s", err) } en.Flush() typ, payload, err := dc.ReadExtensionRaw() if err != nil { t.Errorf("error reading extension: %s", err) } if typ != e.Type || !bytes.Equal(payload, slc) { t.Errorf("extension mismatch: %d %x != %d %x", typ, payload, e.Type, slc) } }) if allocs != 0 { t.Errorf("using stack allocated buffer with WriteExtensionRaw caused %f allocations", allocs) } } func TestReadWriteExtensionBytes(t *testing.T) { var bts []byte for range 24 { e := randomExt() bts, _ = AppendExtension(bts[0:0], &e) _, err := ReadExtensionBytes(bts, &e) if err != nil { t.Errorf("error with extension (length %d): %s", len(bts), err) } } } func TestAppendAndWriteCompatibility(t *testing.T) { var bts []byte var buf bytes.Buffer en := NewWriter(&buf) for range 24 { buf.Reset() e := randomExt() bts, _ = AppendExtension(bts[0:0], &e) en.WriteExtension(&e) en.Flush() if !bytes.Equal(buf.Bytes(), bts) { t.Errorf("the outputs are different:\n\t%x\n\t%x", buf.Bytes(), bts) } _, err := ReadExtensionBytes(bts, &e) if err != nil { t.Errorf("error with extension (length %d): %s", len(bts), err) } } } func BenchmarkExtensionReadWrite(b *testing.B) { var buf bytes.Buffer en := NewWriter(&buf) dc := NewReader(&buf) b.Run("interface", func(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { buf.Reset() e := randomExt() err := en.WriteExtension(&e) if err != nil { b.Errorf("error writing extension: %s", err) } en.Flush() err = dc.ReadExtension(&e) if err != nil { b.Errorf("error reading extension: %s", err) } } }) b.Run("raw", func(b *testing.B) { // this should have zero allocations b.ReportAllocs() for i := 0; i < b.N; i++ { buf.Reset() e := randomExt() err := en.WriteExtensionRaw(e.Type, e.Data) if err != nil { b.Errorf("error writing extension: %s", err) } en.Flush() typ, payload, err := dc.ReadExtensionRaw() if err != nil { b.Errorf("error reading extension: %s", err) } if typ != e.Type || !bytes.Equal(payload, e.Data) { b.Errorf("extension mismatch: %d %x != %d %x", typ, payload, e.Type, e.Data) } buf.Reset() } }) } msgp-1.6.1/msgp/file.go000066400000000000000000000045701511433505400147100ustar00rootroot00000000000000//go:build (linux || darwin || dragonfly || freebsd || illumos || netbsd || openbsd) && !appengine && !tinygo package msgp import ( "os" "syscall" ) // ReadFile reads a file into 'dst' using // a read-only memory mapping. Consequently, // the file must be mmap-able, and the // Unmarshaler should never write to // the source memory. (Methods generated // by the msgp tool obey that constraint, but // user-defined implementations may not.) // // Reading and writing through file mappings // is only efficient for large files; small // files are best read and written using // the ordinary streaming interfaces. func ReadFile(dst Unmarshaler, file *os.File) error { stat, err := file.Stat() if err != nil { return err } data, err := syscall.Mmap(int(file.Fd()), 0, int(stat.Size()), syscall.PROT_READ, syscall.MAP_SHARED) if err != nil { return err } adviseRead(data) _, err = dst.UnmarshalMsg(data) uerr := syscall.Munmap(data) if err == nil { err = uerr } return err } // MarshalSizer is the combination // of the Marshaler and Sizer // interfaces. type MarshalSizer interface { Marshaler Sizer } // WriteFile writes a file from 'src' using // memory mapping. It overwrites the entire // contents of the previous file. // The mapping size is calculated // using the `Msgsize()` method // of 'src', so it must produce a result // equal to or greater than the actual encoded // size of the object. Otherwise, // a fault (SIGBUS) will occur. // // Reading and writing through file mappings // is only efficient for large files; small // files are best read and written using // the ordinary streaming interfaces. // // NOTE: The performance of this call // is highly OS- and filesystem-dependent. // Users should take care to test that this // performs as expected in a production environment. // (Linux users should run a kernel and filesystem // that support fallocate(2) for the best results.) func WriteFile(src MarshalSizer, file *os.File) error { sz := src.Msgsize() err := fallocate(file, int64(sz)) if err != nil { return err } data, err := syscall.Mmap(int(file.Fd()), 0, sz, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED) if err != nil { return err } adviseWrite(data) chunk := data[:0] chunk, err = src.MarshalMsg(chunk) if err != nil { return err } uerr := syscall.Munmap(data) if uerr != nil { return uerr } return file.Truncate(int64(len(chunk))) } msgp-1.6.1/msgp/file_port.go000066400000000000000000000013651511433505400157530ustar00rootroot00000000000000//go:build windows || appengine || tinygo package msgp import ( "io" "os" ) // MarshalSizer is the combination // of the Marshaler and Sizer // interfaces. type MarshalSizer interface { Marshaler Sizer } func ReadFile(dst Unmarshaler, file *os.File) error { if u, ok := dst.(Decodable); ok { return u.DecodeMsg(NewReader(file)) } data, err := io.ReadAll(file) if err != nil { return err } _, err = dst.UnmarshalMsg(data) return err } func WriteFile(src MarshalSizer, file *os.File) error { if e, ok := src.(Encodable); ok { w := NewWriter(file) err := e.EncodeMsg(w) if err == nil { err = w.Flush() } return err } raw, err := src.MarshalMsg(nil) if err != nil { return err } _, err = file.Write(raw) return err } msgp-1.6.1/msgp/file_test.go000066400000000000000000000043121511433505400157410ustar00rootroot00000000000000//go:build linux || darwin || dragonfly || freebsd || illumos || netbsd || openbsd package msgp_test import ( "bytes" "crypto/rand" "io" prand "math/rand" "os" "testing" "github.com/tinylib/msgp/msgp" ) type rawBytes []byte func (r rawBytes) MarshalMsg(b []byte) ([]byte, error) { return msgp.AppendBytes(b, []byte(r)), nil } func (r rawBytes) Msgsize() int { return msgp.BytesPrefixSize + len(r) } func (r *rawBytes) UnmarshalMsg(b []byte) ([]byte, error) { tmp, out, err := msgp.ReadBytesBytes(b, (*(*[]byte)(r))[:0]) *r = rawBytes(tmp) return out, err } func TestReadWriteFile(t *testing.T) { t.Parallel() f, err := os.Create("tmpfile") if err != nil { t.Fatal(err) } defer func() { f.Close() os.Remove("tmpfile") }() data := make([]byte, 1024*1024) rand.Read(data) err = msgp.WriteFile(rawBytes(data), f) if err != nil { t.Fatal(err) } var out rawBytes f.Seek(0, io.SeekStart) err = msgp.ReadFile(&out, f) if err != nil { t.Fatal(err) } if !bytes.Equal([]byte(out), data) { t.Fatal("Input and output not equal.") } } var ( blobstrings = []string{"", "a string", "a longer string here!"} blobfloats = []float64{0.0, -1.0, 1.0, 3.1415926535} blobints = []int64{0, 1, -1, 80000, 1 << 30} blobbytes = [][]byte{{}, []byte("hello"), []byte(`{"is_json":true,"is_compact":"unable to determine"}`)} ) func BenchmarkWriteReadFile(b *testing.B) { // let's not run out of disk space... if b.N > 10000000 { b.N = 10000000 //nolint:staticcheck // ignoring "SA3001: should not assign to b.N (staticcheck)" as this should not usually happen. } fname := "bench-tmpfile" f, err := os.Create(fname) if err != nil { b.Fatal(err) } defer func(f *os.File, name string) { f.Close() os.Remove(name) }(f, fname) data := make(Blobs, b.N) for i := range data { data[i].Name = blobstrings[prand.Intn(len(blobstrings))] data[i].Float = blobfloats[prand.Intn(len(blobfloats))] data[i].Amount = blobints[prand.Intn(len(blobints))] data[i].Bytes = blobbytes[prand.Intn(len(blobbytes))] } b.SetBytes(int64(data.Msgsize() / b.N)) b.ResetTimer() err = msgp.WriteFile(data, f) if err != nil { b.Fatal(err) } err = msgp.ReadFile(&data, f) if err != nil { b.Fatal(err) } } msgp-1.6.1/msgp/floatbench_test.go000066400000000000000000000007421511433505400171320ustar00rootroot00000000000000package msgp import ( "testing" ) func BenchmarkReadWriteFloat32(b *testing.B) { var f float32 = 3.9081 bts := AppendFloat32([]byte{}, f) b.ResetTimer() for i := 0; i < b.N; i++ { bts = AppendFloat32(bts[0:0], f) f, bts, _ = ReadFloat32Bytes(bts) } } func BenchmarkReadWriteFloat64(b *testing.B) { var f = 3.9081 bts := AppendFloat64([]byte{}, f) b.ResetTimer() for i := 0; i < b.N; i++ { bts = AppendFloat64(bts[0:0], f) f, bts, _ = ReadFloat64Bytes(bts) } } msgp-1.6.1/msgp/fuzz_test.go000066400000000000000000000152761511433505400160330ustar00rootroot00000000000000package msgp import ( "archive/zip" "bytes" "fmt" "go/ast" "go/parser" "go/token" "io" "os" "runtime" "strconv" "testing" ) // Fuzz Reader tests the Reader methods with fuzzing inputs. func FuzzReader(f *testing.F) { addFuzzDataFromZip(f, "testdata/FuzzCorpus.zip") f.Fuzz(func(t *testing.T, data []byte) { if len(data) == 0 || len(data) > 1<<20 { return } var tmp5 [5]byte r := NewReader(bytes.NewReader(data)) // Set some rather low limits for the reader to avoid excessive memory usage. r.SetMaxRecursionDepth(1000) r.SetMaxElements(10000) r.SetMaxStringLength(1000) reset := func() { t.Helper() // Reset the test state if needed r.Reset(bytes.NewReader(data)) } // Uses reset when data is read off the stream. r.BufferSize() r.Buffered() r.CopyNext(io.Discard) reset() r.IsNil() r.NextType() r.Read(tmp5[:]) reset() r.ReadArrayHeader() reset() r.ReadBool() reset() r.ReadByte() reset() r.ReadBytes(tmp5[:]) reset() r.ReadComplex128() reset() r.ReadComplex64() reset() r.ReadDuration() reset() r.ReadExactBytes(tmp5[:]) reset() r.ReadExtension(testExt{}) reset() r.ReadExtensionRaw() reset() r.ReadFloat32() reset() r.ReadFloat64() reset() r.ReadFull(tmp5[:]) reset() r.ReadInt() reset() r.ReadInt16() reset() r.ReadInt32() reset() r.ReadInt64() reset() r.ReadInt8() reset() r.ReadIntf() reset() runtime.GC() r.ReadJSONNumber() reset() r.ReadMapHeader() reset() r.ReadMapKey(tmp5[:]) reset() runtime.GC() r.ReadMapKeyPtr() reset() r.ReadMapStrIntf(map[string]any{}) reset() r.ReadNil() reset() r.ReadString() reset() r.ReadStringAsBytes(tmp5[:]) reset() r.ReadStringHeader() reset() r.ReadTime() reset() r.ReadTimeUTC() reset() r.ReadUint() reset() r.ReadUint16() reset() r.ReadUint32() reset() r.ReadUint64() reset() r.ReadUint64() reset() r.ReadUint8() reset() r.ReadBinaryUnmarshal(encodingReader{}) reset() r.ReadTextUnmarshal(encodingReader{}) reset() r.ReadTextUnmarshalString(encodingReader{}) reset() for range ReadArray(r, r.ReadInt) { } reset() iter, errfn := ReadMap(r, r.ReadString, r.ReadUint64) for range iter { } errfn() reset() r.Skip() reset() r.WriteToJSON(io.Discard) }) } // Test all byte reading functions with fuzzing inputs. // Since we are reading bytes memory allocations should be well controlled. func FuzzReadBytes(f *testing.F) { addFuzzDataFromZip(f, "testdata/FuzzCorpus.zip") f.Fuzz(func(t *testing.T, data []byte) { if len(data) == 0 || len(data) > 1<<20 { return } var tmp5 [5]byte ReadArrayHeaderBytes(data) ReadBoolBytes(data) ReadByteBytes(data) ReadBytesBytes(data, tmp5[:]) ReadBytesZC(data) ReadComplex128Bytes(data) ReadComplex64Bytes(data) ReadDurationBytes(data) ReadExactBytes(data, tmp5[:]) ReadExtensionBytes(data, testExt{}) ReadFloat32Bytes(data) ReadFloat64Bytes(data) ReadInt8Bytes(data) ReadInt16Bytes(data) ReadInt32Bytes(data) ReadInt64Bytes(data) ReadIntBytes(data) ReadIntfBytes(data) ReadJSONNumberBytes(data) ReadMapHeaderBytes(data) ReadMapKeyZC(data) ReadMapStrIntfBytes(data, map[string]any{}) ReadNilBytes(data) ReadStringBytes(data) ReadStringAsBytes(data, tmp5[:]) ReadStringBytes(data) ReadStringZC(data) ReadTimeBytes(data) ReadTimeUTCBytes(data) ReadUint8Bytes(data) ReadUint16Bytes(data) ReadUint32Bytes(data) ReadUint64Bytes(data) ReadUintBytes(data) UnmarshalAsJSON(io.Discard, data) iter, errfn := ReadArrayBytes(data, ReadIntBytes) for range iter { } errfn() iter2, errfn2 := ReadMapBytes(data, ReadStringBytes, ReadUint64Bytes) for range iter2 { } errfn2() Skip(data) }) } type testExt struct{} func (e testExt) ExtensionType() int8 { return 42 } func (e testExt) Len() int { return 3 } var marshalExtContent = bytes.Repeat([]byte("x"), 3) func (e testExt) MarshalBinaryTo(i []byte) error { if len(i) < e.Len() { return io.ErrShortBuffer } copy(i, marshalExtContent) return nil } func (e testExt) UnmarshalBinary(i []byte) error { if len(i) < e.Len() { return io.ErrUnexpectedEOF } return nil } // addFuzzDataFromZip will read the supplied zip and add all as corpus for f. // Byte slices only. func addFuzzDataFromZip(f *testing.F, filename string) { file, err := os.Open(filename) if err != nil { f.Fatal(err) } fi, err := file.Stat() if fi == nil { return } if err != nil { f.Fatal(err) } zr, err := zip.NewReader(file, fi.Size()) if err != nil { f.Fatal(err) } for _, file := range zr.File { rc, err := file.Open() if err != nil { f.Fatal(err) } b, err := io.ReadAll(rc) if err != nil { f.Fatal(err) } rc.Close() if !bytes.HasPrefix(b, []byte("go test fuzz")) { continue } vals, err := unmarshalCorpusFile(b) if err != nil { f.Fatal(err) } for _, v := range vals { f.Add(v) } } } // unmarshalCorpusFile decodes corpus bytes into their respective values. func unmarshalCorpusFile(b []byte) ([][]byte, error) { if len(b) == 0 { return nil, fmt.Errorf("cannot unmarshal empty string") } lines := bytes.Split(b, []byte("\n")) if len(lines) < 2 { return nil, fmt.Errorf("must include version and at least one value") } var vals = make([][]byte, 0, len(lines)-1) for _, line := range lines[1:] { line = bytes.TrimSpace(line) if len(line) == 0 { continue } v, err := parseCorpusValue(line) if err != nil { return nil, fmt.Errorf("malformed line %q: %v", line, err) } vals = append(vals, v) } return vals, nil } // parseCorpusValue func parseCorpusValue(line []byte) ([]byte, error) { fs := token.NewFileSet() expr, err := parser.ParseExprFrom(fs, "(test)", line, 0) if err != nil { return nil, err } call, ok := expr.(*ast.CallExpr) if !ok { return nil, fmt.Errorf("expected call expression") } if len(call.Args) != 1 { return nil, fmt.Errorf("expected call expression with 1 argument; got %d", len(call.Args)) } arg := call.Args[0] if arrayType, ok := call.Fun.(*ast.ArrayType); ok { if arrayType.Len != nil { return nil, fmt.Errorf("expected []byte or primitive type") } elt, ok := arrayType.Elt.(*ast.Ident) if !ok || elt.Name != "byte" { return nil, fmt.Errorf("expected []byte") } lit, ok := arg.(*ast.BasicLit) if !ok || lit.Kind != token.STRING { return nil, fmt.Errorf("string literal required for type []byte") } s, err := strconv.Unquote(lit.Value) if err != nil { return nil, err } return []byte(s), nil } return nil, fmt.Errorf("expected []byte") } type encodingReader struct{} func (e encodingReader) UnmarshalBinary(data []byte) error { return nil } func (e encodingReader) UnmarshalText(data []byte) error { return nil } msgp-1.6.1/msgp/integers.go000066400000000000000000000076621511433505400156160ustar00rootroot00000000000000package msgp import "encoding/binary" /* ---------------------------------- integer encoding utilities (inline-able) TODO(tinylib): there are faster, albeit non-portable solutions to the code below. implement byteswap? ---------------------------------- */ func putMint64(b []byte, i int64) { _ = b[8] // bounds check elimination b[0] = mint64 b[1] = byte(i >> 56) b[2] = byte(i >> 48) b[3] = byte(i >> 40) b[4] = byte(i >> 32) b[5] = byte(i >> 24) b[6] = byte(i >> 16) b[7] = byte(i >> 8) b[8] = byte(i) } func getMint64(b []byte) int64 { _ = b[8] // bounds check elimination return (int64(b[1]) << 56) | (int64(b[2]) << 48) | (int64(b[3]) << 40) | (int64(b[4]) << 32) | (int64(b[5]) << 24) | (int64(b[6]) << 16) | (int64(b[7]) << 8) | (int64(b[8])) } func putMint32(b []byte, i int32) { _ = b[4] // bounds check elimination b[0] = mint32 b[1] = byte(i >> 24) b[2] = byte(i >> 16) b[3] = byte(i >> 8) b[4] = byte(i) } func getMint32(b []byte) int32 { _ = b[4] // bounds check elimination return (int32(b[1]) << 24) | (int32(b[2]) << 16) | (int32(b[3]) << 8) | (int32(b[4])) } func putMint16(b []byte, i int16) { _ = b[2] // bounds check elimination b[0] = mint16 b[1] = byte(i >> 8) b[2] = byte(i) } func getMint16(b []byte) (i int16) { _ = b[2] // bounds check elimination return (int16(b[1]) << 8) | int16(b[2]) } func putMint8(b []byte, i int8) { _ = b[1] // bounds check elimination b[0] = mint8 b[1] = byte(i) } func getMint8(b []byte) (i int8) { return int8(b[1]) } func putMuint64(b []byte, u uint64) { _ = b[8] // bounds check elimination b[0] = muint64 b[1] = byte(u >> 56) b[2] = byte(u >> 48) b[3] = byte(u >> 40) b[4] = byte(u >> 32) b[5] = byte(u >> 24) b[6] = byte(u >> 16) b[7] = byte(u >> 8) b[8] = byte(u) } func getMuint64(b []byte) uint64 { _ = b[8] // bounds check elimination return (uint64(b[1]) << 56) | (uint64(b[2]) << 48) | (uint64(b[3]) << 40) | (uint64(b[4]) << 32) | (uint64(b[5]) << 24) | (uint64(b[6]) << 16) | (uint64(b[7]) << 8) | (uint64(b[8])) } func putMuint32(b []byte, u uint32) { _ = b[4] // bounds check elimination b[0] = muint32 b[1] = byte(u >> 24) b[2] = byte(u >> 16) b[3] = byte(u >> 8) b[4] = byte(u) } func getMuint32(b []byte) uint32 { _ = b[4] // bounds check elimination return (uint32(b[1]) << 24) | (uint32(b[2]) << 16) | (uint32(b[3]) << 8) | (uint32(b[4])) } func putMuint16(b []byte, u uint16) { _ = b[2] // bounds check elimination b[0] = muint16 b[1] = byte(u >> 8) b[2] = byte(u) } func getMuint16(b []byte) uint16 { _ = b[2] // bounds check elimination return (uint16(b[1]) << 8) | uint16(b[2]) } func putMuint8(b []byte, u uint8) { _ = b[1] // bounds check elimination b[0] = muint8 b[1] = u } func getMuint8(b []byte) uint8 { return b[1] } func getUnix(b []byte) (sec int64, nsec int32) { sec = int64(binary.BigEndian.Uint64(b)) nsec = int32(binary.BigEndian.Uint32(b[8:])) return } func putUnix(b []byte, sec int64, nsec int32) { binary.BigEndian.PutUint64(b, uint64(sec)) binary.BigEndian.PutUint32(b[8:], uint32(nsec)) } /* ----------------------------- prefix utilities ----------------------------- */ // write prefix and uint8 func prefixu8(b []byte, pre byte, sz uint8) { _ = b[1] // bounds check elimination b[0] = pre b[1] = sz } // write prefix and big-endian uint16 func prefixu16(b []byte, pre byte, sz uint16) { _ = b[2] // bounds check elimination b[0] = pre b[1] = byte(sz >> 8) b[2] = byte(sz) } // write prefix and big-endian uint32 func prefixu32(b []byte, pre byte, sz uint32) { _ = b[4] // bounds check elimination b[0] = pre b[1] = byte(sz >> 24) b[2] = byte(sz >> 16) b[3] = byte(sz >> 8) b[4] = byte(sz) } func prefixu64(b []byte, pre byte, sz uint64) { _ = b[8] // bounds check elimination b[0] = pre b[1] = byte(sz >> 56) b[2] = byte(sz >> 48) b[3] = byte(sz >> 40) b[4] = byte(sz >> 32) b[5] = byte(sz >> 24) b[6] = byte(sz >> 16) b[7] = byte(sz >> 8) b[8] = byte(sz) } msgp-1.6.1/msgp/integers_test.go000066400000000000000000000056101511433505400166440ustar00rootroot00000000000000package msgp import ( "encoding/binary" "testing" ) func BenchmarkIntegers(b *testing.B) { bytes64 := make([]byte, 9) bytes32 := make([]byte, 5) bytes16 := make([]byte, 3) b.Run("Int64", func(b *testing.B) { b.Run("Put", func(b *testing.B) { for i := 0; i < b.N; i++ { putMint64(bytes64, -1234567890123456789) } }) b.Run("Get", func(b *testing.B) { putMint64(bytes64, -1234567890123456789) for i := 0; i < b.N; i++ { getMint64(bytes64) } }) }) b.Run("Int32", func(b *testing.B) { b.Run("Put", func(b *testing.B) { for i := 0; i < b.N; i++ { putMint32(bytes32, -123456789) } }) b.Run("Get", func(b *testing.B) { putMint32(bytes32, -123456789) for i := 0; i < b.N; i++ { getMint32(bytes32) } }) }) b.Run("Int16", func(b *testing.B) { b.Run("Put", func(b *testing.B) { for i := 0; i < b.N; i++ { putMint16(bytes16, -12345) } }) b.Run("Get", func(b *testing.B) { putMint16(bytes16, -12345) for i := 0; i < b.N; i++ { getMint16(bytes16) } }) }) b.Run("Uint64", func(b *testing.B) { b.Run("Put", func(b *testing.B) { for i := 0; i < b.N; i++ { putMuint64(bytes64, 1234567890123456789) } }) b.Run("Get", func(b *testing.B) { putMuint64(bytes64, 1234567890123456789) for i := 0; i < b.N; i++ { getMuint64(bytes64) } }) }) b.Run("Uint32", func(b *testing.B) { b.Run("Put", func(b *testing.B) { for i := 0; i < b.N; i++ { putMuint32(bytes32, 123456789) } }) b.Run("Get", func(b *testing.B) { putMuint32(bytes32, 123456789) for i := 0; i < b.N; i++ { getMuint32(bytes32) } }) }) b.Run("Uint16", func(b *testing.B) { b.Run("Put", func(b *testing.B) { for i := 0; i < b.N; i++ { putMuint16(bytes16, 12345) } }) b.Run("Get", func(b *testing.B) { putMuint16(bytes16, 12345) for i := 0; i < b.N; i++ { getMuint16(bytes16) } }) }) } func BenchmarkIntegersUnix(b *testing.B) { bytes := make([]byte, 12) var sec int64 = 1609459200 var nsec int32 = 123456789 b.Run("Get", func(b *testing.B) { binary.BigEndian.PutUint64(bytes, uint64(sec)) binary.BigEndian.PutUint32(bytes[8:], uint32(nsec)) for i := 0; i < b.N; i++ { getUnix(bytes) } }) b.Run("Put", func(b *testing.B) { for i := 0; i < b.N; i++ { putUnix(bytes, sec, nsec) } }) } func BenchmarkIntegersPrefix(b *testing.B) { bytesU16 := make([]byte, 3) bytesU32 := make([]byte, 5) bytesU64 := make([]byte, 9) b.Run("u16", func(b *testing.B) { var pre byte = 0x01 var sz uint16 = 12345 for i := 0; i < b.N; i++ { prefixu16(bytesU16, pre, sz) } }) b.Run("u32", func(b *testing.B) { var pre byte = 0x02 var sz uint32 = 123456789 for i := 0; i < b.N; i++ { prefixu32(bytesU32, pre, sz) } }) b.Run("u64", func(b *testing.B) { var pre byte = 0x03 var sz uint64 = 1234567890123456789 for i := 0; i < b.N; i++ { prefixu64(bytesU64, pre, sz) } }) } msgp-1.6.1/msgp/iter.go000066400000000000000000000261041511433505400147310ustar00rootroot00000000000000package msgp import ( "cmp" "fmt" "iter" "maps" "math" "slices" ) // ReadArray returns an iterator that can be used to iterate over the elements // of an array in the MessagePack data while being read by the provided Reader. // The type parameter V specifies the type of the elements in the array. // The returned iterator implements the iter.Seq[V] interface, // allowing for sequential access to the array elements. // The iterator will always stop after one error has been encountered. func ReadArray[T any](m *Reader, readFn func() (T, error)) iter.Seq2[T, error] { return func(yield func(T, error) bool) { // Check if nil if m.IsNil() { m.ReadNil() return } // Regular array. var empty T length, err := m.ReadArrayHeader() if err != nil { yield(empty, fmt.Errorf("cannot read array header: %w", err)) return } for range length { var v T v, err = readFn() if !yield(v, err) || err != nil { return } } } } // WriteArray writes an array to the provided Writer. // The writeFn parameter specifies the function to use to write each element of the array. func WriteArray[T any](w *Writer, a []T, writeFn func(T) error) error { // Check if nil if a == nil { return w.WriteNil() } if uint64(len(a)) > math.MaxUint32 { return fmt.Errorf("array too large to encode: %d elements", len(a)) } // Write array header err := w.WriteArrayHeader(uint32(len(a))) if err != nil { return err } // Write elements for _, v := range a { err = writeFn(v) if err != nil { return err } } return nil } // ReadMap returns an iterator that can be used to iterate over the elements // of a map in the MessagePack data while being read by the provided Reader. // The type parameters K and V specify the types of the keys and values in the map. // The returned iterator implements the iter.Seq2[K, V] interface, // allowing for sequential access to the map elements. // The returned function can be used to read any error that // occurred during iteration when iteration is done. func ReadMap[K, V any](m *Reader, readKey func() (K, error), readVal func() (V, error)) (iter.Seq2[K, V], func() error) { var err error return func(yield func(K, V) bool) { var sz uint32 if m.IsNil() { err = m.ReadNil() return } sz, err = m.ReadMapHeader() if err != nil { err = fmt.Errorf("cannot read map header: %w", err) return } for range sz { var k K k, err = readKey() if err != nil { err = fmt.Errorf("cannot read key: %w", err) return } var v V v, err = readVal() if err != nil { err = fmt.Errorf("cannot read value: %w", err) return } if !yield(k, v) { return } } }, func() error { return err } } // WriteMap writes a map to the provided Writer. // The writeKey and writeVal parameters specify the functions // to use to write each key and value of the map. func WriteMap[K comparable, V any](w *Writer, m map[K]V, writeKey func(K) error, writeVal func(V) error) error { if m == nil { return w.WriteNil() } if uint64(len(m)) > math.MaxUint32 { return fmt.Errorf("map too large to encode: %d elements", len(m)) } // Write map header err := w.WriteMapHeader(uint32(len(m))) if err != nil { return err } // Write elements for k, v := range m { err = writeKey(k) if err != nil { return err } err = writeVal(v) if err != nil { return err } } return nil } // WriteMapSorted writes a map to the provided Writer. // The keys of the map are sorted before writing. // This provides deterministic output, but will allocate to sort the keys. // The writeKey and writeVal parameters specify the functions // to use to write each key and value of the map. func WriteMapSorted[K cmp.Ordered, V any](w *Writer, m map[K]V, writeKey func(K) error, writeVal func(V) error) error { if m == nil { return w.WriteNil() } if uint64(len(m)) > math.MaxUint32 { return fmt.Errorf("map too large to encode: %d elements", len(m)) } // Write map header err := w.WriteMapHeader(uint32(len(m))) if err != nil { return err } // Write elements for _, k := range slices.Sorted(maps.Keys(m)) { err = writeKey(k) if err != nil { return err } err = writeVal(m[k]) if err != nil { return err } } return nil } // ReadArrayBytes returns an iterator that can be used to iterate over the elements // of an array in the MessagePack data while being read by the provided Reader. // The type parameter V specifies the type of the elements in the array. // After the iterator is exhausted, the remaining bytes in the buffer // and any error can be read by calling the returned function. func ReadArrayBytes[T any](b []byte, readFn func([]byte) (T, []byte, error)) (iter.Seq[T], func() (remain []byte, err error)) { if IsNil(b) { b, err := ReadNilBytes(b) return func(yield func(T) bool) {}, func() ([]byte, error) { return b, err } } sz, b, err := ReadArrayHeaderBytes(b) if err != nil || sz == 0 { return func(yield func(T) bool) {}, func() ([]byte, error) { return b, err } } return func(yield func(T) bool) { for range sz { var v T v, b, err = readFn(b) if err != nil || !yield(v) { return } } }, func() ([]byte, error) { return b, err } } // AppendArray writes an array to the provided buffer. // The writeFn parameter specifies the function to use to write each element of the array. // The returned buffer contains the encoded array. // The function panics if the array is larger than math.MaxUint32 elements. func AppendArray[T any](b []byte, a []T, writeFn func(b []byte, v T) []byte) []byte { if a == nil { return AppendNil(b) } if uint64(len(a)) > math.MaxUint32 { panic(fmt.Sprintf("array too large to encode: %d elements", len(a))) } b = AppendArrayHeader(b, uint32(len(a))) for _, v := range a { b = writeFn(b, v) } return b } // ReadMapBytes returns an iterator over key/value // pairs from a MessagePack map encoded in b. // The iterator yields K,V pairs, and this function also returns // a closure to get the remaining bytes and any error. func ReadMapBytes[K any, V any](b []byte, readK func([]byte) (K, []byte, error), readV func([]byte) (V, []byte, error)) (iter.Seq2[K, V], func() (remain []byte, err error)) { var err error var sz uint32 if IsNil(b) { b, err = ReadNilBytes(b) return func(yield func(K, V) bool) {}, func() ([]byte, error) { return b, err } } sz, b, err = ReadMapHeaderBytes(b) if err != nil || sz == 0 { return func(yield func(K, V) bool) {}, func() ([]byte, error) { return b, err } } return func(yield func(K, V) bool) { for range sz { var k K k, b, err = readK(b) if err != nil { err = fmt.Errorf("cannot read map key: %w", err) return } var v V v, b, err = readV(b) if err != nil { err = fmt.Errorf("cannot read map value: %w", err) return } if !yield(k, v) { return } } }, func() ([]byte, error) { return b, err } } // AppendMap writes a map to the provided buffer. // The writeK and writeV parameters specify the functions to use to write each key and value of the map. // The returned buffer contains the encoded map. // The function panics if the map is larger than math.MaxUint32 elements. func AppendMap[K comparable, V any](b []byte, m map[K]V, writeK func(b []byte, k K) []byte, writeV func(b []byte, v V) []byte) []byte { if m == nil { return AppendNil(b) } if uint64(len(m)) > math.MaxUint32 { panic(fmt.Sprintf("map too large to encode: %d elements", len(m))) } b = AppendMapHeader(b, uint32(len(m))) for k, v := range m { b = writeK(b, k) b = writeV(b, v) } return b } // AppendMapSorted writes a map to the provided buffer. // Keys are sorted before writing. // This provides deterministic output, but will allocate to sort the keys. // The writeK and writeV parameters specify the functions to use to write each key and value of the map. // The returned buffer contains the encoded map. // The function panics if the map is larger than math.MaxUint32 elements. func AppendMapSorted[K cmp.Ordered, V any](b []byte, m map[K]V, writeK func(b []byte, k K) []byte, writeV func(b []byte, v V) []byte) []byte { if m == nil { return AppendNil(b) } if uint64(len(m)) > math.MaxUint32 { panic(fmt.Sprintf("map too large to encode: %d elements", len(m))) } b = AppendMapHeader(b, uint32(len(m))) for _, k := range slices.Sorted(maps.Keys(m)) { b = writeK(b, k) b = writeV(b, m[k]) } return b } // DecodePtr is a convenience type for decoding into a pointer. type DecodePtr[T any] interface { *T Decodable } // DecoderFrom allows augmenting any type with a DecodeMsg method into a method // that reads from Reader and returns a T. // Provide an instance of T. This value isn't used. // See ReadArray/ReadMap "struct" examples for usage. func DecoderFrom[T any, PT DecodePtr[T]](r *Reader, _ T) func() (T, error) { return func() (T, error) { var t T tPtr := PT(&t) err := tPtr.DecodeMsg(r) return t, err } } // FlexibleEncoder is a constraint for types where either T or *T implements Encodable type FlexibleEncoder[T any] interface { Encodable *T } // EncoderTo allows augmenting any type with an EncodeMsg // method into a method that writes to Writer on each call. // Provide an instance of T. This value isn't used. // See ReadArray or ReadMap "struct" examples for usage. func EncoderTo[T any, _ FlexibleEncoder[T]](w *Writer, _ T) func(T) error { return func(t T) error { // Check if T implements Marshaler if marshaler, ok := any(t).(Encodable); ok { return marshaler.EncodeMsg(w) } // Check if *T implements Marshaler if ptrMarshaler, ok := any(&t).(Encodable); ok { return ptrMarshaler.EncodeMsg(w) } // The compiler should have asserted this. panic("type does not implement Marshaler") } } // UnmarshalPtr is a convenience type for unmarshaling into a pointer. type UnmarshalPtr[T any] interface { *T Unmarshaler } // DecoderFromBytes allows augmenting any type with an UnmarshalMsg // method into a method that reads from []byte and returns a T. // Provide an instance of T. This value isn't used. // See ReadArrayBytes or ReadMapBytes "struct" examples for usage. func DecoderFromBytes[T any, PT UnmarshalPtr[T]](_ T) func([]byte) (T, []byte, error) { return func(b []byte) (T, []byte, error) { var t T tPtr := PT(&t) b, err := tPtr.UnmarshalMsg(b) return t, b, err } } // FlexibleMarshaler is a constraint for types where either T or *T implements Marshaler type FlexibleMarshaler[T any] interface { Marshaler *T // Include *T in the interface } // EncoderToBytes allows augmenting any type with a MarshalMsg method into a method // that reads from T and returns a []byte. // Provide an instance of T. This value isn't used. // See ReadArrayBytes or ReadMapBytes "struct" examples for usage. func EncoderToBytes[T any, _ FlexibleMarshaler[T]](_ T) func([]byte, T) []byte { return func(b []byte, t T) []byte { // Check if T implements Marshaler if marshaler, ok := any(t).(Marshaler); ok { b, _ = marshaler.MarshalMsg(b) return b } // Check if *T implements Marshaler if ptrMarshaler, ok := any(&t).(Marshaler); ok { b, _ = ptrMarshaler.MarshalMsg(b) return b } // The compiler should have asserted this. panic("type does not implement Marshaler") } } msgp-1.6.1/msgp/iter_test.go000066400000000000000000003037771511433505400160060ustar00rootroot00000000000000package msgp import ( "bytes" "fmt" "maps" "math" "testing" "time" ) // Example: reading an array of ints using ReadArray with a *Reader. // It prints each element in order. func ExampleReadArray() { var buf bytes.Buffer w := NewWriter(&buf) // Write an array [10, 20, 30] using WriteArray _ = WriteArray(w, []int{10, 20, 30}, w.WriteInt) _ = w.Flush() r := NewReader(&buf) seq := ReadArray(r, r.ReadInt) seq(func(v int, err error) bool { if err != nil { fmt.Println("err:", err) return false } fmt.Println(v) return true }) // Output: // 10 // 20 // 30 } // Example: Writing and array with WriteArray, // then reading back using ReadArray with a *Reader. // It prints each element in order. func ExampleWriteArray() { var buf bytes.Buffer w := NewWriter(&buf) // Write an array [10, 20, 30] using WriteArray _ = WriteArray(w, []int8{10, 20, 30}, w.WriteInt8) _ = w.Flush() r := NewReader(&buf) seq := ReadArray(r, r.ReadInt) seq(func(v int, err error) bool { if err != nil { fmt.Println("err:", err) return false } fmt.Println(v) return true }) // Output: // 10 // 20 // 30 } // Example: reading a map[string]int using ReadMap with a *Reader. // It prints key=value pairs in the same order they were written. func ExampleReadMap() { var buf bytes.Buffer w := NewWriter(&buf) // Write a map {"a":1, "b":2} using WriteMap - we use the sorted version so output is predictable. _ = WriteMapSorted(w, map[string]int{"a": 1, "b": 2}, w.WriteString, w.WriteInt) _ = w.Flush() r := NewReader(&buf) seq, done := ReadMap(r, r.ReadString, r.ReadInt) seq(func(k string, v int) bool { fmt.Printf("%s=%d\n", k, v) return true }) if err := done(); err != nil { fmt.Println("err:", err) } // Output: // a=1 // b=2 } // Example: writing a map using WriteMap (non-sorted). // Uses a single-entry map to keep output deterministic. // Use WriteMapSorted to write a sorted map. func ExampleWriteMap() { var buf bytes.Buffer w := NewWriter(&buf) // Write a map {"only":1} using WriteMap _ = WriteMap(w, map[string]int{"only": 1}, w.WriteString, w.WriteInt) _ = w.Flush() r := NewReader(&buf) seq, done := ReadMap(r, r.ReadString, r.ReadInt) seq(func(k string, v int) bool { fmt.Printf("%s=%d\n", k, v) return true }) if err := done(); err != nil { fmt.Println("err:", err) } // Output: // only=1 } // Example: reading an array of strings from a byte slice using ReadArrayBytes. // It prints each element and then checks for a final error from the returned closure. func ExampleReadArrayBytes() { var b []byte // Append ["x","y","z"] using AppendArray b = AppendArray(b, []string{"x", "y", "z"}, AppendString) seq, finish := ReadArrayBytes(b, ReadStringBytes) seq(func(s string) bool { fmt.Println(s) return true }) if _, err := finish(); err != nil { fmt.Println("err:", err) } // Output: // x // y // z } // Example: reading a map[string]float64 from a byte slice using ReadMapBytes. // It prints key=value pairs and then checks the remaining bytes/error from the returned closure. func ExampleReadMapBytes() { var b []byte // Append {"pi":3.14, "e":2.718} using AppendMap - we use the sorted version for the example b = AppendMapSorted(b, map[string]float64{"pi": 3.14, "e": 2.718}, AppendString, AppendFloat64) seq, finish := ReadMapBytes(b, ReadStringBytes, ReadFloat64Bytes) seq(func(k string, v float64) bool { fmt.Printf("%s=%.3f\n", k, v) return true }) if _, err := finish(); err != nil { fmt.Println("err:", err) } // Output: // e=2.718 // pi=3.140 } // Example: slice roundtrip with struct elements using WriteArray/ReadArray. // Uses testDec as the element type, with EncoderTo/DecoderFrom helpers. func ExampleReadArray_struct() { var buf bytes.Buffer w := NewWriter(&buf) in := []testDec{{A: 1, B: "x"}, {A: 2, B: "y"}} // Write []testDec using EncoderTo as the per-element writer. _ = WriteArray(w, in, EncoderTo(w, testDec{})) _ = w.Flush() r := NewReader(&buf) // Read []testDec using DecoderFrom as the per-element reader. seq := ReadArray(r, DecoderFrom(r, testDec{})) seq(func(v testDec, err error) bool { if err != nil { fmt.Println("err:", err) return false } fmt.Printf("%d %s\n", v.A, v.B) return true }) // Output: // 1 x // 2 y } // Example: map roundtrip with struct values using WriteMapSorted/ReadMap. // Uses testDec as the value type and sorts keys for deterministic output. // Employs EncoderTo for values and DecoderFrom for values when reading. func ExampleReadMap_struct() { var buf bytes.Buffer w := NewWriter(&buf) in := map[string]testDec{ "a": {A: 1, B: "x"}, "b": {A: 2, B: "y"}, } // Write map[string]testDec using sorted keys for stable example output. _ = WriteMapSorted(w, in, w.WriteString, EncoderTo(w, testDec{})) _ = w.Flush() r := NewReader(&buf) seq, done := ReadMap(r, r.ReadString, DecoderFrom(r, testDec{})) seq(func(k string, v testDec) bool { fmt.Printf("%s=%d,%s\n", k, v.A, v.B) return true }) if err := done(); err != nil { fmt.Println("err:", err) } // Output: // a=1,x // b=2,y } // Example: slice roundtrip with struct elements in a byte slice using AppendArray/ReadArrayBytes. // Uses testDec as the element type, with EncoderToBytes/DecoderFromBytes helpers. func ExampleReadArrayBytes_struct() { in := []testDec{{A: 1, B: "x"}, {A: 2, B: "y"}} var b []byte // Append []testDec using EncoderToBytes as the per-element appender. b = AppendArray(b, in, EncoderToBytes(testDec{})) // Read back using DecoderFromBytes as the per-element reader. seq, finish := ReadArrayBytes(b, DecoderFromBytes(testDec{})) seq(func(v testDec) bool { fmt.Printf("%d %s\n", v.A, v.B) return true }) if _, err := finish(); err != nil { fmt.Println("err:", err) } // Output: // 1 x // 2 y } // Example: map roundtrip with struct values in a byte slice using AppendMapSorted/ReadMapBytes. // Uses testDec as the value type and sorts keys for deterministic output. // Employs EncoderToBytes for values and DecoderFromBytes for values when reading. func ExampleReadMapBytes_struct() { in := map[string]testDec{ "a": {A: 1, B: "x"}, "b": {A: 2, B: "y"}, } var b []byte // Append map[string]testDec with sorted keys for stable example output. b = AppendMapSorted(b, in, AppendString, EncoderToBytes(testDec{})) // Read back using DecoderFromBytes for values. seq, finish := ReadMapBytes(b, ReadStringBytes, DecoderFromBytes(testDec{})) seq(func(k string, v testDec) bool { fmt.Printf("%s=%d,%s\n", k, v.A, v.B) return true }) if _, err := finish(); err != nil { fmt.Println("err:", err) } // Output: // a=1,x // b=2,y } // Example: appending a map to a byte slice using AppendMap (non-sorted). // Uses a single-entry map to keep output deterministic. // Use AppendMapSorted to write a sorted map. func ExampleAppendMap() { var b []byte // Append {"only":1} using AppendMap b = AppendMap(b, map[string]int{"only": 1}, AppendString, AppendInt) // Read back and print seq, finish := ReadMapBytes(b, ReadStringBytes, ReadIntBytes) seq(func(k string, v int) bool { fmt.Printf("%s=%d\n", k, v) return true }) if _, err := finish(); err != nil { fmt.Println("err:", err) } // Output: // only=1 } var nilMsg = AppendNil(nil) // collectSeq2 collects values from an iter.Seq2[V, error] into a slice. // It stops at the first non-nil error and returns it together with the collected values. func collectSeq2[V any](seq func(func(V, error) bool)) (vals []V, err error) { seq(func(v V, e error) bool { if e != nil { err = e return false } vals = append(vals, v) return true }) return } func TestReadNumberArray_Int(t *testing.T) { var buf bytes.Buffer w := NewWriter(&buf) want := []int{1, -2, 3, 0, 42} if err := w.WriteArrayHeader(uint32(len(want))); err != nil { t.Fatalf("WriteArrayHeader: %v", err) } for _, v := range want { if err := w.WriteInt(v); err != nil { t.Fatalf("WriteInt: %v", err) } } if err := w.Flush(); err != nil { t.Fatalf("Flush: %v", err) } r := NewReader(&buf) got, err := collectSeq2(ReadArray(r, r.ReadInt)) if err != nil { t.Fatalf("iteration error: %v", err) } if len(got) != len(want) { t.Fatalf("length mismatch: got %d want %d", len(got), len(want)) } for i := range want { if got[i] != want[i] { t.Fatalf("index %d: got %v want %v", i, got[i], want[i]) } } } func TestReadNumberArray_Float64(t *testing.T) { var buf bytes.Buffer w := NewWriter(&buf) want := []float64{0, 1.5, -2.25, 1e9} if err := w.WriteArrayHeader(uint32(len(want))); err != nil { t.Fatalf("WriteArrayHeader: %v", err) } for _, v := range want { if err := w.WriteFloat64(v); err != nil { t.Fatalf("WriteFloat64: %v", err) } } if err := w.Flush(); err != nil { t.Fatalf("Flush: %v", err) } r := NewReader(&buf) got, err := collectSeq2(ReadArray(r, r.ReadFloat64)) if err != nil { t.Fatalf("iteration error: %v", err) } if len(got) != len(want) { t.Fatalf("length mismatch: got %d want %d", len(got), len(want)) } for i := range want { if got[i] != want[i] { t.Fatalf("index %d: got %v want %v", i, got[i], want[i]) } } } func TestReadArray_String(t *testing.T) { var buf bytes.Buffer w := NewWriter(&buf) want := []string{"", "a", "hello", "世界"} if err := w.WriteArrayHeader(uint32(len(want))); err != nil { t.Fatalf("WriteArrayHeader: %v", err) } for _, v := range want { if err := w.WriteString(v); err != nil { t.Fatalf("WriteString: %v", err) } } if err := w.Flush(); err != nil { t.Fatalf("Flush: %v", err) } r := NewReader(&buf) got, err := collectSeq2(ReadArray(r, r.ReadString)) if err != nil { t.Fatalf("iteration error: %v", err) } if len(got) != len(want) { t.Fatalf("length mismatch: got %d want %d", len(got), len(want)) } for i := range want { if got[i] != want[i] { t.Fatalf("index %d: got %q want %q", i, got[i], want[i]) } } } func TestReadArray_Bool(t *testing.T) { var buf bytes.Buffer w := NewWriter(&buf) want := []bool{true, false, true} if err := w.WriteArrayHeader(uint32(len(want))); err != nil { t.Fatalf("WriteArrayHeader: %v", err) } for _, v := range want { if err := w.WriteBool(v); err != nil { t.Fatalf("WriteBool: %v", err) } } if err := w.Flush(); err != nil { t.Fatalf("Flush: %v", err) } r := NewReader(&buf) got, err := collectSeq2(ReadArray(r, r.ReadBool)) if err != nil { t.Fatalf("iteration error: %v", err) } if len(got) != len(want) { t.Fatalf("length mismatch: got %d want %d", len(got), len(want)) } for i := range want { if got[i] != want[i] { t.Fatalf("index %d: got %v want %v", i, got[i], want[i]) } } } // A decodable type to exercise the default branch of ReadArray. type testDec struct { A int B string } func (t *testDec) MarshalMsg(i []byte) ([]byte, error) { i = AppendInt(i, t.A) i = AppendString(i, t.B) return i, nil } func (t *testDec) UnmarshalMsg(i []byte) ([]byte, error) { var err error if t.A, i, err = ReadIntBytes(i); err != nil { return nil, err } if t.B, i, err = ReadStringBytes(i); err != nil { return nil, err } return i, nil } func (t *testDec) EncodeMsg(w *Writer) error { if err := w.WriteInt(t.A); err != nil { return err } return w.WriteString(t.B) } func (t *testDec) DecodeMsg(r *Reader) error { var err error if t.A, err = r.ReadInt(); err != nil { return err } t.B, err = r.ReadString() return err } func TestReadArray_Decodable(t *testing.T) { var buf bytes.Buffer w := NewWriter(&buf) want := []testDec{ {A: 1, B: "x"}, {A: -5, B: "yz"}, } if err := w.WriteArrayHeader(uint32(len(want))); err != nil { t.Fatalf("WriteArrayHeader: %v", err) } for i := range want { if err := (&want[i]).EncodeMsg(w); err != nil { t.Fatalf("EncodeMsg: %v", err) } } if err := w.Flush(); err != nil { t.Fatalf("Flush: %v", err) } r := NewReader(&buf) got, err := collectSeq2(ReadArray[testDec](r, func() (testDec, error) { var t testDec if err := t.DecodeMsg(r); err != nil { return testDec{}, err } return t, nil })) if err != nil { t.Fatalf("iteration error: %v", err) } if len(got) != len(want) { t.Fatalf("length mismatch: got %d want %d", len(got), len(want)) } for i := range want { if got[i].A != want[i].A || got[i].B != want[i].B { t.Fatalf("index %d: got %+v want %+v", i, got[i], want[i]) } } } func TestReadArray_TimeAndDuration(t *testing.T) { var buf bytes.Buffer w := NewWriter(&buf) now := time.Unix(1700000000, 123456789).UTC() durs := []time.Duration{0, time.Second, -5 * time.Millisecond} // time.Time if err := w.WriteArrayHeader(2); err != nil { t.Fatalf("WriteArrayHeader: %v", err) } if err := w.WriteTime(now); err != nil { t.Fatalf("WriteTime: %v", err) } if err := w.WriteTime(now.Add(time.Minute)); err != nil { t.Fatalf("WriteTime: %v", err) } // time.Duration if err := w.WriteArrayHeader(uint32(len(durs))); err != nil { t.Fatalf("WriteArrayHeader: %v", err) } for _, d := range durs { if err := w.WriteDuration(d); err != nil { t.Fatalf("WriteDuration: %v", err) } } if err := w.Flush(); err != nil { t.Fatalf("Flush: %v", err) } r := NewReader(&buf) timesGot, err := collectSeq2(ReadArray[time.Time](r, r.ReadTime)) if err != nil { t.Fatalf("times iteration error: %v", err) } if len(timesGot) != 2 || !timesGot[0].Equal(now) || !timesGot[1].Equal(now.Add(time.Minute)) { t.Fatalf("times mismatch: got %v", timesGot) } dursGot, err := collectSeq2(ReadArray[time.Duration](r, r.ReadDuration)) if err != nil { t.Fatalf("durations iteration error: %v", err) } if len(dursGot) != len(durs) { t.Fatalf("length mismatch: got %d want %d", len(dursGot), len(durs)) } for i := range durs { if dursGot[i] != durs[i] { t.Fatalf("index %d: got %v want %v", i, dursGot[i], durs[i]) } } } func TestReadNumberArrayBytes_Uint16(t *testing.T) { var msg []byte want := []uint16{0, 1, 255, 256, 65535} msg = AppendArrayHeader(msg, uint32(len(want))) for _, v := range want { msg = AppendUint16(msg, v) } seq, tail := ReadArrayBytes(msg, ReadUint16Bytes) var got []uint16 for v := range seq { got = append(got, v) } remain, err := tail() if err != nil { t.Fatalf("tail err: %v", err) } if len(remain) != 0 { t.Fatalf("expected no remaining bytes, got %d", len(remain)) } if len(got) != len(want) { t.Fatalf("length mismatch: got %d want %d", len(got), len(want)) } for i := range want { if got[i] != want[i] { t.Fatalf("index %d: got %v want %v", i, got[i], want[i]) } } } func TestReadNumberArrayBytes_ErrOnTruncated(t *testing.T) { var msg []byte // 2 elements, but we will truncate the second one msg = AppendArrayHeader(msg, 2) msg = AppendInt32(msg, 123) full := AppendInt32(msg, 456) // Truncate to cause an error when reading the second element. trunc := full[:len(full)-2] seq, tail := ReadArrayBytes(trunc, ReadInt32Bytes) var got []int32 for v := range seq { got = append(got, v) // The second element should fail before yielding } if len(got) != 1 || got[0] != 123 { t.Fatalf("expected to read only first element (123), got %v", got) } remain, err := tail() if err == nil { t.Fatalf("expected an error from tail() on truncated input") } // remain can be partial bytes; ensure it's from the truncated buffer if len(remain) != 0 { // Not strictly required, but checks contract that tail returns the remaining unread slice. _ = remain } } func TestReadArray_ErrorOnTooFewElements(t *testing.T) { // Array header says 2, but only 1 element provided. var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteArrayHeader(2); err != nil { t.Fatalf("WriteArrayHeader: %v", err) } if err := w.WriteInt(7); err != nil { t.Fatalf("WriteInt: %v", err) } if err := w.Flush(); err != nil { t.Fatalf("Flush: %v", err) } r := NewReader(&buf) var got []int var firstErr error ReadArray(r, r.ReadInt)(func(v int, err error) bool { if err != nil { firstErr = err return false } got = append(got, v) return true }) if firstErr == nil { t.Fatalf("expected error due to missing second element, got nil") } if len(got) != 1 || got[0] != 7 { t.Fatalf("unexpected values read before error: %v", got) } } // approxEqual checks approximate equality for float32/float64 func approxEqual[T ~float32 | ~float64](a, b T) bool { af := float64(a) bf := float64(b) const eps = 1e-6 return math.Abs(af-bf) <= eps*(1+math.Max(math.Abs(af), math.Abs(bf))) } func TestRoundtripNumberArray_AllTypes(t *testing.T) { type testcase[V any] struct { name string vals []V write func(w *Writer, v V) error } now := time.Now() // not used here, avoid unused import warnings if refactoring _ = now tests := []any{ testcase[uint]{name: "uint", vals: []uint{0, 1, 255, 1 << 20, math.MaxUint32}, write: func(w *Writer, v uint) error { return w.WriteUint(v) }}, testcase[uint8]{name: "uint8", vals: []uint8{0, 1, 127, 128, 255}, write: func(w *Writer, v uint8) error { return w.WriteUint8(v) }}, testcase[uint16]{name: "uint16", vals: []uint16{0, 255, 256, 65535}, write: func(w *Writer, v uint16) error { return w.WriteUint16(v) }}, testcase[uint32]{name: "uint32", vals: []uint32{0, 65535, 1 << 20, math.MaxUint32}, write: func(w *Writer, v uint32) error { return w.WriteUint32(v) }}, testcase[uint64]{name: "uint64", vals: []uint64{0, 1, 1 << 40, math.MaxUint32 + 1, math.MaxUint64 >> 1}, write: func(w *Writer, v uint64) error { return w.WriteUint64(v) }}, testcase[int]{name: "int", vals: []int{0, 1, -1, 1 << 20, -(1 << 20)}, write: func(w *Writer, v int) error { return w.WriteInt(v) }}, testcase[int8]{name: "int8", vals: []int8{0, 1, -1, 127, -128}, write: func(w *Writer, v int8) error { return w.WriteInt8(v) }}, testcase[int16]{name: "int16", vals: []int16{0, 1, -1, 32767, -32768}, write: func(w *Writer, v int16) error { return w.WriteInt16(v) }}, testcase[int32]{name: "int32", vals: []int32{0, 1, -1, math.MaxInt32, math.MinInt32}, write: func(w *Writer, v int32) error { return w.WriteInt32(v) }}, testcase[int64]{name: "int64", vals: []int64{0, 1, -1, math.MaxInt32 + 1, math.MinInt32 - 1}, write: func(w *Writer, v int64) error { return w.WriteInt64(v) }}, testcase[float32]{name: "float32", vals: []float32{0, 1.5, -2.25, 3.14159, 1e20}, write: func(w *Writer, v float32) error { return w.WriteFloat32(v) }}, testcase[float64]{name: "float64", vals: []float64{0, 1.5, -2.25, math.Pi, 1e308}, write: func(w *Writer, v float64) error { return w.WriteFloat64(v) }}, } for _, anytc := range tests { switch tc := anytc.(type) { case testcase[uint]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteArrayHeader(uint32(len(tc.vals))); err != nil { t.Fatalf("WriteArrayHeader %s: %v", tc.name, err) } for _, v := range tc.vals { if err := tc.write(w, v); err != nil { t.Fatalf("%s write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) got, err := collectSeq2(ReadArray(r, r.ReadUint)) if err != nil { t.Fatalf("%s iterate: %v", tc.name, err) } if len(got) != len(tc.vals) { t.Fatalf("%s len: got %d want %d", tc.name, len(got), len(tc.vals)) } for i := range got { if got[i] != tc.vals[i] { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } r = NewReader(bytes.NewReader(nilMsg)) got, err = collectSeq2(ReadArray(r, r.ReadUint)) if err != nil { t.Fatalf("%s iterate: %v", tc.name, err) } if len(got) != 0 { t.Fatalf("%s len: got %d want %d", tc.name, len(got), 0) } case testcase[uint8]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteArrayHeader(uint32(len(tc.vals))); err != nil { t.Fatalf("WriteArrayHeader %s: %v", tc.name, err) } for _, v := range tc.vals { if err := tc.write(w, v); err != nil { t.Fatalf("%s write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) got, err := collectSeq2(ReadArray(r, r.ReadUint8)) if err != nil { t.Fatalf("%s iterate: %v", tc.name, err) } if len(got) != len(tc.vals) { t.Fatalf("%s len: got %d want %d", tc.name, len(got), len(tc.vals)) } for i := range got { if got[i] != tc.vals[i] { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case testcase[uint16]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteArrayHeader(uint32(len(tc.vals))); err != nil { t.Fatalf("WriteArrayHeader %s: %v", tc.name, err) } for _, v := range tc.vals { if err := tc.write(w, v); err != nil { t.Fatalf("%s write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) got, err := collectSeq2(ReadArray(r, r.ReadUint16)) if err != nil { t.Fatalf("%s iterate: %v", tc.name, err) } if len(got) != len(tc.vals) { t.Fatalf("%s len: got %d want %d", tc.name, len(got), len(tc.vals)) } for i := range got { if got[i] != tc.vals[i] { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case testcase[uint32]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteArrayHeader(uint32(len(tc.vals))); err != nil { t.Fatalf("WriteArrayHeader %s: %v", tc.name, err) } for _, v := range tc.vals { if err := tc.write(w, v); err != nil { t.Fatalf("%s write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) got, err := collectSeq2(ReadArray(r, r.ReadUint32)) if err != nil { t.Fatalf("%s iterate: %v", tc.name, err) } if len(got) != len(tc.vals) { t.Fatalf("%s len: got %d want %d", tc.name, len(got), len(tc.vals)) } for i := range got { if got[i] != tc.vals[i] { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case testcase[uint64]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteArrayHeader(uint32(len(tc.vals))); err != nil { t.Fatalf("WriteArrayHeader %s: %v", tc.name, err) } for _, v := range tc.vals { if err := tc.write(w, v); err != nil { t.Fatalf("%s write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) got, err := collectSeq2(ReadArray(r, r.ReadUint64)) if err != nil { t.Fatalf("%s iterate: %v", tc.name, err) } if len(got) != len(tc.vals) { t.Fatalf("%s len: got %d want %d", tc.name, len(got), len(tc.vals)) } for i := range got { if got[i] != tc.vals[i] { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case testcase[int]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteArrayHeader(uint32(len(tc.vals))); err != nil { t.Fatalf("WriteArrayHeader %s: %v", tc.name, err) } for _, v := range tc.vals { if err := tc.write(w, v); err != nil { t.Fatalf("%s write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) got, err := collectSeq2(ReadArray(r, r.ReadInt)) if err != nil { t.Fatalf("%s iterate: %v", tc.name, err) } if len(got) != len(tc.vals) { t.Fatalf("%s len: got %d want %d", tc.name, len(got), len(tc.vals)) } for i := range got { if got[i] != tc.vals[i] { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case testcase[int8]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteArrayHeader(uint32(len(tc.vals))); err != nil { t.Fatalf("WriteArrayHeader %s: %v", tc.name, err) } for _, v := range tc.vals { if err := tc.write(w, v); err != nil { t.Fatalf("%s write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) got, err := collectSeq2(ReadArray(r, r.ReadInt8)) if err != nil { t.Fatalf("%s iterate: %v", tc.name, err) } if len(got) != len(tc.vals) { t.Fatalf("%s len: got %d want %d", tc.name, len(got), len(tc.vals)) } for i := range got { if got[i] != tc.vals[i] { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case testcase[int16]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteArrayHeader(uint32(len(tc.vals))); err != nil { t.Fatalf("WriteArrayHeader %s: %v", tc.name, err) } for _, v := range tc.vals { if err := tc.write(w, v); err != nil { t.Fatalf("%s write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) got, err := collectSeq2(ReadArray(r, r.ReadInt16)) if err != nil { t.Fatalf("%s iterate: %v", tc.name, err) } if len(got) != len(tc.vals) { t.Fatalf("%s len: got %d want %d", tc.name, len(got), len(tc.vals)) } for i := range got { if got[i] != tc.vals[i] { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case testcase[int32]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteArrayHeader(uint32(len(tc.vals))); err != nil { t.Fatalf("WriteArrayHeader %s: %v", tc.name, err) } for _, v := range tc.vals { if err := tc.write(w, v); err != nil { t.Fatalf("%s write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) got, err := collectSeq2(ReadArray(r, r.ReadInt32)) if err != nil { t.Fatalf("%s iterate: %v", tc.name, err) } if len(got) != len(tc.vals) { t.Fatalf("%s len: got %d want %d", tc.name, len(got), len(tc.vals)) } for i := range got { if got[i] != tc.vals[i] { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case testcase[int64]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteArrayHeader(uint32(len(tc.vals))); err != nil { t.Fatalf("WriteArrayHeader %s: %v", tc.name, err) } for _, v := range tc.vals { if err := tc.write(w, v); err != nil { t.Fatalf("%s write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) got, err := collectSeq2(ReadArray(r, r.ReadInt64)) if err != nil { t.Fatalf("%s iterate: %v", tc.name, err) } if len(got) != len(tc.vals) { t.Fatalf("%s len: got %d want %d", tc.name, len(got), len(tc.vals)) } for i := range got { if got[i] != tc.vals[i] { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case testcase[float32]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteArrayHeader(uint32(len(tc.vals))); err != nil { t.Fatalf("WriteArrayHeader %s: %v", tc.name, err) } for _, v := range tc.vals { if err := tc.write(w, v); err != nil { t.Fatalf("%s write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) got, err := collectSeq2(ReadArray(r, r.ReadFloat32)) if err != nil { t.Fatalf("%s iterate: %v", tc.name, err) } if len(got) != len(tc.vals) { t.Fatalf("%s len: got %d want %d", tc.name, len(got), len(tc.vals)) } for i := range got { if !approxEqual(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case testcase[float64]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteArrayHeader(uint32(len(tc.vals))); err != nil { t.Fatalf("WriteArrayHeader %s: %v", tc.name, err) } for _, v := range tc.vals { if err := tc.write(w, v); err != nil { t.Fatalf("%s write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) got, err := collectSeq2(ReadArray(r, r.ReadFloat64)) if err != nil { t.Fatalf("%s iterate: %v", tc.name, err) } if len(got) != len(tc.vals) { t.Fatalf("%s len: got %d want %d", tc.name, len(got), len(tc.vals)) } for i := range got { if !approxEqual(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } } } } func TestRoundtripArray_AllTypes(t *testing.T) { type regCase[V any] struct { name string vals []V write func(*Writer, V) error eq func(a, b V) bool } now := time.Unix(1700000000, 123456789).UTC() later := now.Add(5 * time.Minute) rcases := []any{ regCase[bool]{name: "bool", vals: []bool{true, false, true}, write: func(w *Writer, v bool) error { return w.WriteBool(v) }, eq: func(a, b bool) bool { return a == b }}, regCase[string]{name: "string", vals: []string{"", "a", "hello", "世界"}, write: func(w *Writer, v string) error { return w.WriteString(v) }, eq: func(a, b string) bool { return a == b }}, regCase[[]byte]{name: "bytes", vals: [][]byte{nil, {}, {0x00}, {0x01, 0x02, 0x03}}, write: func(w *Writer, v []byte) error { return w.WriteBytes(v) }, eq: func(a, b []byte) bool { if len(a) != len(b) { return false } for i := range a { if a[i] != b[i] { return false } } return true }}, regCase[time.Time]{name: "time", vals: []time.Time{now, later}, write: func(w *Writer, v time.Time) error { return w.WriteTime(v) }, eq: func(a, b time.Time) bool { return a.Equal(b) }}, regCase[time.Duration]{name: "duration", vals: []time.Duration{0, time.Second, -5 * time.Millisecond}, write: func(w *Writer, v time.Duration) error { return w.WriteDuration(v) }, eq: func(a, b time.Duration) bool { return a == b }}, regCase[complex64]{name: "complex64", vals: []complex64{0, 1 + 2i, -3.5 + 4.25i}, write: func(w *Writer, v complex64) error { return w.WriteComplex64(v) }, eq: func(a, b complex64) bool { return a == b }}, regCase[complex128]{name: "complex128", vals: []complex128{0, 1 + 2i, -3.5 + 4.25i}, write: func(w *Writer, v complex128) error { return w.WriteComplex128(v) }, eq: func(a, b complex128) bool { return a == b }}, regCase[testDec]{name: "decoder", vals: []testDec{{A: 1, B: "abc"}, {A: 2, B: "def"}}, write: func(w *Writer, v testDec) error { return v.EncodeMsg(w) }, eq: func(a, b testDec) bool { return a == b }}, } for _, anytc := range rcases { switch tc := anytc.(type) { case regCase[bool]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteArrayHeader(uint32(len(tc.vals))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for _, v := range tc.vals { if err := tc.write(w, v); err != nil { t.Fatalf("%s write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) got, err := collectSeq2(ReadArray(r, r.ReadBool)) if err != nil { t.Fatalf("%s iterate: %v", tc.name, err) } if len(got) != len(tc.vals) { t.Fatalf("%s len: got %d want %d", tc.name, len(got), len(tc.vals)) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } r.Reset(bytes.NewReader(nilMsg)) got, err = collectSeq2(ReadArray(r, r.ReadBool)) if len(got) != 0 { t.Fatalf("%s len: got %d want 0", tc.name, len(got)) } if err != nil { t.Fatalf("%s iterate: %v", tc.name, err) } case regCase[string]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteArrayHeader(uint32(len(tc.vals))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for _, v := range tc.vals { if err := tc.write(w, v); err != nil { t.Fatalf("%s write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) got, err := collectSeq2(ReadArray(r, r.ReadString)) if err != nil { t.Fatalf("%s iterate: %v", tc.name, err) } if len(got) != len(tc.vals) { t.Fatalf("%s len: got %d want %d", tc.name, len(got), len(tc.vals)) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %q want %q", tc.name, i, got[i], tc.vals[i]) } } case regCase[[]byte]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteArrayHeader(uint32(len(tc.vals))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for _, v := range tc.vals { if err := tc.write(w, v); err != nil { t.Fatalf("%s write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) got, err := collectSeq2(ReadArray(r, func() ([]byte, error) { return r.ReadBytes(nil) })) if err != nil { t.Fatalf("%s iterate: %v", tc.name, err) } if len(got) != len(tc.vals) { t.Fatalf("%s len: got %d want %d", tc.name, len(got), len(tc.vals)) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case regCase[time.Time]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteArrayHeader(uint32(len(tc.vals))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for _, v := range tc.vals { if err := tc.write(w, v); err != nil { t.Fatalf("%s write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) got, err := collectSeq2(ReadArray(r, r.ReadTime)) if err != nil { t.Fatalf("%s iterate: %v", tc.name, err) } if len(got) != len(tc.vals) { t.Fatalf("%s len: got %d want %d", tc.name, len(got), len(tc.vals)) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case regCase[time.Duration]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteArrayHeader(uint32(len(tc.vals))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for _, v := range tc.vals { if err := tc.write(w, v); err != nil { t.Fatalf("%s write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) got, err := collectSeq2(ReadArray(r, r.ReadDuration)) if err != nil { t.Fatalf("%s iterate: %v", tc.name, err) } if len(got) != len(tc.vals) { t.Fatalf("%s len: got %d want %d", tc.name, len(got), len(tc.vals)) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case regCase[complex64]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteArrayHeader(uint32(len(tc.vals))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for _, v := range tc.vals { if err := tc.write(w, v); err != nil { t.Fatalf("%s write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) got, err := collectSeq2(ReadArray(r, r.ReadComplex64)) if err != nil { t.Fatalf("%s iterate: %v", tc.name, err) } if len(got) != len(tc.vals) { t.Fatalf("%s len: got %d want %d", tc.name, len(got), len(tc.vals)) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case regCase[complex128]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteArrayHeader(uint32(len(tc.vals))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for _, v := range tc.vals { if err := tc.write(w, v); err != nil { t.Fatalf("%s write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) got, err := collectSeq2(ReadArray(r, r.ReadComplex128)) if err != nil { t.Fatalf("%s iterate: %v", tc.name, err) } if len(got) != len(tc.vals) { t.Fatalf("%s len: got %d want %d", tc.name, len(got), len(tc.vals)) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case regCase[testDec]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteArrayHeader(uint32(len(tc.vals))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for _, v := range tc.vals { if err := tc.write(w, v); err != nil { t.Fatalf("%s write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) got, err := collectSeq2(ReadArray[testDec](r, DecoderFrom(r, testDec{}))) if err != nil { t.Fatalf("%s iterate: %v", tc.name, err) } if len(got) != len(tc.vals) { t.Fatalf("%s len: got %d want %d", tc.name, len(got), len(tc.vals)) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } } } } func TestRoundtripNumberArrayBytes_AllTypes(t *testing.T) { type tb[V any] struct { name string vals []V append func([]byte, V) []byte eq func(a, b V) bool } tests := []any{ tb[uint]{name: "uint", vals: []uint{0, 1, 255, 1 << 20}, append: func(b []byte, v uint) []byte { return AppendUint(b, v) }, eq: func(a, b uint) bool { return a == b }}, tb[uint8]{name: "uint8", vals: []uint8{0, 1, 127, 128, 255}, append: func(b []byte, v uint8) []byte { return AppendUint8(b, v) }, eq: func(a, b uint8) bool { return a == b }}, tb[uint16]{name: "uint16", vals: []uint16{0, 255, 256, 65535}, append: func(b []byte, v uint16) []byte { return AppendUint16(b, v) }, eq: func(a, b uint16) bool { return a == b }}, tb[uint32]{name: "uint32", vals: []uint32{0, 65535, 1 << 20}, append: func(b []byte, v uint32) []byte { return AppendUint32(b, v) }, eq: func(a, b uint32) bool { return a == b }}, tb[uint64]{name: "uint64", vals: []uint64{0, 1, 1 << 40}, append: func(b []byte, v uint64) []byte { return AppendUint64(b, v) }, eq: func(a, b uint64) bool { return a == b }}, tb[int]{name: "int", vals: []int{0, 1, -1, 1 << 20, -(1 << 20)}, append: func(b []byte, v int) []byte { return AppendInt(b, v) }, eq: func(a, b int) bool { return a == b }}, tb[int8]{name: "int8", vals: []int8{0, 1, -1, 127, -128}, append: func(b []byte, v int8) []byte { return AppendInt8(b, v) }, eq: func(a, b int8) bool { return a == b }}, tb[int16]{name: "int16", vals: []int16{0, 1, -1, 32767, -32768}, append: func(b []byte, v int16) []byte { return AppendInt16(b, v) }, eq: func(a, b int16) bool { return a == b }}, tb[int32]{name: "int32", vals: []int32{0, 1, -1, math.MaxInt32, math.MinInt32}, append: func(b []byte, v int32) []byte { return AppendInt32(b, v) }, eq: func(a, b int32) bool { return a == b }}, tb[int64]{name: "int64", vals: []int64{0, 1, -1, math.MaxInt32 + 1, math.MinInt32 - 1}, append: func(b []byte, v int64) []byte { return AppendInt64(b, v) }, eq: func(a, b int64) bool { return a == b }}, tb[float32]{name: "float32", vals: []float32{0, 1.5, -2.25, 3.14159, 1e20}, append: func(b []byte, v float32) []byte { return AppendFloat32(b, v) }, eq: func(a, b float32) bool { return approxEqual(a, b) }}, tb[float64]{name: "float64", vals: []float64{0, 1.5, -2.25, math.Pi, 1e308}, append: func(b []byte, v float64) []byte { return AppendFloat(b, v) }, eq: func(a, b float64) bool { return approxEqual(a, b) }}, } for _, anytc := range tests { switch tc := anytc.(type) { case tb[uint]: msg := AppendArrayHeader(nil, uint32(len(tc.vals))) for _, v := range tc.vals { msg = tc.append(msg, v) } seq, tail := ReadArrayBytes(msg, ReadUintBytes) var got []uint for v := range seq { got = append(got, v) } remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain: %d", tc.name, len(remain)) } if len(got) != len(tc.vals) { t.Fatalf("%s len: %d", tc.name, len(got)) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } seq, tail = ReadArrayBytes(nilMsg, ReadUintBytes) for range seq { t.Fatalf("%s: got entries on nil", tc.name) } remain, err = tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain: %d", tc.name, len(remain)) } case tb[uint8]: msg := AppendArrayHeader(nil, uint32(len(tc.vals))) for _, v := range tc.vals { msg = tc.append(msg, v) } seq, tail := ReadArrayBytes(msg, ReadUint8Bytes) var got []uint8 for v := range seq { got = append(got, v) } remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain: %d", tc.name, len(remain)) } if len(got) != len(tc.vals) { t.Fatalf("%s len: %d", tc.name, len(got)) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case tb[uint16]: msg := AppendArrayHeader(nil, uint32(len(tc.vals))) for _, v := range tc.vals { msg = tc.append(msg, v) } seq, tail := ReadArrayBytes(msg, ReadUint16Bytes) var got []uint16 for v := range seq { got = append(got, v) } remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain: %d", tc.name, len(remain)) } if len(got) != len(tc.vals) { t.Fatalf("%s len: %d", tc.name, len(got)) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case tb[uint32]: msg := AppendArrayHeader(nil, uint32(len(tc.vals))) for _, v := range tc.vals { msg = tc.append(msg, v) } seq, tail := ReadArrayBytes(msg, ReadUint32Bytes) var got []uint32 for v := range seq { got = append(got, v) } remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain: %d", tc.name, len(remain)) } if len(got) != len(tc.vals) { t.Fatalf("%s len: %d", tc.name, len(got)) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case tb[uint64]: msg := AppendArrayHeader(nil, uint32(len(tc.vals))) for _, v := range tc.vals { msg = tc.append(msg, v) } seq, tail := ReadArrayBytes(msg, ReadUint64Bytes) var got []uint64 for v := range seq { got = append(got, v) } remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain: %d", tc.name, len(remain)) } if len(got) != len(tc.vals) { t.Fatalf("%s len: %d", tc.name, len(got)) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case tb[int]: msg := AppendArrayHeader(nil, uint32(len(tc.vals))) for _, v := range tc.vals { msg = tc.append(msg, v) } seq, tail := ReadArrayBytes(msg, ReadIntBytes) var got []int for v := range seq { got = append(got, v) } remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain: %d", tc.name, len(remain)) } if len(got) != len(tc.vals) { t.Fatalf("%s len: %d", tc.name, len(got)) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case tb[int8]: msg := AppendArrayHeader(nil, uint32(len(tc.vals))) for _, v := range tc.vals { msg = tc.append(msg, v) } seq, tail := ReadArrayBytes(msg, ReadInt8Bytes) var got []int8 for v := range seq { got = append(got, v) } remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain: %d", tc.name, len(remain)) } if len(got) != len(tc.vals) { t.Fatalf("%s len: %d", tc.name, len(got)) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case tb[int16]: msg := AppendArrayHeader(nil, uint32(len(tc.vals))) for _, v := range tc.vals { msg = tc.append(msg, v) } seq, tail := ReadArrayBytes(msg, ReadInt16Bytes) var got []int16 for v := range seq { got = append(got, v) } remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain: %d", tc.name, len(remain)) } if len(got) != len(tc.vals) { t.Fatalf("%s len: %d", tc.name, len(got)) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case tb[int32]: msg := AppendArrayHeader(nil, uint32(len(tc.vals))) for _, v := range tc.vals { msg = tc.append(msg, v) } seq, tail := ReadArrayBytes(msg, ReadInt32Bytes) var got []int32 for v := range seq { got = append(got, v) } remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain: %d", tc.name, len(remain)) } if len(got) != len(tc.vals) { t.Fatalf("%s len: %d", tc.name, len(got)) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case tb[int64]: msg := AppendArrayHeader(nil, uint32(len(tc.vals))) for _, v := range tc.vals { msg = tc.append(msg, v) } seq, tail := ReadArrayBytes(msg, ReadInt64Bytes) var got []int64 for v := range seq { got = append(got, v) } remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain: %d", tc.name, len(remain)) } if len(got) != len(tc.vals) { t.Fatalf("%s len: %d", tc.name, len(got)) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case tb[float32]: msg := AppendArrayHeader(nil, uint32(len(tc.vals))) for _, v := range tc.vals { msg = tc.append(msg, v) } seq, tail := ReadArrayBytes(msg, ReadFloat32Bytes) var got []float32 for v := range seq { got = append(got, v) } remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain: %d", tc.name, len(remain)) } if len(got) != len(tc.vals) { t.Fatalf("%s len: %d", tc.name, len(got)) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case tb[float64]: msg := AppendArrayHeader(nil, uint32(len(tc.vals))) for _, v := range tc.vals { msg = tc.append(msg, v) } seq, tail := ReadArrayBytes(msg, ReadFloat64Bytes) var got []float64 for v := range seq { got = append(got, v) } remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain: %d", tc.name, len(remain)) } if len(got) != len(tc.vals) { t.Fatalf("%s len: %d", tc.name, len(got)) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } } } } func TestRoundtripArrayBytes_AllTypes(t *testing.T) { type rb[V any] struct { name string vals []V append func([]byte, V) []byte eq func(a, b V) bool } now := time.Unix(1700000000, 123456789).UTC() later := now.Add(7 * time.Second) rtests := []any{ rb[bool]{name: "bool", vals: []bool{true, false, true}, append: func(b []byte, v bool) []byte { return AppendBool(b, v) }, eq: func(a, b bool) bool { return a == b }}, rb[string]{name: "string", vals: []string{"", "hi", "世界"}, append: func(b []byte, v string) []byte { return AppendString(b, v) }, eq: func(a, b string) bool { return a == b }}, rb[[]byte]{name: "bytes", vals: [][]byte{nil, {}, {0x00}, {0x01, 0x02}}, append: func(b []byte, v []byte) []byte { return AppendBytes(b, v) }, eq: func(a, b []byte) bool { if len(a) != len(b) { return false } for i := range a { if a[i] != b[i] { return false } } return true }}, rb[time.Time]{name: "time", vals: []time.Time{now, later}, append: func(b []byte, v time.Time) []byte { return AppendTime(b, v) }, eq: func(a, b time.Time) bool { return a.Equal(b) }}, rb[time.Duration]{name: "duration", vals: []time.Duration{0, time.Second, -3 * time.Millisecond}, append: func(b []byte, v time.Duration) []byte { return AppendDuration(b, v) }, eq: func(a, b time.Duration) bool { return a == b }}, rb[complex64]{name: "complex64", vals: []complex64{0, 1 + 2i, -3.5 + 4.25i}, append: func(b []byte, v complex64) []byte { return AppendComplex64(b, v) }, eq: func(a, b complex64) bool { return a == b }}, rb[complex128]{name: "complex128", vals: []complex128{0, 1 + 2i, -3.5 + 4.25i}, append: func(b []byte, v complex128) []byte { return AppendComplex128(b, v) }, eq: func(a, b complex128) bool { return a == b }}, rb[testDec]{name: "unmarshal", vals: []testDec{{A: 1, B: "abc"}, {A: 2, B: "def"}}, append: func(b []byte, v testDec) []byte { b, _ = v.MarshalMsg(b); return b }, eq: func(a, b testDec) bool { return a == b }}, } for _, anytc := range rtests { switch tc := anytc.(type) { case rb[bool]: msg := AppendArrayHeader(nil, uint32(len(tc.vals))) for _, v := range tc.vals { msg = tc.append(msg, v) } seq, tail := ReadArrayBytes(msg, ReadBoolBytes) var got []bool for v := range seq { got = append(got, v) } remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain: %d", tc.name, len(remain)) } if len(got) != len(tc.vals) { t.Fatalf("%s len mismatch", tc.name) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } seq, tail = ReadArrayBytes(nilMsg, ReadBoolBytes) for range seq { t.Fatalf("%s: got entries on nil", tc.name) } remain, err = tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain: %d", tc.name, len(remain)) } case rb[string]: msg := AppendArrayHeader(nil, uint32(len(tc.vals))) for _, v := range tc.vals { msg = tc.append(msg, v) } seq, tail := ReadArrayBytes(msg, ReadStringBytes) var got []string for v := range seq { got = append(got, v) } remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain: %d", tc.name, len(remain)) } if len(got) != len(tc.vals) { t.Fatalf("%s len mismatch", tc.name) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %q want %q", tc.name, i, got[i], tc.vals[i]) } } case rb[[]byte]: msg := AppendArrayHeader(nil, uint32(len(tc.vals))) for _, v := range tc.vals { msg = tc.append(msg, v) } seq, tail := ReadArrayBytes[[]byte](msg, func(i []byte) ([]byte, []byte, error) { return ReadBytesBytes(i, nil) }) var got [][]byte for v := range seq { got = append(got, v) } remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain: %d", tc.name, len(remain)) } if len(got) != len(tc.vals) { t.Fatalf("%s len mismatch", tc.name) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case rb[time.Time]: msg := AppendArrayHeader(nil, uint32(len(tc.vals))) for _, v := range tc.vals { msg = tc.append(msg, v) } seq, tail := ReadArrayBytes[time.Time](msg, ReadTimeBytes) var got []time.Time for v := range seq { got = append(got, v) } remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain: %d", tc.name, len(remain)) } if len(got) != len(tc.vals) { t.Fatalf("%s len mismatch", tc.name) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case rb[time.Duration]: msg := AppendArrayHeader(nil, uint32(len(tc.vals))) for _, v := range tc.vals { msg = tc.append(msg, v) } seq, tail := ReadArrayBytes[time.Duration](msg, ReadDurationBytes) var got []time.Duration for v := range seq { got = append(got, v) } remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain: %d", tc.name, len(remain)) } if len(got) != len(tc.vals) { t.Fatalf("%s len mismatch", tc.name) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case rb[complex64]: msg := AppendArrayHeader(nil, uint32(len(tc.vals))) for _, v := range tc.vals { msg = tc.append(msg, v) } seq, tail := ReadArrayBytes(msg, ReadComplex64Bytes) var got []complex64 for v := range seq { got = append(got, v) } remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain: %d", tc.name, len(remain)) } if len(got) != len(tc.vals) { t.Fatalf("%s len mismatch", tc.name) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case rb[complex128]: msg := AppendArrayHeader(nil, uint32(len(tc.vals))) for _, v := range tc.vals { msg = tc.append(msg, v) } seq, tail := ReadArrayBytes(msg, ReadComplex128Bytes) var got []complex128 for v := range seq { got = append(got, v) } remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain: %d", tc.name, len(remain)) } if len(got) != len(tc.vals) { t.Fatalf("%s len mismatch", tc.name) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } case rb[testDec]: msg := AppendArrayHeader(nil, uint32(len(tc.vals))) for _, v := range tc.vals { msg = tc.append(msg, v) } seq, tail := ReadArrayBytes[testDec](msg, DecoderFromBytes(testDec{})) var got []testDec for v := range seq { got = append(got, v) } remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain: %d", tc.name, len(remain)) } if len(got) != len(tc.vals) { t.Fatalf("%s len mismatch", tc.name) } for i := range got { if !tc.eq(got[i], tc.vals[i]) { t.Fatalf("%s[%d]: got %v want %v", tc.name, i, got[i], tc.vals[i]) } } } } } func eqNum[T comparable](a, b T) bool { return a == b } func TestReadMap_AllNumberTypes_SameKeyValueTypes(t *testing.T) { type numCase[T any] struct { name string keys []T vals []T write func(*Writer, T) error eq func(a, b T) bool } // Equality helpers eqF32 := func(a, b float32) bool { return approxEqual(a, b) } eqF64 := func(a, b float64) bool { return approxEqual(a, b) } cases := []any{ numCase[uint]{name: "uint", keys: []uint{1, 2, 3}, vals: []uint{10, 20, 30}, write: func(w *Writer, v uint) error { return w.WriteUint(v) }, eq: eqNum[uint]}, numCase[uint8]{name: "uint8", keys: []uint8{1, 2, 255}, vals: []uint8{9, 8, 7}, write: func(w *Writer, v uint8) error { return w.WriteUint8(v) }, eq: eqNum[uint8]}, numCase[uint16]{name: "uint16", keys: []uint16{1, 300, 65535}, vals: []uint16{100, 200, 300}, write: func(w *Writer, v uint16) error { return w.WriteUint16(v) }, eq: eqNum[uint16]}, numCase[uint32]{name: "uint32", keys: []uint32{1, 1 << 20, 4000000000}, vals: []uint32{42, 43, 44}, write: func(w *Writer, v uint32) error { return w.WriteUint32(v) }, eq: eqNum[uint32]}, numCase[uint64]{name: "uint64", keys: []uint64{1, 1 << 40, 1<<50 + 123}, vals: []uint64{5, 6, 7}, write: func(w *Writer, v uint64) error { return w.WriteUint64(v) }, eq: eqNum[uint64]}, numCase[int]{name: "int", keys: []int{-1, 0, 2}, vals: []int{100, -100, 0}, write: func(w *Writer, v int) error { return w.WriteInt(v) }, eq: eqNum[int]}, numCase[int8]{name: "int8", keys: []int8{-128, 0, 127}, vals: []int8{1, -1, 0}, write: func(w *Writer, v int8) error { return w.WriteInt8(v) }, eq: eqNum[int8]}, numCase[int16]{name: "int16", keys: []int16{-32768, 0, 32767}, vals: []int16{2, -2, 3}, write: func(w *Writer, v int16) error { return w.WriteInt16(v) }, eq: eqNum[int16]}, numCase[int32]{name: "int32", keys: []int32{-1, 0, 1}, vals: []int32{7, 8, 9}, write: func(w *Writer, v int32) error { return w.WriteInt32(v) }, eq: eqNum[int32]}, numCase[int64]{name: "int64", keys: []int64{-1, 0, 1<<40 + 5}, vals: []int64{9, 8, 7}, write: func(w *Writer, v int64) error { return w.WriteInt64(v) }, eq: eqNum[int64]}, numCase[float32]{name: "float32", keys: []float32{-2.5, 0, 3.25}, vals: []float32{1.5, -0.25, 10}, write: func(w *Writer, v float32) error { return w.WriteFloat32(v) }, eq: eqF32}, numCase[float64]{name: "float64", keys: []float64{-2.5, 0, 3.25}, vals: []float64{1.5, -0.25, 10}, write: func(w *Writer, v float64) error { return w.WriteFloat64(v) }, eq: eqF64}, } for _, anytc := range cases { switch tc := anytc.(type) { case numCase[uint]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteMapHeader(uint32(len(tc.keys))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for i := range tc.keys { if err := tc.write(w, tc.keys[i]); err != nil { t.Fatalf("%s key write: %v", tc.name, err) } if err := tc.write(w, tc.vals[i]); err != nil { t.Fatalf("%s val write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) seq, tail := ReadMap(r, r.ReadUint, r.ReadUint) got := maps.Collect(seq) if err := tail(); err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(got) != len(tc.keys) { t.Fatalf("%s size: got %d want %d", tc.name, len(got), len(tc.keys)) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v: got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } // Test nil r = NewReader(bytes.NewReader(nilMsg)) seq, tail = ReadMap(r, r.ReadUint, r.ReadUint) for k, v := range seq { t.Fatalf("nil %s: got key %v val %v", tc.name, k, v) } if err := tail(); err != nil { t.Fatalf("nil %s: tail: %v", tc.name, err) } case numCase[uint8]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteMapHeader(uint32(len(tc.keys))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for i := range tc.keys { if err := tc.write(w, tc.keys[i]); err != nil { t.Fatalf("%s key write: %v", tc.name, err) } if err := tc.write(w, tc.vals[i]); err != nil { t.Fatalf("%s val write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) seq, tail := ReadMap(r, r.ReadUint8, r.ReadUint8) got := maps.Collect(seq) if err := tail(); err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(got) != len(tc.keys) { t.Fatalf("%s size: got %d want %d", tc.name, len(got), len(tc.keys)) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v: got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case numCase[uint16]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteMapHeader(uint32(len(tc.keys))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for i := range tc.keys { if err := tc.write(w, tc.keys[i]); err != nil { t.Fatalf("%s key write: %v", tc.name, err) } if err := tc.write(w, tc.vals[i]); err != nil { t.Fatalf("%s val write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) seq, tail := ReadMap(r, r.ReadUint16, r.ReadUint16) got := maps.Collect(seq) if err := tail(); err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(got) != len(tc.keys) { t.Fatalf("%s size: got %d want %d", tc.name, len(got), len(tc.keys)) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v: got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case numCase[uint32]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteMapHeader(uint32(len(tc.keys))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for i := range tc.keys { if err := tc.write(w, tc.keys[i]); err != nil { t.Fatalf("%s key write: %v", tc.name, err) } if err := tc.write(w, tc.vals[i]); err != nil { t.Fatalf("%s val write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) seq, tail := ReadMap(r, r.ReadUint32, r.ReadUint32) got := maps.Collect(seq) if err := tail(); err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(got) != len(tc.keys) { t.Fatalf("%s size: got %d want %d", tc.name, len(got), len(tc.keys)) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v: got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case numCase[uint64]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteMapHeader(uint32(len(tc.keys))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for i := range tc.keys { if err := tc.write(w, tc.keys[i]); err != nil { t.Fatalf("%s key write: %v", tc.name, err) } if err := tc.write(w, tc.vals[i]); err != nil { t.Fatalf("%s val write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) seq, tail := ReadMap(r, r.ReadUint64, r.ReadUint64) got := maps.Collect(seq) if err := tail(); err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(got) != len(tc.keys) { t.Fatalf("%s size: got %d want %d", tc.name, len(got), len(tc.keys)) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v: got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case numCase[int]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteMapHeader(uint32(len(tc.keys))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for i := range tc.keys { if err := tc.write(w, tc.keys[i]); err != nil { t.Fatalf("%s key write: %v", tc.name, err) } if err := tc.write(w, tc.vals[i]); err != nil { t.Fatalf("%s val write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) seq, tail := ReadMap(r, r.ReadInt, r.ReadInt) got := maps.Collect(seq) if err := tail(); err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(got) != len(tc.keys) { t.Fatalf("%s size: got %d want %d", tc.name, len(got), len(tc.keys)) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v: got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case numCase[int8]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteMapHeader(uint32(len(tc.keys))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for i := range tc.keys { if err := tc.write(w, tc.keys[i]); err != nil { t.Fatalf("%s key write: %v", tc.name, err) } if err := tc.write(w, tc.vals[i]); err != nil { t.Fatalf("%s val write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) seq, tail := ReadMap(r, r.ReadInt8, r.ReadInt8) got := maps.Collect(seq) if err := tail(); err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(got) != len(tc.keys) { t.Fatalf("%s size: got %d want %d", tc.name, len(got), len(tc.keys)) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v: got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case numCase[int16]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteMapHeader(uint32(len(tc.keys))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for i := range tc.keys { if err := tc.write(w, tc.keys[i]); err != nil { t.Fatalf("%s key write: %v", tc.name, err) } if err := tc.write(w, tc.vals[i]); err != nil { t.Fatalf("%s val write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) seq, tail := ReadMap(r, r.ReadInt16, r.ReadInt16) got := maps.Collect(seq) if err := tail(); err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(got) != len(tc.keys) { t.Fatalf("%s size: got %d want %d", tc.name, len(got), len(tc.keys)) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v: got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case numCase[int32]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteMapHeader(uint32(len(tc.keys))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for i := range tc.keys { if err := tc.write(w, tc.keys[i]); err != nil { t.Fatalf("%s key write: %v", tc.name, err) } if err := tc.write(w, tc.vals[i]); err != nil { t.Fatalf("%s val write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) seq, tail := ReadMap(r, r.ReadInt32, r.ReadInt32) got := maps.Collect(seq) if err := tail(); err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(got) != len(tc.keys) { t.Fatalf("%s size: got %d want %d", tc.name, len(got), len(tc.keys)) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v: got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case numCase[int64]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteMapHeader(uint32(len(tc.keys))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for i := range tc.keys { if err := tc.write(w, tc.keys[i]); err != nil { t.Fatalf("%s key write: %v", tc.name, err) } if err := tc.write(w, tc.vals[i]); err != nil { t.Fatalf("%s val write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) seq, tail := ReadMap(r, r.ReadInt64, r.ReadInt64) got := maps.Collect(seq) if err := tail(); err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(got) != len(tc.keys) { t.Fatalf("%s size: got %d want %d", tc.name, len(got), len(tc.keys)) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v: got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case numCase[float32]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteMapHeader(uint32(len(tc.keys))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for i := range tc.keys { if err := tc.write(w, tc.keys[i]); err != nil { t.Fatalf("%s key write: %v", tc.name, err) } if err := tc.write(w, tc.vals[i]); err != nil { t.Fatalf("%s val write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) seq, tail := ReadMap(r, r.ReadFloat32, r.ReadFloat32) got := maps.Collect(seq) if err := tail(); err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(got) != len(tc.keys) { t.Fatalf("%s size: got %d want %d", tc.name, len(got), len(tc.keys)) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v: got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case numCase[float64]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteMapHeader(uint32(len(tc.keys))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for i := range tc.keys { if err := tc.write(w, tc.keys[i]); err != nil { t.Fatalf("%s key write: %v", tc.name, err) } if err := tc.write(w, tc.vals[i]); err != nil { t.Fatalf("%s val write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) seq, tail := ReadMap(r, r.ReadFloat64, r.ReadFloat64) got := maps.Collect(seq) if err := tail(); err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(got) != len(tc.keys) { t.Fatalf("%s size: got %d want %d", tc.name, len(got), len(tc.keys)) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v: got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } } } } func TestReadMap_AllRegularTypes_SameKeyValueTypes(t *testing.T) { type regCase[T any] struct { name string keys []T vals []T write func(*Writer, T) error eq func(a, b T) bool } eqBool := func(a, b bool) bool { return a == b } eqStr := func(a, b string) bool { return a == b } eqBytes := func(a, b []byte) bool { if len(a) != len(b) { return false } for i := range a { if a[i] != b[i] { return false } } return true } eqTime := func(a, b time.Time) bool { return a.Equal(b) } eqDur := func(a, b time.Duration) bool { return a == b } eqC64 := func(a, b complex64) bool { return a == b } eqC128 := func(a, b complex128) bool { return a == b } now := time.Unix(1700000000, 123456789).UTC() later := now.Add(123 * time.Second) cases := []any{ regCase[bool]{name: "bool", keys: []bool{false, true}, vals: []bool{false, true, false}, write: func(w *Writer, v bool) error { return w.WriteBool(v) }, eq: eqBool}, regCase[string]{name: "string", keys: []string{"a", "b", "c"}, vals: []string{"x", "y", "z"}, write: func(w *Writer, v string) error { return w.WriteString(v) }, eq: eqStr}, // Note: []byte keys are not comparable in Go; we validate by pair matching instead of using a map. regCase[[]byte]{name: "bytes", keys: [][]byte{{0x01}, {0x02, 0x03}, nil}, vals: [][]byte{{0x09}, {}, {0xFF}}, write: func(w *Writer, v []byte) error { return w.WriteBytes(v) }, eq: eqBytes}, regCase[time.Time]{name: "time", keys: []time.Time{now, later}, vals: []time.Time{later, now}, write: func(w *Writer, v time.Time) error { return w.WriteTime(v) }, eq: eqTime}, regCase[time.Duration]{name: "duration", keys: []time.Duration{0, time.Second, -5 * time.Millisecond}, vals: []time.Duration{time.Minute, -time.Second, 0}, write: func(w *Writer, v time.Duration) error { return w.WriteDuration(v) }, eq: eqDur}, regCase[complex64]{name: "complex64", keys: []complex64{1 + 2i, -3 + 4.5i, 0}, vals: []complex64{9 - 2i, 3 - 4.5i, 7}, write: func(w *Writer, v complex64) error { return w.WriteComplex64(v) }, eq: eqC64}, regCase[complex128]{name: "complex128", keys: []complex128{1 + 2i, -3 + 4.5i, 0}, vals: []complex128{9 - 2i, 3 - 4.5i, 7}, write: func(w *Writer, v complex128) error { return w.WriteComplex128(v) }, eq: eqC128}, } for _, anytc := range cases { switch tc := anytc.(type) { case regCase[bool]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteMapHeader(uint32(len(tc.keys))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for i := range tc.keys { if err := tc.write(w, tc.keys[i]); err != nil { t.Fatalf("%s key write: %v", tc.name, err) } if err := tc.write(w, tc.vals[i]); err != nil { t.Fatalf("%s val write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) seq, tail := ReadMap(r, r.ReadBool, r.ReadBool) got := maps.Collect(seq) if err := tail(); err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(got) != len(tc.keys) { t.Fatalf("%s size mismatch", tc.name) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s: key %v got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } r = NewReader(bytes.NewReader(nilMsg)) seq, tail = ReadMap(r, r.ReadBool, r.ReadBool) for k, v := range seq { t.Fatalf("%s:expected ni results, got %v:%v", tc.name, k, v) } if err := tail(); err != nil { t.Fatalf("%s tail: %v", tc.name, err) } case regCase[string]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteMapHeader(uint32(len(tc.keys))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for i := range tc.keys { if err := tc.write(w, tc.keys[i]); err != nil { t.Fatalf("%s key write: %v", tc.name, err) } if err := tc.write(w, tc.vals[i]); err != nil { t.Fatalf("%s val write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) seq, tail := ReadMap(r, r.ReadString, r.ReadString) got := maps.Collect(seq) if err := tail(); err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(got) != len(tc.keys) { t.Fatalf("%s size mismatch", tc.name) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s: key %q got %q want %q", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case regCase[[]byte]: // For []byte keys (not comparable), validate by pair presence. var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteMapHeader(uint32(len(tc.keys))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for i := range tc.keys { if err := tc.write(w, tc.keys[i]); err != nil { t.Fatalf("%s key write: %v", tc.name, err) } if err := tc.write(w, tc.vals[i]); err != nil { t.Fatalf("%s val write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } type pair struct{ k, v []byte } expected := make([]pair, len(tc.keys)) for i := range tc.keys { expected[i] = pair{append([]byte(nil), tc.keys[i]...), append([]byte(nil), tc.vals[i]...)} } r := NewReader(&buf) seq, tail := ReadMap(r, func() ([]byte, error) { return r.ReadBytes(nil) }, func() ([]byte, error) { return r.ReadBytes(nil) }) var got []pair for k, v := range seq { kk := append([]byte(nil), k...) vv := append([]byte(nil), v...) got = append(got, pair{kk, vv}) } if err := tail(); err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(got) != len(expected) { t.Fatalf("%s size mismatch got %d want %d", tc.name, len(got), len(expected)) } // Match expected pairs match := func(p pair, set []pair) bool { for _, q := range set { if eqBytes(p.k, q.k) && eqBytes(p.v, q.v) { return true } } return false } for _, p := range expected { if !match(p, got) { t.Fatalf("%s missing pair key=%v val=%v", tc.name, p.k, p.v) } } case regCase[time.Time]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteMapHeader(uint32(len(tc.keys))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for i := range tc.keys { if err := tc.write(w, tc.keys[i]); err != nil { t.Fatalf("%s key write: %v", tc.name, err) } if err := tc.write(w, tc.vals[i]); err != nil { t.Fatalf("%s val write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) seq, tail := ReadMap(r, r.ReadTime, r.ReadTime) got := make(map[time.Time]time.Time, len(tc.keys)) for k, v := range seq { got[k.UTC()] = v.UTC() } if err := tail(); err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(got) != len(tc.keys) { t.Fatalf("%s size mismatch", tc.name) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s: key %v got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case regCase[time.Duration]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteMapHeader(uint32(len(tc.keys))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for i := range tc.keys { if err := tc.write(w, tc.keys[i]); err != nil { t.Fatalf("%s key write: %v", tc.name, err) } if err := tc.write(w, tc.vals[i]); err != nil { t.Fatalf("%s val write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) seq, tail := ReadMap(r, r.ReadDuration, r.ReadDuration) got := maps.Collect(seq) if err := tail(); err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(got) != len(tc.keys) { t.Logf("got: %#v", got) t.Fatalf("%s size mismatch", tc.name) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s: key %v got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case regCase[complex64]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteMapHeader(uint32(len(tc.keys))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for i := range tc.keys { if err := tc.write(w, tc.keys[i]); err != nil { t.Fatalf("%s key write: %v", tc.name, err) } if err := tc.write(w, tc.vals[i]); err != nil { t.Fatalf("%s val write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) seq, tail := ReadMap(r, r.ReadComplex64, r.ReadComplex64) got := maps.Collect(seq) if err := tail(); err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(got) != len(tc.keys) { t.Fatalf("%s size mismatch", tc.name) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s: key %v got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case regCase[complex128]: var buf bytes.Buffer w := NewWriter(&buf) if err := w.WriteMapHeader(uint32(len(tc.keys))); err != nil { t.Fatalf("hdr %s: %v", tc.name, err) } for i := range tc.keys { if err := tc.write(w, tc.keys[i]); err != nil { t.Fatalf("%s key write: %v", tc.name, err) } if err := tc.write(w, tc.vals[i]); err != nil { t.Fatalf("%s val write: %v", tc.name, err) } } if err := w.Flush(); err != nil { t.Fatalf("flush: %v", err) } r := NewReader(&buf) seq, tail := ReadMap(r, r.ReadComplex128, r.ReadComplex128) got := maps.Collect(seq) if err := tail(); err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(got) != len(tc.keys) { t.Fatalf("%s size mismatch", tc.name) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s: key %v got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } } } } func TestReadMapBytes_AllNumberTypes_SameKeyValueTypes(t *testing.T) { type numCase[T any] struct { name string keys []T vals []T append func([]byte, T) []byte eq func(a, b T) bool } eqF32 := func(a, b float32) bool { return approxEqual(a, b) } eqF64 := func(a, b float64) bool { return approxEqual(a, b) } cases := []any{ numCase[uint]{name: "uint", keys: []uint{1, 2, 3}, vals: []uint{10, 20, 30}, append: AppendUint, eq: eqNum[uint]}, numCase[uint8]{name: "uint8", keys: []uint8{1, 2, 255}, vals: []uint8{9, 8, 7}, append: AppendUint8, eq: eqNum[uint8]}, numCase[uint16]{name: "uint16", keys: []uint16{1, 300, 65535}, vals: []uint16{100, 200, 300}, append: AppendUint16, eq: eqNum[uint16]}, numCase[uint32]{name: "uint32", keys: []uint32{1, 1 << 20, 4000000000}, vals: []uint32{42, 43, 44}, append: AppendUint32, eq: eqNum[uint32]}, numCase[uint64]{name: "uint64", keys: []uint64{1, 1 << 40, 1<<50 + 123}, vals: []uint64{5, 6, 7}, append: AppendUint64, eq: eqNum[uint64]}, numCase[int]{name: "int", keys: []int{-1, 0, 2}, vals: []int{100, -100, 0}, append: AppendInt, eq: eqNum[int]}, numCase[int8]{name: "int8", keys: []int8{-128, 0, 127}, vals: []int8{1, -1, 0}, append: AppendInt8, eq: eqNum[int8]}, numCase[int16]{name: "int16", keys: []int16{-32768, 0, 32767}, vals: []int16{2, -2, 3}, append: AppendInt16, eq: eqNum[int16]}, numCase[int32]{name: "int32", keys: []int32{-1, 0, 1}, vals: []int32{7, 8, 9}, append: AppendInt32, eq: eqNum[int32]}, numCase[int64]{name: "int64", keys: []int64{-1, 0, 1<<40 + 5}, vals: []int64{9, 8, 7}, append: AppendInt64, eq: eqNum[int64]}, numCase[float32]{name: "float32", keys: []float32{-2.5, 0, 3.25}, vals: []float32{1.5, -0.25, 10}, append: AppendFloat32, eq: eqF32}, numCase[float64]{name: "float64", keys: []float64{-2.5, 0, 3.25}, vals: []float64{1.5, -0.25, 10}, append: AppendFloat, eq: eqF64}, } for _, anytc := range cases { switch tc := anytc.(type) { case numCase[uint]: msg := AppendMapHeader(nil, uint32(len(tc.keys))) for i := range tc.keys { msg = tc.append(msg, tc.keys[i]) msg = tc.append(msg, tc.vals[i]) } seq, tail := ReadMapBytes(msg, ReadUintBytes, ReadUintBytes) got := maps.Collect(seq) remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain %d", tc.name, len(remain)) } if len(got) != len(tc.keys) { t.Fatalf("%s size got %d want %d", tc.name, len(got), len(tc.keys)) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } seq, tail = ReadMapBytes(nilMsg, ReadUintBytes, ReadUintBytes) for k, v := range seq { t.Fatalf("%s: got %v:%v want nothing", tc.name, k, v) } remain, err = tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain %d", tc.name, len(remain)) } case numCase[uint8]: msg := AppendMapHeader(nil, uint32(len(tc.keys))) for i := range tc.keys { msg = tc.append(msg, tc.keys[i]) msg = tc.append(msg, tc.vals[i]) } seq, tail := ReadMapBytes(msg, ReadUint8Bytes, ReadUint8Bytes) got := maps.Collect(seq) remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain %d", tc.name, len(remain)) } if len(got) != len(tc.keys) { t.Fatalf("%s size got %d want %d", tc.name, len(got), len(tc.keys)) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case numCase[uint16]: msg := AppendMapHeader(nil, uint32(len(tc.keys))) for i := range tc.keys { msg = tc.append(msg, tc.keys[i]) msg = tc.append(msg, tc.vals[i]) } seq, tail := ReadMapBytes(msg, ReadUint16Bytes, ReadUint16Bytes) got := maps.Collect(seq) remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain %d", tc.name, len(remain)) } if len(got) != len(tc.keys) { t.Fatalf("%s size got %d want %d", tc.name, len(got), len(tc.keys)) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case numCase[uint32]: msg := AppendMapHeader(nil, uint32(len(tc.keys))) for i := range tc.keys { msg = tc.append(msg, tc.keys[i]) msg = tc.append(msg, tc.vals[i]) } seq, tail := ReadMapBytes(msg, ReadUint32Bytes, ReadUint32Bytes) got := maps.Collect(seq) remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain %d", tc.name, len(remain)) } if len(got) != len(tc.keys) { t.Fatalf("%s size got %d want %d", tc.name, len(got), len(tc.keys)) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case numCase[uint64]: msg := AppendMapHeader(nil, uint32(len(tc.keys))) for i := range tc.keys { msg = tc.append(msg, tc.keys[i]) msg = tc.append(msg, tc.vals[i]) } seq, tail := ReadMapBytes(msg, ReadUint64Bytes, ReadUint64Bytes) got := maps.Collect(seq) remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain %d", tc.name, len(remain)) } if len(got) != len(tc.keys) { t.Fatalf("%s size got %d want %d", tc.name, len(got), len(tc.keys)) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case numCase[int]: msg := AppendMapHeader(nil, uint32(len(tc.keys))) for i := range tc.keys { msg = tc.append(msg, tc.keys[i]) msg = tc.append(msg, tc.vals[i]) } seq, tail := ReadMapBytes(msg, ReadIntBytes, ReadIntBytes) got := maps.Collect(seq) remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain %d", tc.name, len(remain)) } if len(got) != len(tc.keys) { t.Fatalf("%s size got %d want %d", tc.name, len(got), len(tc.keys)) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case numCase[int8]: msg := AppendMapHeader(nil, uint32(len(tc.keys))) for i := range tc.keys { msg = tc.append(msg, tc.keys[i]) msg = tc.append(msg, tc.vals[i]) } seq, tail := ReadMapBytes(msg, ReadInt8Bytes, ReadInt8Bytes) got := maps.Collect(seq) remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain %d", tc.name, len(remain)) } if len(got) != len(tc.keys) { t.Fatalf("%s size got %d want %d", tc.name, len(got), len(tc.keys)) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case numCase[int16]: msg := AppendMapHeader(nil, uint32(len(tc.keys))) for i := range tc.keys { msg = tc.append(msg, tc.keys[i]) msg = tc.append(msg, tc.vals[i]) } seq, tail := ReadMapBytes(msg, ReadInt16Bytes, ReadInt16Bytes) got := maps.Collect(seq) remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain %d", tc.name, len(remain)) } if len(got) != len(tc.keys) { t.Fatalf("%s size got %d want %d", tc.name, len(got), len(tc.keys)) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case numCase[int32]: msg := AppendMapHeader(nil, uint32(len(tc.keys))) for i := range tc.keys { msg = tc.append(msg, tc.keys[i]) msg = tc.append(msg, tc.vals[i]) } seq, tail := ReadMapBytes(msg, ReadInt32Bytes, ReadInt32Bytes) got := maps.Collect(seq) remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain %d", tc.name, len(remain)) } if len(got) != len(tc.keys) { t.Fatalf("%s size got %d want %d", tc.name, len(got), len(tc.keys)) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case numCase[int64]: msg := AppendMapHeader(nil, uint32(len(tc.keys))) for i := range tc.keys { msg = tc.append(msg, tc.keys[i]) msg = tc.append(msg, tc.vals[i]) } seq, tail := ReadMapBytes(msg, ReadInt64Bytes, ReadInt64Bytes) got := maps.Collect(seq) remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain %d", tc.name, len(remain)) } if len(got) != len(tc.keys) { t.Fatalf("%s size got %d want %d", tc.name, len(got), len(tc.keys)) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case numCase[float32]: msg := AppendMapHeader(nil, uint32(len(tc.keys))) for i := range tc.keys { msg = tc.append(msg, tc.keys[i]) msg = tc.append(msg, tc.vals[i]) } seq, tail := ReadMapBytes(msg, ReadFloat32Bytes, ReadFloat32Bytes) got := maps.Collect(seq) remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain %d", tc.name, len(remain)) } if len(got) != len(tc.keys) { t.Fatalf("%s size got %d want %d", tc.name, len(got), len(tc.keys)) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case numCase[float64]: msg := AppendMapHeader(nil, uint32(len(tc.keys))) for i := range tc.keys { msg = tc.append(msg, tc.keys[i]) msg = tc.append(msg, tc.vals[i]) } seq, tail := ReadMapBytes(msg, ReadFloat64Bytes, ReadFloat64Bytes) got := maps.Collect(seq) remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain %d", tc.name, len(remain)) } if len(got) != len(tc.keys) { t.Fatalf("%s size got %d want %d", tc.name, len(got), len(tc.keys)) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } } } } func TestReadMapBytes_AllRegularTypes_SameKeyValueTypes(t *testing.T) { type regCase[T any] struct { name string keys []T vals []T append func([]byte, T) []byte eq func(a, b T) bool } eqBool := func(a, b bool) bool { return a == b } eqStr := func(a, b string) bool { return a == b } eqBytes := func(a, b []byte) bool { if len(a) != len(b) { return false } for i := range a { if a[i] != b[i] { return false } } return true } eqTime := func(a, b time.Time) bool { return a.Equal(b) } eqDur := func(a, b time.Duration) bool { return a == b } eqC64 := func(a, b complex64) bool { return a == b } eqC128 := func(a, b complex128) bool { return a == b } now := time.Unix(1700000000, 123456789).UTC() later := now.Add(99 * time.Second) cases := []any{ regCase[bool]{name: "bool", keys: []bool{false, true}, vals: []bool{false, true}, append: AppendBool, eq: eqBool}, regCase[string]{name: "string", keys: []string{"a", "b", "c"}, vals: []string{"x", "y", "z"}, append: AppendString, eq: eqStr}, regCase[[]byte]{name: "bytes", keys: [][]byte{{0x01}, {0x02, 0x03}, nil}, vals: [][]byte{{0x09}, {}, {0xFF}}, append: AppendBytes, eq: eqBytes}, regCase[time.Time]{name: "time", keys: []time.Time{now, later}, vals: []time.Time{later, now}, append: AppendTime, eq: eqTime}, regCase[time.Duration]{name: "duration", keys: []time.Duration{0, time.Second, -5 * time.Millisecond}, vals: []time.Duration{time.Minute, -time.Second, 0}, append: AppendDuration, eq: eqDur}, regCase[complex64]{name: "complex64", keys: []complex64{1 + 2i, -3 + 4.5i, 0}, vals: []complex64{9 - 2i, 3 - 4.5i, 7}, append: AppendComplex64, eq: eqC64}, regCase[complex128]{name: "complex128", keys: []complex128{1 + 2i, -3 + 4.5i, 0}, vals: []complex128{9 - 2i, 3 - 4.5i, 7}, append: AppendComplex128, eq: eqC128}, } for _, anytc := range cases { switch tc := anytc.(type) { case regCase[bool]: msg := AppendMapHeader(nil, uint32(len(tc.keys))) for i := range tc.keys { msg = tc.append(msg, tc.keys[i]) msg = tc.append(msg, tc.vals[i]) } seq, tail := ReadMapBytes(msg, ReadBoolBytes, ReadBoolBytes) got := maps.Collect(seq) remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain %d", tc.name, len(remain)) } if len(got) != len(tc.keys) { t.Fatalf("%s size mismatch", tc.name) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } seq, tail = ReadMapBytes(nilMsg, ReadBoolBytes, ReadBoolBytes) for k, v := range seq { t.Fatalf("%s key %v:%v want nothing", tc.name, k, v) } remain, err = tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain %d", tc.name, len(remain)) } case regCase[string]: msg := AppendMapHeader(nil, uint32(len(tc.keys))) for i := range tc.keys { msg = tc.append(msg, tc.keys[i]) msg = tc.append(msg, tc.vals[i]) } seq, tail := ReadMapBytes(msg, ReadStringBytes, ReadStringBytes) got := maps.Collect(seq) remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain %d", tc.name, len(remain)) } if len(got) != len(tc.keys) { t.Fatalf("%s size mismatch", tc.name) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %q got %q want %q", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case regCase[[]byte]: // For []byte keys (not comparable), validate by pair presence. type pair struct{ k, v []byte } msg := AppendMapHeader(nil, uint32(len(tc.keys))) for i := range tc.keys { msg = tc.append(msg, append([]byte(nil), tc.keys[i]...)) msg = tc.append(msg, append([]byte(nil), tc.vals[i]...)) } expected := make([]pair, len(tc.keys)) for i := range tc.keys { expected[i] = pair{append([]byte(nil), tc.keys[i]...), append([]byte(nil), tc.vals[i]...)} } seq, tail := ReadMapBytes[[]byte, []byte](msg, ReadBytesZC, ReadBytesZC) var got []pair for k, v := range seq { kk := append([]byte(nil), k...) vv := append([]byte(nil), v...) got = append(got, pair{kk, vv}) } remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain %d", tc.name, len(remain)) } if len(got) != len(expected) { t.Fatalf("%s count got %d want %d", tc.name, len(got), len(expected)) } match := func(p pair, set []pair) bool { for _, q := range set { if eqBytes(p.k, q.k) && eqBytes(p.v, q.v) { return true } } return false } for _, p := range expected { if !match(p, got) { t.Fatalf("%s missing pair key=%v val=%v", tc.name, p.k, p.v) } } case regCase[time.Time]: msg := AppendMapHeader(nil, uint32(len(tc.keys))) for i := range tc.keys { msg = tc.append(msg, tc.keys[i]) msg = tc.append(msg, tc.vals[i]) } seq, tail := ReadMapBytes(msg, ReadTimeBytes, ReadTimeBytes) got := make(map[time.Time]time.Time, len(tc.keys)) for k, v := range seq { got[k.UTC()] = v.UTC() } remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain %d", tc.name, len(remain)) } if len(got) != len(tc.keys) { t.Fatalf("%s size mismatch", tc.name) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case regCase[time.Duration]: msg := AppendMapHeader(nil, uint32(len(tc.keys))) for i := range tc.keys { msg = tc.append(msg, tc.keys[i]) msg = tc.append(msg, tc.vals[i]) } seq, tail := ReadMapBytes(msg, ReadDurationBytes, ReadDurationBytes) got := maps.Collect(seq) remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain %d", tc.name, len(remain)) } if len(got) != len(tc.keys) { t.Fatalf("%s size mismatch", tc.name) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case regCase[complex64]: msg := AppendMapHeader(nil, uint32(len(tc.keys))) for i := range tc.keys { msg = tc.append(msg, tc.keys[i]) msg = tc.append(msg, tc.vals[i]) } seq, tail := ReadMapBytes(msg, ReadComplex64Bytes, ReadComplex64Bytes) got := maps.Collect(seq) remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain %d", tc.name, len(remain)) } if len(got) != len(tc.keys) { t.Fatalf("%s size mismatch", tc.name) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } case regCase[complex128]: msg := AppendMapHeader(nil, uint32(len(tc.keys))) for i := range tc.keys { msg = tc.append(msg, tc.keys[i]) msg = tc.append(msg, tc.vals[i]) } seq, tail := ReadMapBytes(msg, ReadComplex128Bytes, ReadComplex128Bytes) got := maps.Collect(seq) remain, err := tail() if err != nil { t.Fatalf("%s tail: %v", tc.name, err) } if len(remain) != 0 { t.Fatalf("%s remain %d", tc.name, len(remain)) } if len(got) != len(tc.keys) { t.Fatalf("%s size mismatch", tc.name) } for i := range tc.keys { if !tc.eq(got[tc.keys[i]], tc.vals[i]) { t.Fatalf("%s key %v got %v want %v", tc.name, tc.keys[i], got[tc.keys[i]], tc.vals[i]) } } } } } func TestReadMapBytes_TailErrorOnTruncated(t *testing.T) { // Prepare a map with 2 entries: {1: 10, 2: 20} // Then truncate after encoding the second key to induce an error while reading the second value. msg := AppendMapHeader(nil, 2) msg = AppendInt(msg, 1) msg = AppendInt(msg, 10) msg = AppendInt(msg, 2) full := AppendInt(msg, 20) trunc := full[:len(full)-2] // truncate some bytes from the last value seq, tail := ReadMapBytes(trunc, ReadIntBytes, ReadIntBytes) got := maps.Collect(seq) // We expect only the first pair to be read if len(got) != 1 || got[1] != 10 { t.Fatalf("expected only first pair (1:10), got %v", got) } remain, err := tail() if err == nil { t.Fatalf("expected tail error due to truncation") } _ = remain // remaining bytes content is not strictly asserted here } msgp-1.6.1/msgp/json.go000066400000000000000000000242611511433505400147410ustar00rootroot00000000000000package msgp import ( "bufio" "encoding/base64" "encoding/json" "io" "strconv" "unicode/utf8" ) var ( null = []byte("null") hex = []byte("0123456789abcdef") ) var defuns [_maxtype]func(jsWriter, *Reader) (int, error) // note: there is an initialization loop if // this isn't set up during init() func init() { // since none of these functions are inline-able, // there is not much of a penalty to the indirect // call. however, this is best expressed as a jump-table... defuns = [_maxtype]func(jsWriter, *Reader) (int, error){ StrType: rwString, BinType: rwBytes, MapType: rwMap, ArrayType: rwArray, Float64Type: rwFloat64, Float32Type: rwFloat32, BoolType: rwBool, IntType: rwInt, UintType: rwUint, NilType: rwNil, ExtensionType: rwExtension, Complex64Type: rwExtension, Complex128Type: rwExtension, TimeType: rwTime, } } // this is the interface // used to write json type jsWriter interface { io.Writer io.ByteWriter WriteString(string) (int, error) } // CopyToJSON reads MessagePack from 'src' and copies it // as JSON to 'dst' until EOF. func CopyToJSON(dst io.Writer, src io.Reader) (n int64, err error) { r := NewReader(src) n, err = r.WriteToJSON(dst) freeR(r) return } // WriteToJSON translates MessagePack from 'r' and writes it as // JSON to 'w' until the underlying reader returns io.EOF. It returns // the number of bytes written, and an error if it stopped before EOF. func (m *Reader) WriteToJSON(w io.Writer) (n int64, err error) { var j jsWriter var bf *bufio.Writer if jsw, ok := w.(jsWriter); ok { j = jsw } else { bf = bufio.NewWriter(w) j = bf } var nn int for err == nil { nn, err = rwNext(j, m) n += int64(nn) } if err != io.EOF { if bf != nil { bf.Flush() } return } err = nil if bf != nil { err = bf.Flush() } return } func rwNext(w jsWriter, src *Reader) (int, error) { t, err := src.NextType() if err != nil { return 0, err } return defuns[t](w, src) } func rwMap(dst jsWriter, src *Reader) (n int, err error) { var comma bool var sz uint32 var field []byte sz, err = src.ReadMapHeader() if err != nil { return } if sz == 0 { return dst.WriteString("{}") } // This is potentially a recursive call. if done, err := src.recursiveCall(); err != nil { return 0, err } else { defer done() } err = dst.WriteByte('{') if err != nil { return } n++ var nn int for i := uint32(0); i < sz; i++ { if comma { err = dst.WriteByte(',') if err != nil { return } n++ } field, err = src.ReadMapKeyPtr() if err != nil { return } nn, err = rwquoted(dst, field) n += nn if err != nil { return } err = dst.WriteByte(':') if err != nil { return } n++ nn, err = rwNext(dst, src) n += nn if err != nil { return } if !comma { comma = true } } err = dst.WriteByte('}') if err != nil { return } n++ return } func rwArray(dst jsWriter, src *Reader) (n int, err error) { err = dst.WriteByte('[') if err != nil { return } // This is potentially a recursive call. if done, err := src.recursiveCall(); err != nil { return 0, err } else { defer done() } var sz uint32 var nn int sz, err = src.ReadArrayHeader() if err != nil { return } comma := false for i := uint32(0); i < sz; i++ { if comma { err = dst.WriteByte(',') if err != nil { return } n++ } nn, err = rwNext(dst, src) n += nn if err != nil { return } comma = true } err = dst.WriteByte(']') if err != nil { return } n++ return } func rwNil(dst jsWriter, src *Reader) (int, error) { err := src.ReadNil() if err != nil { return 0, err } return dst.Write(null) } func rwFloat32(dst jsWriter, src *Reader) (int, error) { f, err := src.ReadFloat32() if err != nil { return 0, err } src.scratch = strconv.AppendFloat(src.scratch[:0], float64(f), 'f', -1, 32) return dst.Write(src.scratch) } func rwFloat64(dst jsWriter, src *Reader) (int, error) { f, err := src.ReadFloat64() if err != nil { return 0, err } src.scratch = strconv.AppendFloat(src.scratch[:0], f, 'f', -1, 64) return dst.Write(src.scratch) } func rwInt(dst jsWriter, src *Reader) (int, error) { i, err := src.ReadInt64() if err != nil { return 0, err } src.scratch = strconv.AppendInt(src.scratch[:0], i, 10) return dst.Write(src.scratch) } func rwUint(dst jsWriter, src *Reader) (int, error) { u, err := src.ReadUint64() if err != nil { return 0, err } src.scratch = strconv.AppendUint(src.scratch[:0], u, 10) return dst.Write(src.scratch) } func rwBool(dst jsWriter, src *Reader) (int, error) { b, err := src.ReadBool() if err != nil { return 0, err } if b { return dst.WriteString("true") } return dst.WriteString("false") } func rwTime(dst jsWriter, src *Reader) (int, error) { t, err := src.ReadTime() if err != nil { return 0, err } bts, err := t.MarshalJSON() if err != nil { return 0, err } return dst.Write(bts) } func rwExtension(dst jsWriter, src *Reader) (n int, err error) { et, err := src.peekExtensionType() if err != nil { return 0, err } // registered extensions can override // the JSON encoding if j, ok := extensionReg[et]; ok { var bts []byte e := j() err = src.ReadExtension(e) if err != nil { return } bts, err = json.Marshal(e) if err != nil { return } return dst.Write(bts) } e := RawExtension{} e.Type = et err = src.ReadExtension(&e) if err != nil { return } var nn int err = dst.WriteByte('{') if err != nil { return } n++ nn, err = dst.WriteString(`"type":`) n += nn if err != nil { return } src.scratch = strconv.AppendInt(src.scratch[0:0], int64(e.Type), 10) nn, err = dst.Write(src.scratch) n += nn if err != nil { return } nn, err = dst.WriteString(`,"data":"`) n += nn if err != nil { return } enc := base64.NewEncoder(base64.StdEncoding, dst) nn, err = enc.Write(e.Data) n += nn if err != nil { return } err = enc.Close() if err != nil { return } nn, err = dst.WriteString(`"}`) n += nn return } func rwString(dst jsWriter, src *Reader) (n int, err error) { lead, err := src.R.PeekByte() if err != nil { return } var read int var p []byte if isfixstr(lead) { read = int(rfixstr(lead)) src.R.Skip(1) goto write } switch lead { case mstr8: p, err = src.R.Next(2) if err != nil { return } read = int(p[1]) case mstr16: p, err = src.R.Next(3) if err != nil { return } read = int(big.Uint16(p[1:])) case mstr32: p, err = src.R.Next(5) if err != nil { return } read = int(big.Uint32(p[1:])) default: err = badPrefix(StrType, lead) return } write: if uint64(read) > src.GetMaxStringLength() { err = ErrLimitExceeded return } p, err = src.R.Next(read) if err != nil { return } n, err = rwquoted(dst, p) return } func rwBytes(dst jsWriter, src *Reader) (n int, err error) { var nn int err = dst.WriteByte('"') if err != nil { return } n++ src.scratch, err = src.ReadBytes(src.scratch[:0]) if err != nil { return } enc := base64.NewEncoder(base64.StdEncoding, dst) nn, err = enc.Write(src.scratch) n += nn if err != nil { return } err = enc.Close() if err != nil { return } err = dst.WriteByte('"') if err != nil { return } n++ return } // Below (c) The Go Authors, 2009-2014 // Subject to the BSD-style license found at http://golang.org // // see: encoding/json/encode.go:(*encodeState).stringbytes() func rwquoted(dst jsWriter, s []byte) (n int, err error) { var nn int err = dst.WriteByte('"') if err != nil { return } n++ start := 0 for i := 0; i < len(s); { if b := s[i]; b < utf8.RuneSelf { if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' && b != '&' { i++ continue } if start < i { nn, err = dst.Write(s[start:i]) n += nn if err != nil { return } } switch b { case '\\', '"': err = dst.WriteByte('\\') if err != nil { return } n++ err = dst.WriteByte(b) if err != nil { return } n++ case '\n': err = dst.WriteByte('\\') if err != nil { return } n++ err = dst.WriteByte('n') if err != nil { return } n++ case '\r': err = dst.WriteByte('\\') if err != nil { return } n++ err = dst.WriteByte('r') if err != nil { return } n++ case '\t': err = dst.WriteByte('\\') if err != nil { return } n++ err = dst.WriteByte('t') if err != nil { return } n++ default: // This encodes bytes < 0x20 except for \t, \n and \r. // It also escapes <, >, and & // because they can lead to security holes when // user-controlled strings are rendered into JSON // and served to some browsers. nn, err = dst.WriteString(`\u00`) n += nn if err != nil { return } err = dst.WriteByte(hex[b>>4]) if err != nil { return } n++ err = dst.WriteByte(hex[b&0xF]) if err != nil { return } n++ } i++ start = i continue } c, size := utf8.DecodeRune(s[i:]) if c == utf8.RuneError && size == 1 { if start < i { nn, err = dst.Write(s[start:i]) n += nn if err != nil { return } } nn, err = dst.WriteString(`\ufffd`) n += nn if err != nil { return } i += size start = i continue } // U+2028 is LINE SEPARATOR. // U+2029 is PARAGRAPH SEPARATOR. // They are both technically valid characters in JSON strings, // but don't work in JSONP, which has to be evaluated as JavaScript, // and can lead to security holes there. It is valid JSON to // escape them, so we do so unconditionally. // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. if c == '\u2028' || c == '\u2029' { if start < i { nn, err = dst.Write(s[start:i]) n += nn if err != nil { return } } nn, err = dst.WriteString(`\u202`) n += nn if err != nil { return } err = dst.WriteByte(hex[c&0xF]) if err != nil { return } n++ i += size start = i continue } i += size } if start < len(s) { nn, err = dst.Write(s[start:]) n += nn if err != nil { return } } err = dst.WriteByte('"') if err != nil { return } n++ return } msgp-1.6.1/msgp/json_bytes.go000066400000000000000000000202571511433505400161500ustar00rootroot00000000000000package msgp import ( "bufio" "encoding/base64" "encoding/json" "io" "strconv" "time" ) var unfuns [_maxtype]func(jsWriter, []byte, []byte, int) ([]byte, []byte, error) func init() { // NOTE(pmh): this is best expressed as a jump table, // but gc doesn't do that yet. revisit post-go1.5. unfuns = [_maxtype]func(jsWriter, []byte, []byte, int) ([]byte, []byte, error){ StrType: rwStringBytes, BinType: rwBytesBytes, MapType: rwMapBytes, ArrayType: rwArrayBytes, Float64Type: rwFloat64Bytes, Float32Type: rwFloat32Bytes, BoolType: rwBoolBytes, IntType: rwIntBytes, UintType: rwUintBytes, NilType: rwNullBytes, ExtensionType: rwExtensionBytes, Complex64Type: rwExtensionBytes, Complex128Type: rwExtensionBytes, TimeType: rwTimeBytes, } } // UnmarshalAsJSON takes raw messagepack and writes // it as JSON to 'w'. If an error is returned, the // bytes not translated will also be returned. If // no errors are encountered, the length of the returned // slice will be zero. func UnmarshalAsJSON(w io.Writer, msg []byte) ([]byte, error) { var ( scratch []byte cast bool dst jsWriter err error ) if jsw, ok := w.(jsWriter); ok { dst = jsw cast = true } else { dst = bufio.NewWriterSize(w, 512) } for len(msg) > 0 && err == nil { msg, scratch, err = writeNext(dst, msg, scratch, 0) } if !cast && err == nil { err = dst.(*bufio.Writer).Flush() } return msg, err } func writeNext(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { if len(msg) < 1 { return msg, scratch, ErrShortBytes } t := getType(msg[0]) if t == InvalidType { return msg, scratch, InvalidPrefixError(msg[0]) } if t == ExtensionType { et, err := peekExtension(msg) if err != nil { return nil, scratch, err } if et == TimeExtension || et == MsgTimeExtension { t = TimeType } } return unfuns[t](w, msg, scratch, depth) } func rwArrayBytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { if depth >= recursionLimit { return msg, scratch, ErrRecursion } sz, msg, err := ReadArrayHeaderBytes(msg) if err != nil { return msg, scratch, err } err = w.WriteByte('[') if err != nil { return msg, scratch, err } for i := range sz { if i != 0 { err = w.WriteByte(',') if err != nil { return msg, scratch, err } } msg, scratch, err = writeNext(w, msg, scratch, depth+1) if err != nil { return msg, scratch, err } } err = w.WriteByte(']') return msg, scratch, err } func rwMapBytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { if depth >= recursionLimit { return msg, scratch, ErrRecursion } sz, msg, err := ReadMapHeaderBytes(msg) if err != nil { return msg, scratch, err } err = w.WriteByte('{') if err != nil { return msg, scratch, err } for i := range sz { if i != 0 { err = w.WriteByte(',') if err != nil { return msg, scratch, err } } msg, scratch, err = rwMapKeyBytes(w, msg, scratch, depth) if err != nil { return msg, scratch, err } err = w.WriteByte(':') if err != nil { return msg, scratch, err } msg, scratch, err = writeNext(w, msg, scratch, depth+1) if err != nil { return msg, scratch, err } } err = w.WriteByte('}') return msg, scratch, err } func rwMapKeyBytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { msg, scratch, err := rwStringBytes(w, msg, scratch, depth) if err != nil { if tperr, ok := err.(TypeError); ok && tperr.Encoded == BinType { return rwBytesBytes(w, msg, scratch, depth) } } return msg, scratch, err } func rwStringBytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { str, msg, err := ReadStringZC(msg) if err != nil { return msg, scratch, err } _, err = rwquoted(w, str) return msg, scratch, err } func rwBytesBytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { bts, msg, err := ReadBytesZC(msg) if err != nil { return msg, scratch, err } l := base64.StdEncoding.EncodedLen(len(bts)) if cap(scratch) >= l { scratch = scratch[0:l] } else { scratch = make([]byte, l) } base64.StdEncoding.Encode(scratch, bts) err = w.WriteByte('"') if err != nil { return msg, scratch, err } _, err = w.Write(scratch) if err != nil { return msg, scratch, err } err = w.WriteByte('"') return msg, scratch, err } func rwNullBytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { msg, err := ReadNilBytes(msg) if err != nil { return msg, scratch, err } _, err = w.Write(null) return msg, scratch, err } func rwBoolBytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { b, msg, err := ReadBoolBytes(msg) if err != nil { return msg, scratch, err } if b { _, err = w.WriteString("true") return msg, scratch, err } _, err = w.WriteString("false") return msg, scratch, err } func rwIntBytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { i, msg, err := ReadInt64Bytes(msg) if err != nil { return msg, scratch, err } scratch = strconv.AppendInt(scratch[0:0], i, 10) _, err = w.Write(scratch) return msg, scratch, err } func rwUintBytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { u, msg, err := ReadUint64Bytes(msg) if err != nil { return msg, scratch, err } scratch = strconv.AppendUint(scratch[0:0], u, 10) _, err = w.Write(scratch) return msg, scratch, err } func rwFloat32Bytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { var f float32 var err error f, msg, err = ReadFloat32Bytes(msg) if err != nil { return msg, scratch, err } scratch = strconv.AppendFloat(scratch[:0], float64(f), 'f', -1, 32) _, err = w.Write(scratch) return msg, scratch, err } func rwFloat64Bytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { var f float64 var err error f, msg, err = ReadFloat64Bytes(msg) if err != nil { return msg, scratch, err } scratch = strconv.AppendFloat(scratch[:0], f, 'f', -1, 64) _, err = w.Write(scratch) return msg, scratch, err } func rwTimeBytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { var t time.Time var err error t, msg, err = ReadTimeBytes(msg) if err != nil { return msg, scratch, err } bts, err := t.MarshalJSON() if err != nil { return msg, scratch, err } _, err = w.Write(bts) return msg, scratch, err } func rwExtensionBytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { var err error var et int8 et, err = peekExtension(msg) if err != nil { return msg, scratch, err } // if it's time.Time if et == TimeExtension || et == MsgTimeExtension { var tm time.Time tm, msg, err = ReadTimeBytes(msg) if err != nil { return msg, scratch, err } bts, err := tm.MarshalJSON() if err != nil { return msg, scratch, err } _, err = w.Write(bts) return msg, scratch, err } // if the extension is registered, // use its canonical JSON form if f, ok := extensionReg[et]; ok { e := f() msg, err = ReadExtensionBytes(msg, e) if err != nil { return msg, scratch, err } bts, err := json.Marshal(e) if err != nil { return msg, scratch, err } _, err = w.Write(bts) return msg, scratch, err } // otherwise, write `{"type": , "data": ""}` r := RawExtension{} r.Type = et msg, err = ReadExtensionBytes(msg, &r) if err != nil { return msg, scratch, err } scratch, err = writeExt(w, r, scratch) return msg, scratch, err } func writeExt(w jsWriter, r RawExtension, scratch []byte) ([]byte, error) { _, err := w.WriteString(`{"type":`) if err != nil { return scratch, err } scratch = strconv.AppendInt(scratch[0:0], int64(r.Type), 10) _, err = w.Write(scratch) if err != nil { return scratch, err } _, err = w.WriteString(`,"data":"`) if err != nil { return scratch, err } l := base64.StdEncoding.EncodedLen(len(r.Data)) if cap(scratch) >= l { scratch = scratch[0:l] } else { scratch = make([]byte, l) } base64.StdEncoding.Encode(scratch, r.Data) _, err = w.Write(scratch) if err != nil { return scratch, err } _, err = w.WriteString(`"}`) return scratch, err } msgp-1.6.1/msgp/json_bytes_test.go000066400000000000000000000045141511433505400172050ustar00rootroot00000000000000package msgp import ( "bytes" "encoding/json" "testing" "time" ) func TestUnmarshalJSON(t *testing.T) { var buf bytes.Buffer enc := NewWriter(&buf) enc.WriteMapHeader(5) enc.WriteString("thing_1") enc.WriteString("a string object") enc.WriteString("a_map") enc.WriteMapHeader(2) // INNER enc.WriteString("cmplx") enc.WriteComplex64(complex(1.0, 1.0)) enc.WriteString("int_b") enc.WriteInt64(-100) enc.WriteString("an extension") enc.WriteExtension(&RawExtension{Type: 1, Data: []byte("blaaahhh")}) enc.WriteString("some bytes") enc.WriteBytes([]byte("here are some bytes")) enc.WriteString("now") enc.WriteTime(time.Now()) enc.Flush() var js bytes.Buffer _, err := UnmarshalAsJSON(&js, buf.Bytes()) if err != nil { t.Logf("%s", js.Bytes()) t.Fatal(err) } mp := make(map[string]any) err = json.Unmarshal(js.Bytes(), &mp) if err != nil { t.Log(js.String()) t.Fatalf("Error unmarshaling: %s", err) } if len(mp) != 5 { t.Errorf("map length should be %d, not %d", 5, len(mp)) } so, ok := mp["thing_1"] if !ok || so != "a string object" { t.Errorf("expected %q; got %q", "a string object", so) } if _, ok := mp["now"]; !ok { t.Error(`"now" field doesn't exist`) } c, ok := mp["a_map"] if !ok { t.Error(`"a_map" field doesn't exist`) } else { if m, ok := c.(map[string]any); ok { if _, ok := m["cmplx"]; !ok { t.Error(`"a_map.cmplx" doesn't exist`) } } else { t.Error(`can't type-assert "c" to map[string]interface{}`) } } t.Logf("JSON: %s", js.Bytes()) } func BenchmarkUnmarshalAsJSON(b *testing.B) { var buf bytes.Buffer enc := NewWriter(&buf) enc.WriteMapHeader(4) enc.WriteString("thing_1") enc.WriteString("a string object") enc.WriteString("a_first_map") enc.WriteMapHeader(2) enc.WriteString("float_a") enc.WriteFloat32(1.0) enc.WriteString("int_b") enc.WriteInt64(-100) enc.WriteString("an array") enc.WriteArrayHeader(2) enc.WriteBool(true) enc.WriteUint(2089) enc.WriteString("a_second_map") enc.WriteMapStrStr(map[string]string{ "internal_one": "blah", "internal_two": "blahhh...", }) enc.Flush() var js bytes.Buffer bts := buf.Bytes() _, err := UnmarshalAsJSON(&js, bts) if err != nil { b.Fatal(err) } b.SetBytes(int64(len(js.Bytes()))) b.ResetTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { js.Reset() UnmarshalAsJSON(&js, bts) } } msgp-1.6.1/msgp/json_test.go000066400000000000000000000074501511433505400160010ustar00rootroot00000000000000package msgp import ( "bytes" "encoding/json" "reflect" "testing" "unicode/utf8" ) func TestCopyJSON(t *testing.T) { var buf bytes.Buffer enc := NewWriter(&buf) const mapLength = 6 enc.WriteMapHeader(mapLength) enc.WriteString("thing_1") enc.WriteString("a string object") enc.WriteString("a_map") enc.WriteMapHeader(2) enc.WriteString("float_a") enc.WriteFloat32(1.0) enc.WriteString("int_b") enc.WriteInt64(-100) enc.WriteString("some bytes") enc.WriteBytes([]byte("here are some bytes")) enc.WriteString("a bool") enc.WriteBool(true) enc.WriteString("a map") enc.WriteMapStrStr(map[string]string{ "internal_one": "blah", "internal_two": "blahhh...", }) enc.WriteString("float64") const encodedFloat64 = 1672209023 enc.WriteFloat64(encodedFloat64) enc.Flush() var js bytes.Buffer _, err := CopyToJSON(&js, &buf) if err != nil { t.Fatal(err) } mp := make(map[string]any) err = json.Unmarshal(js.Bytes(), &mp) if err != nil { t.Log(js.String()) t.Fatalf("Error unmarshaling: %s", err) } if len(mp) != mapLength { t.Errorf("map length should be %d, not %d", mapLength, len(mp)) } so, ok := mp["thing_1"] if !ok || so != "a string object" { t.Errorf("expected %q; got %q", "a string object", so) } in, ok := mp["a map"] if !ok { t.Error("no key 'a map'") } if inm, ok := in.(map[string]any); !ok { t.Error("inner map not type-assertable to map[string]interface{}") } else { inm1, ok := inm["internal_one"] if !ok || !reflect.DeepEqual(inm1, "blah") { t.Errorf("inner map field %q should be %q, not %q", "internal_one", "blah", inm1) } } if actual := mp["float64"]; float64(encodedFloat64) != actual.(float64) { t.Errorf("expected %G, got %G", float64(encodedFloat64), actual) } } // Encoder should generate valid utf-8 even if passed bad input func TestCopyJSONNegativeUTF8(t *testing.T) { // Single string with non-compliant utf-8 byte stringWithBadUTF8 := []byte{ 0xa1, 0xe0, } src := bytes.NewBuffer(stringWithBadUTF8) var js bytes.Buffer _, err := CopyToJSON(&js, src) if err != nil { t.Fatal(err) } // Even though we provided bad input, should have escaped the naughty character if !utf8.Valid(js.Bytes()) { t.Errorf("Expected JSON to be valid utf-8 even when provided bad input") } // Expect a bad character string expected := `"\ufffd"` if js.String() != expected { t.Errorf("Expected: '%s', got: '%s'", expected, js.String()) } } func BenchmarkCopyToJSON(b *testing.B) { var buf bytes.Buffer enc := NewWriter(&buf) enc.WriteMapHeader(4) enc.WriteString("thing_1") enc.WriteString("a string object") enc.WriteString("a_first_map") enc.WriteMapHeader(2) enc.WriteString("float_a") enc.WriteFloat32(1.0) enc.WriteString("int_b") enc.WriteInt64(-100) enc.WriteString("an array") enc.WriteArrayHeader(2) enc.WriteBool(true) enc.WriteUint(2089) enc.WriteString("a_second_map") enc.WriteMapStrStr(map[string]string{ "internal_one": "blah", "internal_two": "blahhh...", }) enc.Flush() var js bytes.Buffer bts := buf.Bytes() _, err := CopyToJSON(&js, &buf) if err != nil { b.Fatal(err) } b.SetBytes(int64(len(js.Bytes()))) b.ResetTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { js.Reset() CopyToJSON(&js, bytes.NewReader(bts)) } } func BenchmarkStdlibJSON(b *testing.B) { obj := map[string]any{ "thing_1": "a string object", "a_first_map": map[string]any{ "float_a": float32(1.0), "float_b": -100, }, "an array": []any{ "part_A", "part_B", }, "a_second_map": map[string]any{ "internal_one": "blah", "internal_two": "blahhh...", }, } var js bytes.Buffer err := json.NewEncoder(&js).Encode(&obj) if err != nil { b.Fatal(err) } b.SetBytes(int64(len(js.Bytes()))) b.ResetTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { js.Reset() json.NewEncoder(&js).Encode(&obj) } } msgp-1.6.1/msgp/number.go000066400000000000000000000213551511433505400152610ustar00rootroot00000000000000package msgp import ( "math" "math/bits" "strconv" ) // The portable parts of the Number implementation // Number can be // an int64, uint64, float32, // or float64 internally. // It can decode itself // from any of the native // messagepack number types. // The zero-value of Number // is Int(0). Using the equality // operator with Number compares // both the type and the value // of the number. type Number struct { // internally, this // is just a tagged union. // the raw bits of the number // are stored the same way regardless. bits uint64 typ Type } // AsInt sets the number to an int64. func (n *Number) AsInt(i int64) { // we always store int(0) // as {0, InvalidType} in // order to preserve // the behavior of the == operator if i == 0 { n.typ = InvalidType n.bits = 0 return } n.typ = IntType n.bits = uint64(i) } // AsUint sets the number to a uint64. func (n *Number) AsUint(u uint64) { n.typ = UintType n.bits = u } // AsFloat32 sets the value of the number // to a float32. func (n *Number) AsFloat32(f float32) { n.typ = Float32Type n.bits = uint64(math.Float32bits(f)) } // AsFloat64 sets the value of the // number to a float64. func (n *Number) AsFloat64(f float64) { n.typ = Float64Type n.bits = math.Float64bits(f) } // Int casts the number as an int64, and // returns whether or not that was the // underlying type. func (n *Number) Int() (int64, bool) { return int64(n.bits), n.typ == IntType || n.typ == InvalidType } // Uint casts the number as a uint64, and returns // whether or not that was the underlying type. func (n *Number) Uint() (uint64, bool) { return n.bits, n.typ == UintType } // Float casts the number to a float64, and // returns whether that was the underlying // type (either a float64 or a float32). func (n *Number) Float() (float64, bool) { switch n.typ { case Float32Type: return float64(math.Float32frombits(uint32(n.bits))), true case Float64Type: return math.Float64frombits(n.bits), true default: return 0.0, false } } // Type will return one of: // Float64Type, Float32Type, UintType, or IntType. func (n *Number) Type() Type { if n.typ == InvalidType { return IntType } return n.typ } // DecodeMsg implements msgp.Decodable func (n *Number) DecodeMsg(r *Reader) error { typ, err := r.NextType() if err != nil { return err } switch typ { case Float32Type: f, err := r.ReadFloat32() if err != nil { return err } n.AsFloat32(f) return nil case Float64Type: f, err := r.ReadFloat64() if err != nil { return err } n.AsFloat64(f) return nil case IntType: i, err := r.ReadInt64() if err != nil { return err } n.AsInt(i) return nil case UintType: u, err := r.ReadUint64() if err != nil { return err } n.AsUint(u) return nil default: return TypeError{Encoded: typ, Method: IntType} } } // UnmarshalMsg implements msgp.Unmarshaler func (n *Number) UnmarshalMsg(b []byte) ([]byte, error) { typ := NextType(b) switch typ { case IntType: i, o, err := ReadInt64Bytes(b) if err != nil { return b, err } n.AsInt(i) return o, nil case UintType: u, o, err := ReadUint64Bytes(b) if err != nil { return b, err } n.AsUint(u) return o, nil case Float64Type: f, o, err := ReadFloat64Bytes(b) if err != nil { return b, err } n.AsFloat64(f) return o, nil case Float32Type: f, o, err := ReadFloat32Bytes(b) if err != nil { return b, err } n.AsFloat32(f) return o, nil default: return b, TypeError{Method: IntType, Encoded: typ} } } // MarshalMsg implements msgp.Marshaler func (n *Number) MarshalMsg(b []byte) ([]byte, error) { switch n.typ { case IntType: return AppendInt64(b, int64(n.bits)), nil case UintType: return AppendUint64(b, n.bits), nil case Float64Type: return AppendFloat64(b, math.Float64frombits(n.bits)), nil case Float32Type: return AppendFloat32(b, math.Float32frombits(uint32(n.bits))), nil default: return AppendInt64(b, 0), nil } } // EncodeMsg implements msgp.Encodable func (n *Number) EncodeMsg(w *Writer) error { switch n.typ { case IntType: return w.WriteInt64(int64(n.bits)) case UintType: return w.WriteUint64(n.bits) case Float64Type: return w.WriteFloat64(math.Float64frombits(n.bits)) case Float32Type: return w.WriteFloat32(math.Float32frombits(uint32(n.bits))) default: return w.WriteInt64(0) } } // CoerceInt attempts to coerce the value of // the number into a signed integer and returns // whether it was successful. // "Success" implies that no precision in the value of // the number was lost, which means that the number was an integer or // a floating point that mapped exactly to an integer without rounding. func (n *Number) CoerceInt() (int64, bool) { switch n.typ { case InvalidType, IntType: // InvalidType just means un-initialized. return int64(n.bits), true case UintType: return int64(n.bits), n.bits <= math.MaxInt64 case Float32Type: f := math.Float32frombits(uint32(n.bits)) if n.isExactInt() && f <= math.MaxInt64 && f >= math.MinInt64 { return int64(f), true } if n.bits == 0 || n.bits == 1<<31 { return 0, true } case Float64Type: f := math.Float64frombits(n.bits) if n.isExactInt() && f <= math.MaxInt64 && f >= math.MinInt64 { return int64(f), true } return 0, n.bits == 0 || n.bits == 1<<63 } return 0, false } // CoerceUInt attempts to coerce the value of // the number into an unsigned integer and returns // whether it was successful. // "Success" implies that no precision in the value of // the number was lost, which means that the number was an integer or // a floating point that mapped exactly to an integer without rounding. func (n *Number) CoerceUInt() (uint64, bool) { switch n.typ { case InvalidType, IntType: // InvalidType just means un-initialized. if int64(n.bits) >= 0 { return n.bits, true } case UintType: return n.bits, true case Float32Type: f := math.Float32frombits(uint32(n.bits)) if f >= 0 && f <= math.MaxUint64 && n.isExactInt() { return uint64(f), true } if n.bits == 0 || n.bits == 1<<31 { return 0, true } case Float64Type: f := math.Float64frombits(n.bits) if f >= 0 && f <= math.MaxUint64 && n.isExactInt() { return uint64(f), true } return 0, n.bits == 0 || n.bits == 1<<63 } return 0, false } // isExactInt will return true if the number represents an integer value. // NaN, Inf returns false. func (n *Number) isExactInt() bool { var eBits int // Exponent bits var mBits int // Mantissa bits switch n.typ { case InvalidType, IntType, UintType: return true case Float32Type: eBits = 8 mBits = 23 case Float64Type: eBits = 11 mBits = 52 default: return false } // Calculate float parts exp := int(n.bits>>mBits) & ((1 << eBits) - 1) mant := n.bits & ((1 << mBits) - 1) if exp == 0 && mant == 0 { // Handle zero value. return true } exp -= (1 << (eBits - 1)) - 1 if exp < 0 || exp == 1<<(eBits-1) { // Negative exponent is never integer (except zero handled above) // Handles NaN (exp all 1s) return false } if exp >= mBits { // If we have more exponent than mantissa bits it is always an integer. return true } // Check if all bits below the exponent are zero. return bits.TrailingZeros64(mant) >= mBits-exp } // CoerceFloat returns the number as a float64. // If the number is an integer, it will be // converted to a float64 with the closest representation. func (n *Number) CoerceFloat() float64 { switch n.typ { case IntType: return float64(int64(n.bits)) case UintType: return float64(n.bits) case Float32Type: return float64(math.Float32frombits(uint32(n.bits))) case Float64Type: return math.Float64frombits(n.bits) default: return 0.0 } } // Msgsize implements msgp.Sizer func (n *Number) Msgsize() int { switch n.typ { case Float32Type: return Float32Size case Float64Type: return Float64Size case IntType: return Int64Size case UintType: return Uint64Size default: return 1 // fixint(0) } } // MarshalJSON implements json.Marshaler func (n *Number) MarshalJSON() ([]byte, error) { t := n.Type() if t == InvalidType { return []byte{'0'}, nil } out := make([]byte, 0, 32) switch t { case Float32Type, Float64Type: f, _ := n.Float() return strconv.AppendFloat(out, f, 'f', -1, 64), nil case IntType: i, _ := n.Int() return strconv.AppendInt(out, i, 10), nil case UintType: u, _ := n.Uint() return strconv.AppendUint(out, u, 10), nil default: panic("(*Number).typ is invalid") } } // String implements fmt.Stringer func (n *Number) String() string { switch n.typ { case InvalidType: return "0" case Float32Type, Float64Type: f, _ := n.Float() return strconv.FormatFloat(f, 'f', -1, 64) case IntType: i, _ := n.Int() return strconv.FormatInt(i, 10) case UintType: u, _ := n.Uint() return strconv.FormatUint(u, 10) default: panic("(*Number).typ is invalid") } } msgp-1.6.1/msgp/number_test.go000066400000000000000000000070751511433505400163230ustar00rootroot00000000000000package msgp import ( "bytes" "math" "testing" ) func TestNumber(t *testing.T) { n := Number{} if n.Type() != IntType { t.Errorf("expected zero-value type to be %s; got %s", IntType, n.Type()) } if n.String() != "0" { t.Errorf("expected Number{}.String() to be \"0\" but got %q", n.String()) } n.AsInt(248) i, ok := n.Int() if !ok || i != 248 || n.Type() != IntType || n.String() != "248" { t.Errorf("%d in; %d out!", 248, i) } n.AsFloat64(3.141) f, ok := n.Float() if !ok || f != 3.141 || n.Type() != Float64Type || n.String() != "3.141" { t.Errorf("%f in; %f out!", 3.141, f) } n.AsUint(40000) u, ok := n.Uint() if !ok || u != 40000 || n.Type() != UintType || n.String() != "40000" { t.Errorf("%d in; %d out!", 40000, u) } nums := []any{ float64(3.14159), int64(-29081), uint64(90821983), float32(3.141), } var dat []byte var buf bytes.Buffer wr := NewWriter(&buf) for _, n := range nums { dat, _ = AppendIntf(dat, n) wr.WriteIntf(n) } wr.Flush() mout := make([]Number, len(nums)) dout := make([]Number, len(nums)) rd := NewReader(&buf) unm := dat for i := range nums { var err error unm, err = mout[i].UnmarshalMsg(unm) if err != nil { t.Fatal("unmarshal error:", err) } err = dout[i].DecodeMsg(rd) if err != nil { t.Fatal("decode error:", err) } if mout[i] != dout[i] { t.Errorf("for %#v, got %#v from unmarshal and %#v from decode", nums[i], mout[i], dout[i]) } } buf.Reset() var odat []byte for i := range nums { var err error odat, err = mout[i].MarshalMsg(odat) if err != nil { t.Fatal("marshal error:", err) } err = dout[i].EncodeMsg(wr) if err != nil { t.Fatal("encode error", err) } } wr.Flush() if !bytes.Equal(dat, odat) { t.Errorf("marshal: expected output %#v; got %#v", dat, odat) } if !bytes.Equal(dat, buf.Bytes()) { t.Errorf("encode: expected output %#v; got %#v", dat, buf.Bytes()) } } func TestConv32(t *testing.T) { for i := -1 << 24; i < 1<<25; i++ { x := math.Float32bits(float32(i)) exp := int(x>>23)&255 - 127 mant := x & ((1 << 23) - 1) isExact := false if exp >= 23 || (exp == -127 && mant == 0) { isExact = true } // Only exp >= 0 can be exact integer if exp >= 0 && exp <= 23 { mantissaMask := uint32((1 << (23 - exp)) - 1) isExact = (mant & mantissaMask) == 0 } n := Number{bits: uint64(x), typ: Float32Type} got := n.isExactInt() if got != isExact { t.Errorf("n.IsExactInt(): got %t, want %t", got, isExact) } n = Number{bits: uint64(math.Float32bits(float32(i) + 0.1)), typ: Float32Type} got = n.isExactInt() if got != false && i > -2097152 && i < 2097152 { val, ok := n.Float() t.Fatalf("n.IsExactInt(%f): got %t, want %t, ok: %v", val, got, false, ok) } } } func TestConv64(t *testing.T) { for i := -1 << 30; i < 1<<30; i++ { if testing.Short() { i += 8 } x := math.Float64bits(float64(i)) exp := int(x>>52)&2047 - 1023 mant := x & ((1 << 52) - 1) isExact := false if exp >= 52 || (exp == -1023 && mant == 0) { isExact = true } // Only exp >= 0 can be exact integer if exp >= 0 && exp <= 52 { mantissaMask := uint64((1 << (52 - exp)) - 1) isExact = (mant & mantissaMask) == 0 } n := Number{bits: x, typ: Float64Type} got := n.isExactInt() if got != isExact { t.Errorf("n.IsExactInt(): got %t, want %t", got, isExact) } if !got { t.Fatal(i) } n = Number{bits: math.Float64bits(float64(i) + 0.1), typ: Float64Type} got = n.isExactInt() if got != false { val, ok := n.Float() t.Fatalf("n.IsExactInt(%f): got %t, want %t, ok: %v", val, got, false, ok) } } } msgp-1.6.1/msgp/purego.go000066400000000000000000000003771511433505400152730ustar00rootroot00000000000000//go:build (purego && !unsafe) || appengine package msgp // let's just assume appengine // uses 64-bit hardware... const smallint = false func UnsafeString(b []byte) string { return string(b) } func UnsafeBytes(s string) []byte { return []byte(s) } msgp-1.6.1/msgp/raw_test.go000066400000000000000000000041551511433505400156200ustar00rootroot00000000000000package msgp import ( "bytes" "testing" "time" ) // all standard interfaces type allifaces interface { Encodable Decodable Marshaler Unmarshaler Sizer } func TestRaw(t *testing.T) { bts := make([]byte, 0, 512) bts = AppendMapHeader(bts, 3) bts = AppendString(bts, "key_one") bts = AppendFloat64(bts, -1.0) bts = AppendString(bts, "key_two") bts = AppendString(bts, "value_two") bts = AppendString(bts, "key_three") bts = AppendTime(bts, time.Now()) var r Raw // verify that Raw satisfies // the interfaces we want it to var _ allifaces = &r // READ TESTS extra, err := r.UnmarshalMsg(bts) if err != nil { t.Fatal("error from UnmarshalMsg:", err) } if len(extra) != 0 { t.Errorf("expected 0 bytes left; found %d", len(extra)) } if !bytes.Equal([]byte(r), bts) { t.Fatal("value of raw and input slice are not equal after UnmarshalMsg") } r = r[:0] var buf bytes.Buffer buf.Write(bts) rd := NewReader(&buf) err = r.DecodeMsg(rd) if err != nil { t.Fatal("error from DecodeMsg:", err) } if !bytes.Equal([]byte(r), bts) { t.Fatal("value of raw and input slice are not equal after DecodeMsg") } // WRITE TESTS buf.Reset() wr := NewWriter(&buf) err = r.EncodeMsg(wr) if err != nil { t.Fatal("error from EncodeMsg:", err) } wr.Flush() if !bytes.Equal(buf.Bytes(), bts) { t.Fatal("value of buf.Bytes() and input slice are not equal after EncodeMsg") } var outsl []byte outsl, err = r.MarshalMsg(outsl) if err != nil { t.Fatal("error from MarshalMsg:", err) } if !bytes.Equal(outsl, bts) { t.Fatal("value of output and input of MarshalMsg are not equal.") } } func TestNullRaw(t *testing.T) { // Marshal/Unmarshal var x, y Raw if bts, err := x.MarshalMsg(nil); err != nil { t.Fatal(err) } else if _, err = y.UnmarshalMsg(bts); err != nil { t.Fatal(err) } if !bytes.Equal(x, y) { t.Fatal("compare") } // Encode/Decode var buf bytes.Buffer wr := NewWriter(&buf) if err := x.EncodeMsg(wr); err != nil { t.Fatal(err) } wr.Flush() rd := NewReader(&buf) if err := y.DecodeMsg(rd); err != nil { t.Fatal(err) } if !bytes.Equal(x, y) { t.Fatal("compare") } } msgp-1.6.1/msgp/read.go000066400000000000000000001004641511433505400147030ustar00rootroot00000000000000package msgp import ( "encoding" "encoding/binary" "encoding/json" "fmt" "io" "math" "strconv" "sync" "time" "github.com/philhofer/fwd" ) // where we keep old *Readers var readerPool = sync.Pool{New: func() any { return &Reader{} }} // Type is a MessagePack wire type, // including this package's built-in // extension types. type Type byte // MessagePack Types // // The zero value of Type // is InvalidType. const ( InvalidType Type = iota // MessagePack built-in types StrType BinType MapType ArrayType Float64Type Float32Type BoolType IntType UintType NilType DurationType ExtensionType // pseudo-types provided // by extensions Complex64Type Complex128Type TimeType NumberType _maxtype ) // String implements fmt.Stringer func (t Type) String() string { switch t { case StrType: return "str" case BinType: return "bin" case MapType: return "map" case ArrayType: return "array" case Float64Type: return "float64" case Float32Type: return "float32" case BoolType: return "bool" case UintType: return "uint" case IntType: return "int" case ExtensionType: return "ext" case NilType: return "nil" case NumberType: return "number" default: return "" } } func freeR(m *Reader) { readerPool.Put(m) } // Unmarshaler is the interface fulfilled // by objects that know how to unmarshal // themselves from MessagePack. // UnmarshalMsg unmarshals the object // from binary, returing any leftover // bytes and any errors encountered. type Unmarshaler interface { UnmarshalMsg([]byte) ([]byte, error) } // Decodable is the interface fulfilled // by objects that know how to read // themselves from a *Reader. type Decodable interface { DecodeMsg(*Reader) error } // Decode decodes 'd' from 'r'. func Decode(r io.Reader, d Decodable) error { rd := NewReader(r) err := d.DecodeMsg(rd) freeR(rd) return err } // NewReader returns a *Reader that // reads from the provided reader. The // reader will be buffered. func NewReader(r io.Reader) *Reader { p := readerPool.Get().(*Reader) if p.R == nil { p.R = fwd.NewReader(r) } else { p.R.Reset(r) } return p } // NewReaderSize returns a *Reader with a buffer of the given size. // (This is vastly preferable to passing the decoder a reader that is already buffered.) func NewReaderSize(r io.Reader, sz int) *Reader { return &Reader{R: fwd.NewReaderSize(r, sz)} } // NewReaderBuf returns a *Reader with a provided buffer. func NewReaderBuf(r io.Reader, buf []byte) *Reader { return &Reader{R: fwd.NewReaderBuf(r, buf)} } // Reader wraps an io.Reader and provides // methods to read MessagePack-encoded values // from it. Readers are buffered. type Reader struct { // R is the buffered reader // that the Reader uses // to decode MessagePack. // The Reader itself // is stateless; all the // buffering is done // within R. R *fwd.Reader scratch []byte recursionDepth int maxRecursionDepth int // maximum recursion depth maxElements uint32 // maximum number of elements in arrays and maps maxStrLen uint64 // maximum number of bytes in any string } // Read implements `io.Reader` func (m *Reader) Read(p []byte) (int, error) { return m.R.Read(p) } // CopyNext reads the next object from m without decoding it and writes it to w. // It avoids unnecessary copies internally. func (m *Reader) CopyNext(w io.Writer) (int64, error) { sz, o, err := getNextSize(m.R) if err != nil { return 0, err } var n int64 // Opportunistic optimization: if we can fit the whole thing in the m.R // buffer, then just get a pointer to that, and pass it to w.Write, // avoiding an allocation. if int(sz) >= 0 && int(sz) <= m.R.BufferSize() { var nn int var buf []byte buf, err = m.R.Next(int(sz)) if err != nil { if err == io.ErrUnexpectedEOF { err = ErrShortBytes } return 0, err } nn, err = w.Write(buf) n += int64(nn) } else { // Fall back to io.CopyN. // May avoid allocating if w is a ReaderFrom (e.g. bytes.Buffer) n, err = io.CopyN(w, m.R, int64(sz)) if err == io.ErrUnexpectedEOF { err = ErrShortBytes } } if err != nil { return n, err } else if n < int64(sz) { return n, io.ErrShortWrite } if done, err := m.recursiveCall(); err != nil { return n, err } else { defer done() } // for maps and slices, read elements for range o { var n2 int64 n2, err = m.CopyNext(w) if err != nil { return n, err } n += n2 } return n, nil } // SetMaxRecursionDepth sets the maximum recursion depth. func (m *Reader) SetMaxRecursionDepth(d int) { m.maxRecursionDepth = d } // GetMaxRecursionDepth returns the maximum recursion depth. // Set to 0 to use the default value of 100000. func (m *Reader) GetMaxRecursionDepth() int { if m.maxRecursionDepth <= 0 { return recursionLimit } return m.maxRecursionDepth } // SetMaxElements sets the maximum number of elements to allow in map, bin, array or extension payload. // Setting this to 0 will allow any number of elements - math.MaxUint32. // This does currently apply to generated code. func (m *Reader) SetMaxElements(d uint32) { m.maxElements = d } // GetMaxElements will return the maximum number of elements in a map, bin, array or extension payload. func (m *Reader) GetMaxElements() uint32 { if m.maxElements <= 0 { return math.MaxUint32 } return m.maxElements } // SetMaxStringLength sets the maximum number of bytes to allow in strings. // Setting this == 0 will allow any number of elements - math.MaxUint64. func (m *Reader) SetMaxStringLength(d uint64) { m.maxStrLen = d } // GetMaxStringLength will return the current string length limit. func (m *Reader) GetMaxStringLength() uint64 { if m.maxStrLen <= 0 { return math.MaxUint64 } return min(m.maxStrLen, math.MaxUint64) } // recursiveCall will increment the recursion depth and return an error if it is exceeded. // If a nil error is returned, done must be called to decrement the counter. func (m *Reader) recursiveCall() (done func(), err error) { if m.recursionDepth >= m.GetMaxRecursionDepth() { return func() {}, ErrRecursion } m.recursionDepth++ return func() { m.recursionDepth-- }, nil } // ReadFull implements `io.ReadFull` func (m *Reader) ReadFull(p []byte) (int, error) { return m.R.ReadFull(p) } // Reset resets the underlying reader. func (m *Reader) Reset(r io.Reader) { m.R.Reset(r) } // Buffered returns the number of bytes currently in the read buffer. func (m *Reader) Buffered() int { return m.R.Buffered() } // BufferSize returns the capacity of the read buffer. func (m *Reader) BufferSize() int { return m.R.BufferSize() } // NextType returns the next object type to be decoded. func (m *Reader) NextType() (Type, error) { next, err := m.R.PeekByte() if err != nil { return InvalidType, err } t := getType(next) if t == InvalidType { return t, InvalidPrefixError(next) } if t == ExtensionType { v, err := m.peekExtensionType() if err != nil { return InvalidType, err } switch v { case Complex64Extension: return Complex64Type, nil case Complex128Extension: return Complex128Type, nil case TimeExtension, MsgTimeExtension: return TimeType, nil } } return t, nil } // IsNil returns whether or not // the next byte is a null messagepack byte func (m *Reader) IsNil() bool { p, err := m.R.PeekByte() return err == nil && p == mnil } // getNextSize returns the size of the next object on the wire. // returns (obj size, obj elements, error) // only maps and arrays have non-zero obj elements // for maps and arrays, obj size does not include elements // // use uintptr b/c it's guaranteed to be large enough // to hold whatever we can fit in memory. func getNextSize(r *fwd.Reader) (uintptr, uintptr, error) { lead, err := r.PeekByte() if err != nil { return 0, 0, err } spec := getBytespec(lead) size, mode := spec.size, spec.extra if size == 0 { return 0, 0, InvalidPrefixError(lead) } if mode >= 0 { return uintptr(size), uintptr(mode), nil } b, err := r.Peek(int(size)) if err != nil { return 0, 0, err } switch mode { case extra8: return uintptr(size) + uintptr(b[1]), 0, nil case extra16: return uintptr(size) + uintptr(big.Uint16(b[1:])), 0, nil case extra32: return uintptr(size) + uintptr(big.Uint32(b[1:])), 0, nil case map16v: return uintptr(size), 2 * uintptr(big.Uint16(b[1:])), nil case map32v: return uintptr(size), 2 * uintptr(big.Uint32(b[1:])), nil case array16v: return uintptr(size), uintptr(big.Uint16(b[1:])), nil case array32v: return uintptr(size), uintptr(big.Uint32(b[1:])), nil default: return 0, 0, fatal } } // Skip skips over the next object, regardless of // its type. If it is an array or map, the whole array // or map will be skipped. func (m *Reader) Skip() error { var ( v uintptr // bytes o uintptr // objects err error p []byte ) // we can use the faster // method if we have enough // buffered data if m.R.Buffered() >= 5 { p, err = m.R.Peek(5) if err != nil { return err } v, o, err = getSize(p) if err != nil { return err } } else { v, o, err = getNextSize(m.R) if err != nil { return err } } // 'v' is always non-zero // if err == nil _, err = m.R.Skip(int(v)) if err != nil { return err } // for maps and slices, skip elements with recursive call if done, err := m.recursiveCall(); err != nil { return err } else { defer done() } for x := uintptr(0); x < o; x++ { err = m.Skip() if err != nil { return err } } return nil } // ReadMapHeader reads the next object // as a map header and returns the size // of the map and the number of bytes written. // It will return a TypeError{} if the next // object is not a map. func (m *Reader) ReadMapHeader() (sz uint32, err error) { var p []byte var lead byte lead, err = m.R.PeekByte() if err != nil { return } if isfixmap(lead) { sz = uint32(rfixmap(lead)) _, err = m.R.Skip(1) return } switch lead { case mmap16: p, err = m.R.Next(3) if err != nil { return } sz = uint32(big.Uint16(p[1:])) return case mmap32: p, err = m.R.Next(5) if err != nil { return } sz = big.Uint32(p[1:]) return default: err = badPrefix(MapType, lead) return } } // ReadMapKey reads either a 'str' or 'bin' field from // the reader and returns the value as a []byte. It uses // scratch for storage if it is large enough. func (m *Reader) ReadMapKey(scratch []byte) ([]byte, error) { out, err := m.ReadStringAsBytes(scratch) if err != nil { if tperr, ok := err.(TypeError); ok && tperr.Encoded == BinType { key, err := m.ReadBytes(scratch) if uint64(len(key)) > m.GetMaxStringLength() { return nil, ErrLimitExceeded } return key, err } return nil, err } return out, nil } // ReadMapKeyPtr returns a []byte pointing to the contents // of a valid map key. The key cannot be empty, and it // must be shorter than the total buffer size of the // *Reader. Additionally, the returned slice is only // valid until the next *Reader method call. Users // should exercise extreme care when using this // method; writing into the returned slice may // corrupt future reads. func (m *Reader) ReadMapKeyPtr() ([]byte, error) { lead, err := m.R.PeekByte() if err != nil { return nil, err } var read int var p []byte if isfixstr(lead) { read = int(rfixstr(lead)) m.R.Skip(1) goto fill } switch lead { case mstr8, mbin8: p, err = m.R.Next(2) if err != nil { return nil, err } read = int(p[1]) case mstr16, mbin16: p, err = m.R.Next(3) if err != nil { return nil, err } read = int(big.Uint16(p[1:])) case mstr32, mbin32: p, err = m.R.Next(5) if err != nil { return nil, err } read = int(big.Uint32(p[1:])) default: return nil, badPrefix(StrType, lead) } fill: if read == 0 { return nil, ErrShortBytes } if uint64(read) > m.GetMaxStringLength() { return nil, ErrLimitExceeded } return m.R.Next(read) } // ReadArrayHeader reads the next object as an // array header and returns the size of the array // and the number of bytes read. func (m *Reader) ReadArrayHeader() (sz uint32, err error) { lead, err := m.R.PeekByte() if err != nil { return } if isfixarray(lead) { sz = uint32(rfixarray(lead)) _, err = m.R.Skip(1) return } var p []byte switch lead { case marray16: p, err = m.R.Next(3) if err != nil { return } sz = uint32(big.Uint16(p[1:])) return case marray32: p, err = m.R.Next(5) if err != nil { return } sz = big.Uint32(p[1:]) return default: err = badPrefix(ArrayType, lead) return } } // ReadNil reads a 'nil' MessagePack byte from the reader func (m *Reader) ReadNil() error { p, err := m.R.PeekByte() if err != nil { return err } if p != mnil { return badPrefix(NilType, p) } _, err = m.R.Skip(1) return err } // ReadFloat64 reads a float64 from the reader. // (If the value on the wire is encoded as a float32, // it will be up-cast to a float64.) func (m *Reader) ReadFloat64() (f float64, err error) { var p []byte p, err = m.R.Peek(9) if err != nil { // we'll allow a conversion from float32 to float64, // since we don't lose any precision if err == io.EOF && len(p) > 0 && p[0] == mfloat32 { ef, err := m.ReadFloat32() return float64(ef), err } return } if p[0] != mfloat64 { // see above if p[0] == mfloat32 { ef, err := m.ReadFloat32() return float64(ef), err } err = badPrefix(Float64Type, p[0]) return } f = math.Float64frombits(getMuint64(p)) _, err = m.R.Skip(9) return } // ReadFloat32 reads a float32 from the reader func (m *Reader) ReadFloat32() (f float32, err error) { var p []byte p, err = m.R.Peek(5) if err != nil { return } if p[0] != mfloat32 { err = badPrefix(Float32Type, p[0]) return } f = math.Float32frombits(getMuint32(p)) _, err = m.R.Skip(5) return } // ReadBool reads a bool from the reader func (m *Reader) ReadBool() (b bool, err error) { var p byte p, err = m.R.PeekByte() if err != nil { return } switch p { case mtrue: b = true case mfalse: default: err = badPrefix(BoolType, p) return } _, err = m.R.Skip(1) return } // ReadDuration reads a time.Duration from the reader func (m *Reader) ReadDuration() (d time.Duration, err error) { i, err := m.ReadInt64() return time.Duration(i), err } // ReadInt64 reads an int64 from the reader func (m *Reader) ReadInt64() (i int64, err error) { var p []byte lead, err := m.R.PeekByte() if err != nil { return } if isfixint(lead) { i = int64(rfixint(lead)) _, err = m.R.Skip(1) return } else if isnfixint(lead) { i = int64(rnfixint(lead)) _, err = m.R.Skip(1) return } switch lead { case mint8: p, err = m.R.Next(2) if err != nil { return } i = int64(getMint8(p)) return case muint8: p, err = m.R.Next(2) if err != nil { return } i = int64(getMuint8(p)) return case mint16: p, err = m.R.Next(3) if err != nil { return } i = int64(getMint16(p)) return case muint16: p, err = m.R.Next(3) if err != nil { return } i = int64(getMuint16(p)) return case mint32: p, err = m.R.Next(5) if err != nil { return } i = int64(getMint32(p)) return case muint32: p, err = m.R.Next(5) if err != nil { return } i = int64(getMuint32(p)) return case mint64: p, err = m.R.Next(9) if err != nil { return } i = getMint64(p) return case muint64: p, err = m.R.Next(9) if err != nil { return } u := getMuint64(p) if u > math.MaxInt64 { err = UintOverflow{Value: u, FailedBitsize: 64} return } i = int64(u) return default: err = badPrefix(IntType, lead) return } } // ReadInt32 reads an int32 from the reader func (m *Reader) ReadInt32() (i int32, err error) { var in int64 in, err = m.ReadInt64() if in > math.MaxInt32 || in < math.MinInt32 { err = IntOverflow{Value: in, FailedBitsize: 32} return } i = int32(in) return } // ReadInt16 reads an int16 from the reader func (m *Reader) ReadInt16() (i int16, err error) { var in int64 in, err = m.ReadInt64() if in > math.MaxInt16 || in < math.MinInt16 { err = IntOverflow{Value: in, FailedBitsize: 16} return } i = int16(in) return } // ReadInt8 reads an int8 from the reader func (m *Reader) ReadInt8() (i int8, err error) { var in int64 in, err = m.ReadInt64() if in > math.MaxInt8 || in < math.MinInt8 { err = IntOverflow{Value: in, FailedBitsize: 8} return } i = int8(in) return } // ReadInt reads an int from the reader func (m *Reader) ReadInt() (i int, err error) { if smallint { var in int32 in, err = m.ReadInt32() i = int(in) return } var in int64 in, err = m.ReadInt64() i = int(in) return } // ReadUint64 reads a uint64 from the reader func (m *Reader) ReadUint64() (u uint64, err error) { var p []byte lead, err := m.R.PeekByte() if err != nil { return } if isfixint(lead) { u = uint64(rfixint(lead)) _, err = m.R.Skip(1) return } switch lead { case mint8: p, err = m.R.Next(2) if err != nil { return } v := int64(getMint8(p)) if v < 0 { err = UintBelowZero{Value: v} return } u = uint64(v) return case muint8: p, err = m.R.Next(2) if err != nil { return } u = uint64(getMuint8(p)) return case mint16: p, err = m.R.Next(3) if err != nil { return } v := int64(getMint16(p)) if v < 0 { err = UintBelowZero{Value: v} return } u = uint64(v) return case muint16: p, err = m.R.Next(3) if err != nil { return } u = uint64(getMuint16(p)) return case mint32: p, err = m.R.Next(5) if err != nil { return } v := int64(getMint32(p)) if v < 0 { err = UintBelowZero{Value: v} return } u = uint64(v) return case muint32: p, err = m.R.Next(5) if err != nil { return } u = uint64(getMuint32(p)) return case mint64: p, err = m.R.Next(9) if err != nil { return } v := getMint64(p) if v < 0 { err = UintBelowZero{Value: v} return } u = uint64(v) return case muint64: p, err = m.R.Next(9) if err != nil { return } u = getMuint64(p) return default: if isnfixint(lead) { err = UintBelowZero{Value: int64(rnfixint(lead))} } else { err = badPrefix(UintType, lead) } return } } // ReadUint32 reads a uint32 from the reader func (m *Reader) ReadUint32() (u uint32, err error) { var in uint64 in, err = m.ReadUint64() if in > math.MaxUint32 { err = UintOverflow{Value: in, FailedBitsize: 32} return } u = uint32(in) return } // ReadUint16 reads a uint16 from the reader func (m *Reader) ReadUint16() (u uint16, err error) { var in uint64 in, err = m.ReadUint64() if in > math.MaxUint16 { err = UintOverflow{Value: in, FailedBitsize: 16} return } u = uint16(in) return } // ReadUint8 reads a uint8 from the reader func (m *Reader) ReadUint8() (u uint8, err error) { var in uint64 in, err = m.ReadUint64() if in > math.MaxUint8 { err = UintOverflow{Value: in, FailedBitsize: 8} return } u = uint8(in) return } // ReadUint reads a uint from the reader func (m *Reader) ReadUint() (u uint, err error) { if smallint { var un uint32 un, err = m.ReadUint32() u = uint(un) return } var un uint64 un, err = m.ReadUint64() u = uint(un) return } // ReadByte is analogous to ReadUint8. // // NOTE: this is *not* an implementation // of io.ByteReader. func (m *Reader) ReadByte() (b byte, err error) { var in uint64 in, err = m.ReadUint64() if in > math.MaxUint8 { err = UintOverflow{Value: in, FailedBitsize: 8} return } b = byte(in) return } // ReadBytes reads a MessagePack 'bin' object // from the reader and returns its value. It may // use 'scratch' for storage if it is non-nil. func (m *Reader) ReadBytes(scratch []byte) (b []byte, err error) { var p []byte var lead byte p, err = m.R.Peek(2) if err != nil { return } lead = p[0] var read int64 switch lead { case mbin8: read = int64(p[1]) m.R.Skip(2) case mbin16: p, err = m.R.Next(3) if err != nil { return } read = int64(big.Uint16(p[1:])) case mbin32: p, err = m.R.Next(5) if err != nil { return } read = int64(big.Uint32(p[1:])) default: err = badPrefix(BinType, lead) return } if int64(cap(scratch)) < read { if read > int64(m.GetMaxElements()) { err = ErrLimitExceeded return } b = make([]byte, read) } else { b = scratch[0:read] } _, err = m.R.ReadFull(b) return } // ReadBytesHeader reads the size header // of a MessagePack 'bin' object. The user // is responsible for dealing with the next // 'sz' bytes from the reader in an application-specific // way. func (m *Reader) ReadBytesHeader() (sz uint32, err error) { var p []byte lead, err := m.R.PeekByte() if err != nil { return } switch lead { case mbin8: p, err = m.R.Next(2) if err != nil { return } sz = uint32(p[1]) return case mbin16: p, err = m.R.Next(3) if err != nil { return } sz = uint32(big.Uint16(p[1:])) return case mbin32: p, err = m.R.Next(5) if err != nil { return } sz = big.Uint32(p[1:]) return default: err = badPrefix(BinType, lead) return } } // ReadExactBytes reads a MessagePack 'bin'-encoded // object off of the wire into the provided slice. An // ArrayError will be returned if the object is not // exactly the length of the input slice. func (m *Reader) ReadExactBytes(into []byte) error { p, err := m.R.Peek(2) if err != nil { return err } lead := p[0] var read int64 // bytes to read var skip int // prefix size to skip switch lead { case mbin8: read = int64(p[1]) skip = 2 case mbin16: p, err = m.R.Peek(3) if err != nil { return err } read = int64(big.Uint16(p[1:])) skip = 3 case mbin32: p, err = m.R.Peek(5) if err != nil { return err } read = int64(big.Uint32(p[1:])) skip = 5 default: return badPrefix(BinType, lead) } if read != int64(len(into)) { return ArrayError{Wanted: uint32(len(into)), Got: uint32(read)} } m.R.Skip(skip) _, err = m.R.ReadFull(into) return err } // ReadStringAsBytes reads a MessagePack 'str' (utf-8) string // and returns its value as bytes. It may use 'scratch' for storage // if it is non-nil. func (m *Reader) ReadStringAsBytes(scratch []byte) (b []byte, err error) { var p []byte lead, err := m.R.PeekByte() if err != nil { return } var read int64 if isfixstr(lead) { read = int64(rfixstr(lead)) m.R.Skip(1) goto fill } switch lead { case mstr8: p, err = m.R.Next(2) if err != nil { return } read = int64(p[1]) case mstr16: p, err = m.R.Next(3) if err != nil { return } read = int64(big.Uint16(p[1:])) case mstr32: p, err = m.R.Next(5) if err != nil { return } read = int64(big.Uint32(p[1:])) default: err = badPrefix(StrType, lead) return } fill: if uint64(read) > m.GetMaxStringLength() { err = ErrLimitExceeded return } if int64(cap(scratch)) < read { b = make([]byte, read) } else { b = scratch[0:read] } _, err = m.R.ReadFull(b) return } // ReadStringHeader reads a string header // off of the wire. The user is then responsible // for dealing with the next 'sz' bytes from // the reader in an application-specific manner. func (m *Reader) ReadStringHeader() (sz uint32, err error) { lead, err := m.R.PeekByte() if err != nil { return } if isfixstr(lead) { sz = uint32(rfixstr(lead)) m.R.Skip(1) return } var p []byte switch lead { case mstr8: p, err = m.R.Next(2) if err != nil { return } sz = uint32(p[1]) return case mstr16: p, err = m.R.Next(3) if err != nil { return } sz = uint32(big.Uint16(p[1:])) return case mstr32: p, err = m.R.Next(5) if err != nil { return } sz = big.Uint32(p[1:]) return default: err = badPrefix(StrType, lead) return } } // ReadString reads a utf-8 string from the reader func (m *Reader) ReadString() (s string, err error) { var read int64 lead, err := m.R.PeekByte() if err != nil { return } var p []byte if isfixstr(lead) { read = int64(rfixstr(lead)) m.R.Skip(1) goto fill } switch lead { case mstr8: p, err = m.R.Next(2) if err != nil { return } read = int64(p[1]) case mstr16: p, err = m.R.Next(3) if err != nil { return } read = int64(big.Uint16(p[1:])) case mstr32: p, err = m.R.Next(5) if err != nil { return } read = int64(big.Uint32(p[1:])) default: err = badPrefix(StrType, lead) return } fill: if read == 0 { s, err = "", nil return } if uint64(read) > m.GetMaxStringLength() { err = ErrLimitExceeded return } // reading into the memory // that will become the string // itself has vastly superior // worst-case performance, because // the reader buffer doesn't have // to be large enough to hold the string. // the idea here is to make it more // difficult for someone malicious // to cause the system to run out of // memory by sending very large strings. // // NOTE: this works because the argument // passed to (*fwd.Reader).ReadFull escapes // to the heap; its argument may, in turn, // be passed to the underlying reader, and // thus escape analysis *must* conclude that // 'out' escapes. out := make([]byte, read) _, err = m.R.ReadFull(out) if err != nil { return } s = UnsafeString(out) return } // ReadComplex64 reads a complex64 from the reader func (m *Reader) ReadComplex64() (f complex64, err error) { var p []byte p, err = m.R.Peek(10) if err != nil { return } if p[0] != mfixext8 { err = badPrefix(Complex64Type, p[0]) return } if int8(p[1]) != Complex64Extension { err = errExt(int8(p[1]), Complex64Extension) return } f = complex(math.Float32frombits(big.Uint32(p[2:])), math.Float32frombits(big.Uint32(p[6:]))) _, err = m.R.Skip(10) return } // ReadComplex128 reads a complex128 from the reader func (m *Reader) ReadComplex128() (f complex128, err error) { var p []byte p, err = m.R.Peek(18) if err != nil { return } if p[0] != mfixext16 { err = badPrefix(Complex128Type, p[0]) return } if int8(p[1]) != Complex128Extension { err = errExt(int8(p[1]), Complex128Extension) return } f = complex(math.Float64frombits(big.Uint64(p[2:])), math.Float64frombits(big.Uint64(p[10:]))) _, err = m.R.Skip(18) return } // ReadMapStrIntf reads a MessagePack map into a map[string]interface{}. // (You must pass a non-nil map into the function.) func (m *Reader) ReadMapStrIntf(mp map[string]any) (err error) { var sz uint32 sz, err = m.ReadMapHeader() if err != nil { return } for key := range mp { delete(mp, key) } if sz > m.GetMaxElements() { err = ErrLimitExceeded return } for i := uint32(0); i < sz; i++ { var key string var val any key, err = m.ReadString() if err != nil { return } val, err = m.ReadIntf() if err != nil { return } mp[key] = val } return } // ReadTimeUTC reads a time.Time object from the reader. // The returned time's location will be set to UTC. func (m *Reader) ReadTimeUTC() (t time.Time, err error) { t, err = m.ReadTime() return t.UTC(), err } // ReadTime reads a time.Time object from the reader. // The returned time's location will be set to time.Local. func (m *Reader) ReadTime() (t time.Time, err error) { offset, length, extType, err := m.peekExtensionHeader() if err != nil { return t, err } switch extType { case TimeExtension: var p []byte p, err = m.R.Peek(15) if err != nil { return } if p[0] != mext8 || p[1] != 12 { err = badPrefix(TimeType, p[0]) return } if int8(p[2]) != TimeExtension { err = errExt(int8(p[2]), TimeExtension) return } sec, nsec := getUnix(p[3:]) t = time.Unix(sec, int64(nsec)).Local() _, err = m.R.Skip(15) return case MsgTimeExtension: switch length { case 4, 8, 12: var tmp [12]byte _, err = m.R.Skip(offset) if err != nil { return } var n int n, err = m.R.Read(tmp[:length]) if err != nil { return } if n != length { err = ErrShortBytes return } b := tmp[:length] switch length { case 4: t = time.Unix(int64(binary.BigEndian.Uint32(b)), 0).Local() case 8: v := binary.BigEndian.Uint64(b) nanos := int64(v >> 34) if nanos > 999999999 { // In timestamp 64 and timestamp 96 formats, nanoseconds must not be larger than 999999999. err = InvalidTimestamp{Nanos: nanos} return } t = time.Unix(int64(v&(1<<34-1)), nanos).Local() case 12: nanos := int64(binary.BigEndian.Uint32(b)) if nanos > 999999999 { // In timestamp 64 and timestamp 96 formats, nanoseconds must not be larger than 999999999. err = InvalidTimestamp{Nanos: nanos} return } ux := int64(binary.BigEndian.Uint64(b[4:])) t = time.Unix(ux, nanos).Local() } default: err = InvalidTimestamp{FieldLength: length} } default: err = errExt(extType, TimeExtension) } return } // ReadJSONNumber reads an integer or a float value and return as json.Number func (m *Reader) ReadJSONNumber() (n json.Number, err error) { t, err := m.NextType() if err != nil { return } switch t { case IntType: v, err := m.ReadInt64() if err == nil { return json.Number(strconv.FormatInt(v, 10)), nil } return "", err case UintType: v, err := m.ReadUint64() if err == nil { return json.Number(strconv.FormatUint(v, 10)), nil } return "", err case Float32Type, Float64Type: v, err := m.ReadFloat64() if err == nil { return json.Number(strconv.FormatFloat(v, 'f', -1, 64)), nil } return "", err } return "", TypeError{Method: NumberType, Encoded: t} } // ReadIntf reads out the next object as a raw interface{}/any. // Arrays are decoded as []interface{}, and maps are decoded // as map[string]interface{}. Integers are decoded as int64 // and unsigned integers are decoded as uint64. func (m *Reader) ReadIntf() (i any, err error) { var t Type t, err = m.NextType() if err != nil { return } switch t { case BoolType: i, err = m.ReadBool() return case IntType: i, err = m.ReadInt64() return case UintType: i, err = m.ReadUint64() return case BinType: i, err = m.ReadBytes(nil) return case StrType: i, err = m.ReadString() return case Complex64Type: i, err = m.ReadComplex64() return case Complex128Type: i, err = m.ReadComplex128() return case TimeType: i, err = m.ReadTime() return case DurationType: i, err = m.ReadDuration() return case ExtensionType: var t int8 t, err = m.peekExtensionType() if err != nil { return } f, ok := extensionReg[t] if ok { e := f() err = m.ReadExtension(e) i = e return } var e RawExtension e.Type = t err = m.ReadExtension(&e) i = &e return case MapType: // This can call back here, so treat as recursive call. if done, err := m.recursiveCall(); err != nil { return nil, err } else { defer done() } mp := make(map[string]any) err = m.ReadMapStrIntf(mp) i = mp return case NilType: err = m.ReadNil() i = nil return case Float32Type: i, err = m.ReadFloat32() return case Float64Type: i, err = m.ReadFloat64() return case ArrayType: var sz uint32 sz, err = m.ReadArrayHeader() if err != nil { return } if done, err := m.recursiveCall(); err != nil { return nil, err } else { defer done() } if sz > m.GetMaxElements() { err = ErrLimitExceeded return } out := make([]any, int(sz)) for j := range out { out[j], err = m.ReadIntf() if err != nil { return } } i = out return default: return nil, fatal // unreachable } } // ReadBinaryUnmarshal reads a binary-encoded object from the reader and unmarshals it into dst. func (m *Reader) ReadBinaryUnmarshal(dst encoding.BinaryUnmarshaler) (err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("msgp: panic during UnmarshalBinary: %v", r) } }() tmp := bytesPool.Get().([]byte) defer bytesPool.Put(tmp) //nolint:staticcheck tmp, err = m.ReadBytes(tmp[:0]) if err != nil { return } return dst.UnmarshalBinary(tmp) } // ReadTextUnmarshal reads a text-encoded bin array from the reader and unmarshals it into dst. func (m *Reader) ReadTextUnmarshal(dst encoding.TextUnmarshaler) (err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("msgp: panic during UnmarshalText: %v", r) } }() tmp := bytesPool.Get().([]byte) defer bytesPool.Put(tmp) //nolint:staticcheck tmp, err = m.ReadBytes(tmp[:0]) if err != nil { return } return dst.UnmarshalText(tmp) } // ReadTextUnmarshalString reads a text-encoded string from the reader and unmarshals it into dst. func (m *Reader) ReadTextUnmarshalString(dst encoding.TextUnmarshaler) (err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("msgp: panic during UnmarshalText: %v", r) } }() tmp := bytesPool.Get().([]byte) defer bytesPool.Put(tmp) //nolint:staticcheck tmp, err = m.ReadStringAsBytes(tmp[:0]) if err != nil { return } return dst.UnmarshalText(tmp) } msgp-1.6.1/msgp/read_bytes.go000066400000000000000000000670041511433505400161130ustar00rootroot00000000000000package msgp import ( "bytes" "encoding/binary" "encoding/json" "math" "strconv" "time" ) var big = binary.BigEndian // NextType returns the type of the next // object in the slice. If the length // of the input is zero, it returns // [InvalidType]. func NextType(b []byte) Type { if len(b) == 0 { return InvalidType } spec := getBytespec(b[0]) t := spec.typ if t == ExtensionType && len(b) > int(spec.size) { var tp int8 if spec.extra == constsize { tp = int8(b[1]) } else { tp = int8(b[spec.size-1]) } switch tp { case TimeExtension, MsgTimeExtension: return TimeType case Complex128Extension: return Complex128Type case Complex64Extension: return Complex64Type default: return ExtensionType } } return t } // IsNil returns true if len(b)>0 and // the leading byte is a 'nil' MessagePack // byte; false otherwise func IsNil(b []byte) bool { if len(b) != 0 && b[0] == mnil { return true } return false } // Raw is raw MessagePack. // Raw allows you to read and write // data without interpreting its contents. type Raw []byte // MarshalMsg implements [Marshaler]. // It appends the raw contents of 'raw' // to the provided byte slice. If 'raw' // is 0 bytes, 'nil' will be appended instead. func (r Raw) MarshalMsg(b []byte) ([]byte, error) { i := len(r) if i == 0 { return AppendNil(b), nil } o, l := ensure(b, i) copy(o[l:], []byte(r)) return o, nil } // UnmarshalMsg implements [Unmarshaler]. // It sets the contents of *Raw to be the next // object in the provided byte slice. func (r *Raw) UnmarshalMsg(b []byte) ([]byte, error) { l := len(b) out, err := Skip(b) if err != nil { return b, err } rlen := l - len(out) if IsNil(b[:rlen]) { rlen = 0 } if cap(*r) < rlen { *r = make(Raw, rlen) } else { *r = (*r)[0:rlen] } copy(*r, b[:rlen]) return out, nil } // EncodeMsg implements [Encodable]. // It writes the raw bytes to the writer. // If r is empty, it writes 'nil' instead. func (r Raw) EncodeMsg(w *Writer) error { if len(r) == 0 { return w.WriteNil() } _, err := w.Write([]byte(r)) return err } // DecodeMsg implements [Decodable]. // It sets the value of *Raw to be the // next object on the wire. func (r *Raw) DecodeMsg(f *Reader) error { *r = (*r)[:0] err := appendNext(f, (*[]byte)(r)) if IsNil(*r) { *r = (*r)[:0] } return err } // Msgsize implements [Sizer]. func (r Raw) Msgsize() int { l := len(r) if l == 0 { return 1 // for 'nil' } return l } func appendNext(f *Reader, d *[]byte) error { amt, o, err := getNextSize(f.R) if err != nil { return err } var i int *d, i = ensure(*d, int(amt)) _, err = f.R.ReadFull((*d)[i:]) if err != nil { return err } for o > 0 { err = appendNext(f, d) if err != nil { return err } o-- } return nil } // MarshalJSON implements [json.Marshaler]. func (r *Raw) MarshalJSON() ([]byte, error) { var buf bytes.Buffer _, err := UnmarshalAsJSON(&buf, []byte(*r)) return buf.Bytes(), err } // ReadMapHeaderBytes reads a map header size // from 'b' and returns the remaining bytes. // // Possible errors: // // - [ErrShortBytes] (too few bytes) // - [TypeError] (not a map) func ReadMapHeaderBytes(b []byte) (sz uint32, o []byte, err error) { l := len(b) if l < 1 { err = ErrShortBytes return } lead := b[0] b = b[1:] if isfixmap(lead) { sz = uint32(rfixmap(lead)) o = b return } switch lead { case mmap16: if len(b) < 2 { err = ErrShortBytes return } sz = uint32(big.Uint16(b)) o = b[2:] return case mmap32: if len(b) < 4 { err = ErrShortBytes return } sz = big.Uint32(b) o = b[4:] return default: err = badPrefix(MapType, lead) return } } // ReadMapKeyZC attempts to read a map key // from 'b' and returns the key bytes and the remaining bytes // // Possible errors: // // - [ErrShortBytes] (too few bytes) // - [TypeError] (not a str or bin) func ReadMapKeyZC(b []byte) ([]byte, []byte, error) { o, x, err := ReadStringZC(b) if err != nil { if tperr, ok := err.(TypeError); ok && tperr.Encoded == BinType { return ReadBytesZC(b) } return nil, b, err } return o, x, nil } // ReadArrayHeaderBytes attempts to read // the array header size off of 'b' and return // the size and remaining bytes. // // Possible errors: // // - [ErrShortBytes] (too few bytes) // - [TypeError] (not an array) func ReadArrayHeaderBytes(b []byte) (sz uint32, o []byte, err error) { if len(b) < 1 { return 0, nil, ErrShortBytes } lead := b[0] b = b[1:] if isfixarray(lead) { sz = uint32(rfixarray(lead)) o = b return } switch lead { case marray16: if len(b) < 2 { err = ErrShortBytes return } sz = uint32(big.Uint16(b)) o = b[2:] return case marray32: if len(b) < 4 { err = ErrShortBytes return } sz = big.Uint32(b) o = b[4:] return default: err = badPrefix(ArrayType, lead) return } } // ReadBytesHeader reads the 'bin' header size // off of 'b' and returns the size and remaining bytes. // // Possible errors: // // - [ErrShortBytes] (too few bytes) // - [TypeError] (not a bin object) func ReadBytesHeader(b []byte) (sz uint32, o []byte, err error) { if len(b) < 1 { return 0, nil, ErrShortBytes } switch b[0] { case mbin8: if len(b) < 2 { err = ErrShortBytes return } sz = uint32(b[1]) o = b[2:] return case mbin16: if len(b) < 3 { err = ErrShortBytes return } sz = uint32(big.Uint16(b[1:])) o = b[3:] return case mbin32: if len(b) < 5 { err = ErrShortBytes return } sz = big.Uint32(b[1:]) o = b[5:] return default: err = badPrefix(BinType, b[0]) return } } // ReadNilBytes tries to read a "nil" byte // off of 'b' and return the remaining bytes. // // Possible errors: // // - [ErrShortBytes] (too few bytes) // - [TypeError] (not a 'nil') // - [InvalidPrefixError] func ReadNilBytes(b []byte) ([]byte, error) { if len(b) < 1 { return nil, ErrShortBytes } if b[0] != mnil { return b, badPrefix(NilType, b[0]) } return b[1:], nil } // ReadFloat64Bytes tries to read a float64 // from 'b' and return the value and the remaining bytes. // // Possible errors: // // - [ErrShortBytes] (too few bytes) // - [TypeError] (not a float64) func ReadFloat64Bytes(b []byte) (f float64, o []byte, err error) { if len(b) < 9 { if len(b) >= 5 && b[0] == mfloat32 { var tf float32 tf, o, err = ReadFloat32Bytes(b) f = float64(tf) return } err = ErrShortBytes return } if b[0] != mfloat64 { if b[0] == mfloat32 { var tf float32 tf, o, err = ReadFloat32Bytes(b) f = float64(tf) return } err = badPrefix(Float64Type, b[0]) return } f = math.Float64frombits(getMuint64(b)) o = b[9:] return } // ReadFloat32Bytes tries to read a float32 // from 'b' and return the value and the remaining bytes. // // Possible errors: // // - [ErrShortBytes] (too few bytes) // - [TypeError] (not a float32) func ReadFloat32Bytes(b []byte) (f float32, o []byte, err error) { if len(b) < 5 { err = ErrShortBytes return } if b[0] != mfloat32 { err = TypeError{Method: Float32Type, Encoded: getType(b[0])} return } f = math.Float32frombits(getMuint32(b)) o = b[5:] return } // ReadBoolBytes tries to read a bool // from 'b' and return the value and the remaining bytes. // // Possible errors: // // - [ErrShortBytes] (too few bytes) // - [TypeError] (not a bool) func ReadBoolBytes(b []byte) (bool, []byte, error) { if len(b) < 1 { return false, b, ErrShortBytes } switch b[0] { case mtrue: return true, b[1:], nil case mfalse: return false, b[1:], nil default: return false, b, badPrefix(BoolType, b[0]) } } // ReadDurationBytes tries to read a time.Duration // from 'b' and return the value and the remaining bytes. // // Possible errors: // // - [ErrShortBytes] (too few bytes) // - TypeError (not a int) func ReadDurationBytes(b []byte) (d time.Duration, o []byte, err error) { i, o, err := ReadInt64Bytes(b) return time.Duration(i), o, err } // ReadInt64Bytes tries to read an int64 // from 'b' and return the value and the remaining bytes. // // Possible errors: // // - [ErrShortBytes] (too few bytes) // - [TypeError] (not a int) func ReadInt64Bytes(b []byte) (i int64, o []byte, err error) { if len(b) < 1 { return 0, nil, ErrShortBytes } lead := b[0] b = b[1:] if isfixint(lead) { i = int64(rfixint(lead)) o = b return } if isnfixint(lead) { i = int64(rnfixint(lead)) o = b return } switch lead { case mint8: if len(b) < 1 { err = ErrShortBytes return } i = int64(int8(b[0])) o = b[1:] return case muint8: if len(b) < 1 { err = ErrShortBytes return } i = int64(b[0]) o = b[1:] return case mint16: if len(b) < 2 { err = ErrShortBytes return } i = int64(int16(big.Uint16(b))) o = b[2:] return case muint16: if len(b) < 2 { err = ErrShortBytes return } i = int64(big.Uint16(b)) o = b[2:] return case mint32: if len(b) < 4 { err = ErrShortBytes return } i = int64(int32(big.Uint32(b))) o = b[4:] return case muint32: if len(b) < 4 { err = ErrShortBytes return } i = int64(big.Uint32(b)) o = b[4:] return case mint64: if len(b) < 8 { err = ErrShortBytes return } i = int64(big.Uint64(b)) o = b[8:] return case muint64: if len(b) < 8 { err = ErrShortBytes return } u := big.Uint64(b) if u > math.MaxInt64 { err = UintOverflow{Value: u, FailedBitsize: 64} return } i = int64(u) o = b[8:] return default: err = badPrefix(IntType, lead) return } } // ReadInt32Bytes tries to read an int32 // from 'b' and return the value and the remaining bytes. // // Possible errors: // // - [ErrShortBytes] (too few bytes) // - [TypeError] (not a int) // - [IntOverflow] (value doesn't fit in int32) func ReadInt32Bytes(b []byte) (int32, []byte, error) { i, o, err := ReadInt64Bytes(b) if i > math.MaxInt32 || i < math.MinInt32 { return 0, o, IntOverflow{Value: i, FailedBitsize: 32} } return int32(i), o, err } // ReadInt16Bytes tries to read an int16 // from 'b' and return the value and the remaining bytes. // // Possible errors: // // - [ErrShortBytes] (too few bytes) // - [TypeError] (not a int) // - [IntOverflow] (value doesn't fit in int16) func ReadInt16Bytes(b []byte) (int16, []byte, error) { i, o, err := ReadInt64Bytes(b) if i > math.MaxInt16 || i < math.MinInt16 { return 0, o, IntOverflow{Value: i, FailedBitsize: 16} } return int16(i), o, err } // ReadInt8Bytes tries to read an int16 // from 'b' and return the value and the remaining bytes. // // Possible errors: // // - [ErrShortBytes] (too few bytes) // - [TypeError] (not a int) // - [IntOverflow] (value doesn't fit in int8) func ReadInt8Bytes(b []byte) (int8, []byte, error) { i, o, err := ReadInt64Bytes(b) if i > math.MaxInt8 || i < math.MinInt8 { return 0, o, IntOverflow{Value: i, FailedBitsize: 8} } return int8(i), o, err } // ReadIntBytes tries to read an int // from 'b' and return the value and the remaining bytes. // // Possible errors: // // - [ErrShortBytes] (too few bytes) // - [TypeError] (not a int) // - [IntOverflow] (value doesn't fit in int; 32-bit platforms only) func ReadIntBytes(b []byte) (int, []byte, error) { if smallint { i, b, err := ReadInt32Bytes(b) return int(i), b, err } i, b, err := ReadInt64Bytes(b) return int(i), b, err } // ReadUint64Bytes tries to read a uint64 // from 'b' and return the value and the remaining bytes. // // Possible errors: // // - [ErrShortBytes] (too few bytes) // - [TypeError] (not a uint) func ReadUint64Bytes(b []byte) (u uint64, o []byte, err error) { if len(b) < 1 { return 0, nil, ErrShortBytes } lead := b[0] b = b[1:] if isfixint(lead) { u = uint64(rfixint(lead)) o = b return } switch lead { case mint8: if len(b) < 1 { err = ErrShortBytes return } v := int64(int8(b[0])) if v < 0 { err = UintBelowZero{Value: v} return } u = uint64(v) o = b[1:] return case muint8: if len(b) < 1 { err = ErrShortBytes return } u = uint64(b[0]) o = b[1:] return case mint16: if len(b) < 2 { err = ErrShortBytes return } v := int64((int16(b[0]) << 8) | int16(b[1])) if v < 0 { err = UintBelowZero{Value: v} return } u = uint64(v) o = b[2:] return case muint16: if len(b) < 2 { err = ErrShortBytes return } u = uint64(big.Uint16(b)) o = b[2:] return case mint32: if len(b) < 4 { err = ErrShortBytes return } v := int64(int32(big.Uint32(b))) if v < 0 { err = UintBelowZero{Value: v} return } u = uint64(v) o = b[4:] return case muint32: if len(b) < 4 { err = ErrShortBytes return } u = uint64(big.Uint32(b)) o = b[4:] return case mint64: if len(b) < 8 { err = ErrShortBytes return } v := int64(big.Uint64(b)) if v < 0 { err = UintBelowZero{Value: v} return } u = uint64(v) o = b[8:] return case muint64: if len(b) < 8 { err = ErrShortBytes return } u = big.Uint64(b) o = b[8:] return default: if isnfixint(lead) { err = UintBelowZero{Value: int64(rnfixint(lead))} } else { err = badPrefix(UintType, lead) } return } } // ReadUint32Bytes tries to read a uint32 // from 'b' and return the value and the remaining bytes. // // Possible errors: // // - [ErrShortBytes] (too few bytes) // - [TypeError] (not a uint) // - [UintOverflow] (value too large for uint32) func ReadUint32Bytes(b []byte) (uint32, []byte, error) { v, o, err := ReadUint64Bytes(b) if v > math.MaxUint32 { return 0, nil, UintOverflow{Value: v, FailedBitsize: 32} } return uint32(v), o, err } // ReadUint16Bytes tries to read a uint16 // from 'b' and return the value and the remaining bytes. // // Possible errors: // // - [ErrShortBytes] (too few bytes) // - [TypeError] (not a uint) // - [UintOverflow] (value too large for uint16) func ReadUint16Bytes(b []byte) (uint16, []byte, error) { v, o, err := ReadUint64Bytes(b) if v > math.MaxUint16 { return 0, nil, UintOverflow{Value: v, FailedBitsize: 16} } return uint16(v), o, err } // ReadUint8Bytes tries to read a uint8 // from 'b' and return the value and the remaining bytes. // // Possible errors: // // - [ErrShortBytes] (too few bytes) // - [TypeError] (not a uint) // - [UintOverflow] (value too large for uint8) func ReadUint8Bytes(b []byte) (uint8, []byte, error) { v, o, err := ReadUint64Bytes(b) if v > math.MaxUint8 { return 0, nil, UintOverflow{Value: v, FailedBitsize: 8} } return uint8(v), o, err } // ReadUintBytes tries to read a uint // from 'b' and return the value and the remaining bytes. // // Possible errors: // // - [ErrShortBytes] (too few bytes) // - [TypeError] (not a uint) // - [UintOverflow] (value too large for uint; 32-bit platforms only) func ReadUintBytes(b []byte) (uint, []byte, error) { if smallint { u, b, err := ReadUint32Bytes(b) return uint(u), b, err } u, b, err := ReadUint64Bytes(b) return uint(u), b, err } // ReadByteBytes is analogous to ReadUint8Bytes func ReadByteBytes(b []byte) (byte, []byte, error) { return ReadUint8Bytes(b) } // ReadBytesBytes reads a 'bin' object // from 'b' and returns its vaue and // the remaining bytes in 'b'. // // Possible errors: // // - [ErrShortBytes] (too few bytes) // - [TypeError] (not a 'bin' object) func ReadBytesBytes(b []byte, scratch []byte) (v []byte, o []byte, err error) { return readBytesBytes(b, scratch, false) } func readBytesBytes(b []byte, scratch []byte, zc bool) (v []byte, o []byte, err error) { l := len(b) if l < 1 { return nil, nil, ErrShortBytes } lead := b[0] b = b[1:] var read int switch lead { case mbin8: if len(b) < 1 { err = ErrShortBytes return } read = int(b[0]) b = b[1:] case mbin16: if len(b) < 2 { err = ErrShortBytes return } read = int(big.Uint16(b)) b = b[2:] case mbin32: if len(b) < 4 { err = ErrShortBytes return } read = int(big.Uint32(b)) b = b[4:] default: err = badPrefix(BinType, lead) return } if len(b) < read { err = ErrShortBytes return } // zero-copy if zc { v = b[0:read] o = b[read:] return } if cap(scratch) >= read { v = scratch[0:read] } else { v = make([]byte, read) } o = b[copy(v, b):] return } // ReadBytesZC extracts the messagepack-encoded // binary field without copying. The returned []byte // points to the same memory as the input slice. // // Possible errors: // // - [ErrShortBytes] (b not long enough) // - [TypeError] (object not 'bin') func ReadBytesZC(b []byte) (v []byte, o []byte, err error) { return readBytesBytes(b, nil, true) } func ReadExactBytes(b []byte, into []byte) (o []byte, err error) { if len(b) < 1 { err = ErrShortBytes return } lead := b[0] var read uint32 b = b[1:] switch lead { case mbin8: if len(b) < 1 { err = ErrShortBytes return } read = uint32(b[0]) b = b[1:] case mbin16: if len(b) < 2 { err = ErrShortBytes return } read = uint32(big.Uint16(b)) b = b[2:] case mbin32: if len(b) < 4 { err = ErrShortBytes return } read = big.Uint32(b) b = b[4:] default: err = badPrefix(BinType, lead) return } if read != uint32(len(into)) { err = ArrayError{Wanted: uint32(len(into)), Got: read} return } o = b[copy(into, b):] return } // ReadStringZC reads a messagepack string field // without copying. The returned []byte points // to the same memory as the input slice. // // Possible errors: // // - [ErrShortBytes] (b not long enough) // - [TypeError] (object not 'str') func ReadStringZC(b []byte) (v []byte, o []byte, err error) { if len(b) < 1 { return nil, nil, ErrShortBytes } lead := b[0] var read int b = b[1:] if isfixstr(lead) { read = int(rfixstr(lead)) } else { switch lead { case mstr8: if len(b) < 1 { err = ErrShortBytes return } read = int(b[0]) b = b[1:] case mstr16: if len(b) < 2 { err = ErrShortBytes return } read = int(big.Uint16(b)) b = b[2:] case mstr32: if len(b) < 4 { err = ErrShortBytes return } read = int(big.Uint32(b)) b = b[4:] default: err = TypeError{Method: StrType, Encoded: getType(lead)} return } } if len(b) < read { err = ErrShortBytes return } v = b[0:read] o = b[read:] return } // ReadStringBytes reads a 'str' object // from 'b' and returns its value and the // remaining bytes in 'b'. // // Possible errors: // // - [ErrShortBytes] (b not long enough) // - [TypeError] (not 'str' type) // - [InvalidPrefixError] func ReadStringBytes(b []byte) (string, []byte, error) { v, o, err := ReadStringZC(b) return string(v), o, err } // ReadStringAsBytes reads a 'str' object // into a slice of bytes. 'v' is the value of // the 'str' object, which may reside in memory // pointed to by 'scratch.' 'o' is the remaining bytes // in 'b'. // // Possible errors: // // - [ErrShortBytes] (b not long enough) // - [TypeError] (not 'str' type) // - [InvalidPrefixError] (unknown type marker) func ReadStringAsBytes(b []byte, scratch []byte) (v []byte, o []byte, err error) { var tmp []byte tmp, o, err = ReadStringZC(b) v = append(scratch[:0], tmp...) return } // ReadComplex128Bytes reads a complex128 // extension object from 'b' and returns the // remaining bytes. // // Possible errors: // // - [ErrShortBytes] (not enough bytes in 'b') // - [TypeError] (object not a complex128) // - [InvalidPrefixError] // - [ExtensionTypeError] (object an extension of the correct size, but not a complex128) func ReadComplex128Bytes(b []byte) (c complex128, o []byte, err error) { if len(b) < 18 { err = ErrShortBytes return } if b[0] != mfixext16 { err = badPrefix(Complex128Type, b[0]) return } if int8(b[1]) != Complex128Extension { err = errExt(int8(b[1]), Complex128Extension) return } c = complex(math.Float64frombits(big.Uint64(b[2:])), math.Float64frombits(big.Uint64(b[10:]))) o = b[18:] return } // ReadComplex64Bytes reads a complex64 // extension object from 'b' and returns the // remaining bytes. // // Possible errors: // // - [ErrShortBytes] (not enough bytes in 'b') // - [TypeError] (object not a complex64) // - [ExtensionTypeError] (object an extension of the correct size, but not a complex64) func ReadComplex64Bytes(b []byte) (c complex64, o []byte, err error) { if len(b) < 10 { err = ErrShortBytes return } if b[0] != mfixext8 { err = badPrefix(Complex64Type, b[0]) return } if b[1] != Complex64Extension { err = errExt(int8(b[1]), Complex64Extension) return } c = complex(math.Float32frombits(big.Uint32(b[2:])), math.Float32frombits(big.Uint32(b[6:]))) o = b[10:] return } // ReadTimeUTCBytes does the same as ReadTimeBytes, but returns the value as UTC. func ReadTimeUTCBytes(b []byte) (t time.Time, o []byte, err error) { t, o, err = ReadTimeBytes(b) return t.UTC(), o, err } // ReadTimeBytes reads a time.Time // extension object from 'b' and returns the // remaining bytes. // Both the official and the format in this package will be read. // // Possible errors: // // - [ErrShortBytes] (not enough bytes in 'b') // - [TypeError] (object not a time extension 5 or -1) // - [ExtensionTypeError] (object an extension of the correct size, but not a time.Time) func ReadTimeBytes(b []byte) (t time.Time, o []byte, err error) { if len(b) < 6 { err = ErrShortBytes return } typ, o, b, err := readExt(b) if err != nil { return } switch typ { case TimeExtension: if len(b) != 12 { err = ErrShortBytes return } sec, nsec := getUnix(b) t = time.Unix(sec, int64(nsec)).Local() return case MsgTimeExtension: switch len(b) { case 4: t = time.Unix(int64(binary.BigEndian.Uint32(b)), 0).Local() return case 8: v := binary.BigEndian.Uint64(b) nanos := int64(v >> 34) if nanos > 999999999 { // In timestamp 64 and timestamp 96 formats, nanoseconds must not be larger than 999999999. err = InvalidTimestamp{Nanos: nanos} return } t = time.Unix(int64(v&(1<<34-1)), nanos).Local() return case 12: nanos := int64(binary.BigEndian.Uint32(b)) if nanos > 999999999 { // In timestamp 64 and timestamp 96 formats, nanoseconds must not be larger than 999999999. err = InvalidTimestamp{Nanos: nanos} return } ux := int64(binary.BigEndian.Uint64(b[4:])) t = time.Unix(ux, nanos).Local() return default: err = InvalidTimestamp{FieldLength: len(b)} return } default: err = errExt(typ, TimeExtension) return } } // ReadMapStrIntfBytes reads a map[string]interface{} // out of 'b' and returns the map and remaining bytes. // If 'old' is non-nil, the values will be read into that map. func ReadMapStrIntfBytes(b []byte, old map[string]any) (v map[string]any, o []byte, err error) { return readMapStrIntfBytesDepth(b, old, 0) } func readMapStrIntfBytesDepth(b []byte, old map[string]any, depth int) (v map[string]any, o []byte, err error) { if depth >= recursionLimit { err = ErrRecursion return } var sz uint32 o = b sz, o, err = ReadMapHeaderBytes(o) if err != nil { return } // Map key, min size is 2 bytes. Value min 1 byte. if int64(len(b)) < int64(sz)*3 { err = ErrShortBytes return } if old != nil { for key := range old { delete(old, key) } v = old } else { v = make(map[string]any, int(sz)) } for z := uint32(0); z < sz; z++ { if len(o) < 1 { err = ErrShortBytes return } var key []byte key, o, err = ReadMapKeyZC(o) if err != nil { return } var val any val, o, err = readIntfBytesDepth(o, depth) if err != nil { return } v[string(key)] = val } return } // ReadIntfBytes attempts to read // the next object out of 'b' as a raw interface{} and // return the remaining bytes. func ReadIntfBytes(b []byte) (i any, o []byte, err error) { return readIntfBytesDepth(b, 0) } func readIntfBytesDepth(b []byte, depth int) (i any, o []byte, err error) { if depth >= recursionLimit { err = ErrRecursion return } if len(b) < 1 { err = ErrShortBytes return } k := NextType(b) switch k { case MapType: i, o, err = readMapStrIntfBytesDepth(b, nil, depth+1) return case ArrayType: var sz uint32 sz, o, err = ReadArrayHeaderBytes(b) if err != nil { return } // Each element will at least be 1 byte. if uint32(len(o)) < sz { err = ErrShortBytes return } j := make([]any, int(sz)) i = j for d := range j { j[d], o, err = readIntfBytesDepth(o, depth+1) if err != nil { return } } return case Float32Type: i, o, err = ReadFloat32Bytes(b) return case Float64Type: i, o, err = ReadFloat64Bytes(b) return case IntType: i, o, err = ReadInt64Bytes(b) return case UintType: i, o, err = ReadUint64Bytes(b) return case BoolType: i, o, err = ReadBoolBytes(b) return case TimeType: i, o, err = ReadTimeBytes(b) return case Complex64Type: i, o, err = ReadComplex64Bytes(b) return case Complex128Type: i, o, err = ReadComplex128Bytes(b) return case ExtensionType: var t int8 t, err = peekExtension(b) if err != nil { return } // use a user-defined extension, // if it's been registered f, ok := extensionReg[t] if ok { e := f() o, err = ReadExtensionBytes(b, e) i = e return } // last resort is a raw extension e := RawExtension{} e.Type = t o, err = ReadExtensionBytes(b, &e) i = &e return case NilType: o, err = ReadNilBytes(b) return case BinType: i, o, err = ReadBytesBytes(b, nil) return case StrType: i, o, err = ReadStringBytes(b) return default: err = InvalidPrefixError(b[0]) return } } // Skip skips the next object in 'b' and // returns the remaining bytes. If the object // is a map or array, all of its elements // will be skipped. // // Possible errors: // // - [ErrShortBytes] (not enough bytes in b) // - [InvalidPrefixError] (bad encoding) // - [ErrRecursion] (too deeply nested data) func Skip(b []byte) ([]byte, error) { return skipDepth(b, 0) } func skipDepth(b []byte, depth int) ([]byte, error) { if depth >= recursionLimit { return b, ErrRecursion } sz, asz, err := getSize(b) if err != nil { return b, err } if uintptr(len(b)) < sz { return b, ErrShortBytes } b = b[sz:] for asz > 0 { b, err = skipDepth(b, depth+1) if err != nil { return b, err } asz-- } return b, nil } // returns (skip N bytes, skip M objects, error) func getSize(b []byte) (uintptr, uintptr, error) { l := len(b) if l == 0 { return 0, 0, ErrShortBytes } lead := b[0] spec := getBytespec(lead) // get type information size, mode := spec.size, spec.extra if size == 0 { return 0, 0, InvalidPrefixError(lead) } if mode >= 0 { // fixed composites return uintptr(size), uintptr(mode), nil } if l < int(size) { return 0, 0, ErrShortBytes } switch mode { case extra8: return uintptr(size) + uintptr(b[1]), 0, nil case extra16: return uintptr(size) + uintptr(big.Uint16(b[1:])), 0, nil case extra32: return uintptr(size) + uintptr(big.Uint32(b[1:])), 0, nil case map16v: return uintptr(size), 2 * uintptr(big.Uint16(b[1:])), nil case map32v: return uintptr(size), 2 * uintptr(big.Uint32(b[1:])), nil case array16v: return uintptr(size), uintptr(big.Uint16(b[1:])), nil case array32v: return uintptr(size), uintptr(big.Uint32(b[1:])), nil default: return 0, 0, fatal } } // ReadJSONNumberBytes tries to read a number // from 'b' and return the value and the remaining bytes. // // Possible errors: // // - [ErrShortBytes] (too few bytes) // - TypeError (not a number (int/float)) func ReadJSONNumberBytes(b []byte) (number json.Number, o []byte, err error) { if len(b) < 1 { return "", nil, ErrShortBytes } if i, o, err := ReadInt64Bytes(b); err == nil { return json.Number(strconv.FormatInt(i, 10)), o, nil } f, o, err := ReadFloat64Bytes(b) if err == nil { return json.Number(strconv.FormatFloat(f, 'f', -1, 64)), o, nil } return "", nil, TypeError{Method: NumberType, Encoded: getType(b[0])} } msgp-1.6.1/msgp/read_bytes_test.go000066400000000000000000000366521511433505400171570ustar00rootroot00000000000000package msgp import ( "bytes" "fmt" "log" "math" "reflect" "testing" "time" ) func TestReadMapHeaderBytes(t *testing.T) { var buf bytes.Buffer en := NewWriter(&buf) tests := []uint32{0, 1, 5, 49082} for i, v := range tests { buf.Reset() en.WriteMapHeader(v) en.Flush() out, left, err := ReadMapHeaderBytes(buf.Bytes()) if err != nil { t.Errorf("test case %d: %s", i, err) } if len(left) != 0 { t.Errorf("expected 0 bytes left; found %d", len(left)) } if out != v { t.Errorf("%d in; %d out", v, out) } } } func BenchmarkReadMapHeaderBytes(b *testing.B) { sizes := []uint32{1, 100, tuint16, tuint32} buf := make([]byte, 0, 5*len(sizes)) for _, sz := range sizes { buf = AppendMapHeader(buf, sz) } b.SetBytes(int64(len(buf) / len(sizes))) b.ReportAllocs() b.ResetTimer() o := buf for i := 0; i < b.N; i++ { _, buf, _ = ReadMapHeaderBytes(buf) if len(buf) == 0 { buf = o } } } func TestReadArrayHeaderBytes(t *testing.T) { var buf bytes.Buffer en := NewWriter(&buf) tests := []uint32{0, 1, 5, 49082} for i, v := range tests { buf.Reset() en.WriteArrayHeader(v) en.Flush() out, left, err := ReadArrayHeaderBytes(buf.Bytes()) if err != nil { t.Errorf("test case %d: %s", i, err) } if len(left) != 0 { t.Errorf("expected 0 bytes left; found %d", len(left)) } if out != v { t.Errorf("%d in; %d out", v, out) } } } func BenchmarkReadArrayHeaderBytes(b *testing.B) { sizes := []uint32{1, 100, tuint16, tuint32} buf := make([]byte, 0, 5*len(sizes)) for _, sz := range sizes { buf = AppendArrayHeader(buf, sz) } b.SetBytes(int64(len(buf) / len(sizes))) b.ReportAllocs() b.ResetTimer() o := buf for i := 0; i < b.N; i++ { _, buf, _ = ReadArrayHeaderBytes(buf) if len(buf) == 0 { buf = o } } } func TestReadBytesHeader(t *testing.T) { var buf bytes.Buffer en := NewWriter(&buf) tests := []uint32{0, 1, 5, 49082, 1 << 16, math.MaxUint32} for i, v := range tests { buf.Reset() en.WriteBytesHeader(v) en.Flush() out, left, err := ReadBytesHeader(buf.Bytes()) if err != nil { t.Errorf("test case %d: %s", i, err) } if len(left) != 0 { t.Errorf("expected 0 bytes left; found %d", len(left)) } if out != v { t.Errorf("%d in; %d out", v, out) } } } func BenchmarkTestReadBytesHeader(b *testing.B) { sizes := []uint32{1, 100, tuint16, tuint32} buf := make([]byte, 0, 5*len(sizes)) for _, sz := range sizes { buf = AppendBytesHeader(buf, sz) } b.SetBytes(int64(len(buf) / len(sizes))) b.ReportAllocs() b.ResetTimer() o := buf for i := 0; i < b.N; i++ { _, buf, _ = ReadBytesHeader(buf) if len(buf) == 0 { buf = o } } } func TestReadNilBytes(t *testing.T) { var buf bytes.Buffer en := NewWriter(&buf) en.WriteNil() en.Flush() left, err := ReadNilBytes(buf.Bytes()) if err != nil { t.Fatal(err) } if len(left) != 0 { t.Errorf("expected 0 bytes left; found %d", len(left)) } } func BenchmarkReadNilByte(b *testing.B) { buf := []byte{mnil} b.SetBytes(1) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { ReadNilBytes(buf) } } func TestReadFloat64Bytes(t *testing.T) { var buf bytes.Buffer en := NewWriter(&buf) en.WriteFloat64(3.14159) en.Flush() out, left, err := ReadFloat64Bytes(buf.Bytes()) if err != nil { t.Fatal(err) } if len(left) != 0 { t.Errorf("expected 0 bytes left; found %d", len(left)) } if out != 3.14159 { t.Errorf("%f in; %f out", 3.14159, out) } } func BenchmarkReadFloat64Bytes(b *testing.B) { f := float64(3.14159) buf := make([]byte, 0, 9) buf = AppendFloat64(buf, f) b.SetBytes(int64(len(buf))) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { ReadFloat64Bytes(buf) } } func TestReadFloat32Bytes(t *testing.T) { var buf bytes.Buffer en := NewWriter(&buf) en.WriteFloat32(3.1) en.Flush() out, left, err := ReadFloat32Bytes(buf.Bytes()) if err != nil { t.Fatal(err) } if len(left) != 0 { t.Errorf("expected 0 bytes left; found %d", len(left)) } if out != 3.1 { t.Errorf("%f in; %f out", 3.1, out) } } func BenchmarkReadFloat32Bytes(b *testing.B) { f := float32(3.14159) buf := make([]byte, 0, 5) buf = AppendFloat32(buf, f) b.SetBytes(int64(len(buf))) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { ReadFloat32Bytes(buf) } } func TestReadBoolBytes(t *testing.T) { var buf bytes.Buffer en := NewWriter(&buf) tests := []bool{true, false} for i, v := range tests { buf.Reset() en.WriteBool(v) en.Flush() out, left, err := ReadBoolBytes(buf.Bytes()) if err != nil { t.Errorf("test case %d: %s", i, err) } if len(left) != 0 { t.Errorf("expected 0 bytes left; found %d", len(left)) } if out != v { t.Errorf("%t in; %t out", v, out) } } } func BenchmarkReadBoolBytes(b *testing.B) { buf := []byte{mtrue, mfalse, mtrue, mfalse} b.SetBytes(1) b.ReportAllocs() b.ResetTimer() o := buf for i := 0; i < b.N; i++ { _, buf, _ = ReadBoolBytes(buf) if len(buf) == 0 { buf = o } } } func TestReadInt64Bytes(t *testing.T) { var buf bytes.Buffer wr := NewWriter(&buf) ints := []int64{ -100000, -5000, -5, 0, 8, 240, int64(tuint16), int64(tuint32), int64(tuint64), -5, -30, 0, 1, 127, 300, 40921, 34908219, } uints := []uint64{0, 8, 240, uint64(tuint16), uint64(tuint32), tuint64} all := make([]any, 0, len(ints)+len(uints)) for _, v := range ints { all = append(all, v) } for _, v := range uints { all = append(all, v) } for i, num := range all { buf.Reset() var err error var in int64 switch num := num.(type) { case int64: err = wr.WriteInt64(num) in = num case uint64: err = wr.WriteUint64(num) in = int64(num) default: panic(num) } if err != nil { t.Fatal(err) } err = wr.Flush() if err != nil { t.Fatal(err) } out, left, err := ReadInt64Bytes(buf.Bytes()) if out != in { t.Errorf("Test case %d: put %d in and got %d out", i, num, in) } if err != nil { t.Errorf("test case %d: %s", i, err) } if len(left) != 0 { t.Errorf("expected 0 bytes left; found %d", len(left)) } } } func TestReadUint64Bytes(t *testing.T) { var buf bytes.Buffer wr := NewWriter(&buf) vs := []any{ int64(0), int64(8), int64(240), int64(tuint16), int64(tuint32), int64(tuint64), uint64(0), uint64(8), uint64(240), uint64(tuint16), uint64(tuint32), tuint64, uint64(math.MaxUint64), } for i, num := range vs { buf.Reset() var err error var in uint64 switch num := num.(type) { case int64: err = wr.WriteInt64(num) in = uint64(num) case uint64: err = wr.WriteUint64(num) in = (num) default: panic(num) } if err != nil { t.Fatal(err) } err = wr.Flush() if err != nil { t.Fatal(err) } out, left, err := ReadUint64Bytes(buf.Bytes()) if out != in { t.Errorf("Test case %d: put %d in and got %d out", i, num, in) } if err != nil { t.Errorf("test case %d: %s", i, err) } if len(left) != 0 { t.Errorf("expected 0 bytes left; found %d", len(left)) } } } func TestReadIntBytesOverflows(t *testing.T) { var buf bytes.Buffer wr := NewWriter(&buf) i8, i16, i32, i64, u8, u16, u32, u64 := 1, 2, 3, 4, 5, 6, 7, 8 overflowErr := func(err error, failBits int) bool { bits := 0 switch err := err.(type) { case IntOverflow: bits = err.FailedBitsize case UintOverflow: bits = err.FailedBitsize } if bits == failBits { return true } log.Println("bits mismatch", bits, failBits) return false } belowZeroErr := func(err error, failBits int) bool { switch err.(type) { case UintBelowZero: return true } return false } vs := []struct { v any rdBits int failBits int errCheck func(err error, failBits int) bool }{ {uint64(math.MaxInt64), i32, 32, overflowErr}, {uint64(math.MaxInt64), i16, 16, overflowErr}, {uint64(math.MaxInt64), i8, 8, overflowErr}, {uint64(math.MaxUint64), i64, 64, overflowErr}, {uint64(math.MaxUint64), i32, 64, overflowErr}, {uint64(math.MaxUint64), i16, 64, overflowErr}, {uint64(math.MaxUint64), i8, 64, overflowErr}, {uint64(math.MaxUint32), i32, 32, overflowErr}, {uint64(math.MaxUint32), i16, 16, overflowErr}, {uint64(math.MaxUint32), i8, 8, overflowErr}, {int64(math.MinInt64), u64, 64, belowZeroErr}, {int64(math.MinInt64), u32, 64, belowZeroErr}, {int64(math.MinInt64), u16, 64, belowZeroErr}, {int64(math.MinInt64), u8, 64, belowZeroErr}, {int64(math.MinInt32), u64, 64, belowZeroErr}, {int64(math.MinInt32), u32, 32, belowZeroErr}, {int64(math.MinInt32), u16, 16, belowZeroErr}, {int64(math.MinInt32), u8, 8, belowZeroErr}, {int64(math.MinInt16), u64, 64, belowZeroErr}, {int64(math.MinInt16), u32, 32, belowZeroErr}, {int64(math.MinInt16), u16, 16, belowZeroErr}, {int64(math.MinInt16), u8, 8, belowZeroErr}, {int64(math.MinInt8), u64, 64, belowZeroErr}, {int64(math.MinInt8), u32, 32, belowZeroErr}, {int64(math.MinInt8), u16, 16, belowZeroErr}, {int64(math.MinInt8), u8, 8, belowZeroErr}, {-1, u64, 64, belowZeroErr}, {-1, u32, 32, belowZeroErr}, {-1, u16, 16, belowZeroErr}, {-1, u8, 8, belowZeroErr}, } for i, v := range vs { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { buf.Reset() switch num := v.v.(type) { case int: wr.WriteInt64(int64(num)) case int64: wr.WriteInt64(num) case uint64: wr.WriteUint64(num) default: panic(num) } wr.Flush() var err error switch v.rdBits { case i64: _, _, err = ReadInt64Bytes(buf.Bytes()) case i32: _, _, err = ReadInt32Bytes(buf.Bytes()) case i16: _, _, err = ReadInt16Bytes(buf.Bytes()) case i8: _, _, err = ReadInt8Bytes(buf.Bytes()) case u64: _, _, err = ReadUint64Bytes(buf.Bytes()) case u32: _, _, err = ReadUint32Bytes(buf.Bytes()) case u16: _, _, err = ReadUint16Bytes(buf.Bytes()) case u8: _, _, err = ReadUint8Bytes(buf.Bytes()) } if !v.errCheck(err, v.failBits) { t.Fatal(err, v.rdBits, v.failBits) } }) } } func TestReadBytesBytes(t *testing.T) { var buf bytes.Buffer en := NewWriter(&buf) tests := [][]byte{{}, []byte("some bytes"), []byte("some more bytes")} var scratch []byte for i, v := range tests { buf.Reset() en.WriteBytes(v) en.Flush() out, left, err := ReadBytesBytes(buf.Bytes(), scratch) if err != nil { t.Errorf("test case %d: %s", i, err) } if len(left) != 0 { t.Errorf("expected 0 bytes left; found %d", len(left)) } if !bytes.Equal(out, v) { t.Errorf("%q in; %q out", v, out) } } } func TestReadZCBytes(t *testing.T) { var buf bytes.Buffer en := NewWriter(&buf) tests := [][]byte{{}, []byte("some bytes"), []byte("some more bytes")} for i, v := range tests { buf.Reset() en.WriteBytes(v) en.Flush() out, left, err := ReadBytesZC(buf.Bytes()) if err != nil { t.Errorf("test case %d: %s", i, err) } if len(left) != 0 { t.Errorf("expected 0 bytes left; found %d", len(left)) } if !bytes.Equal(out, v) { t.Errorf("%q in; %q out", v, out) } } } func TestReadZCString(t *testing.T) { var buf bytes.Buffer en := NewWriter(&buf) tests := []string{"", "hello", "here's another string......"} for i, v := range tests { buf.Reset() en.WriteString(v) en.Flush() out, left, err := ReadStringZC(buf.Bytes()) if err != nil { t.Errorf("test case %d: %s", i, err) } if len(left) != 0 { t.Errorf("expected 0 bytes left; found %d", len(left)) } if string(out) != v { t.Errorf("%q in; %q out", v, out) } } } func TestReadStringBytes(t *testing.T) { var buf bytes.Buffer en := NewWriter(&buf) tests := []string{"", "hello", "here's another string......"} for i, v := range tests { buf.Reset() en.WriteString(v) en.Flush() out, left, err := ReadStringBytes(buf.Bytes()) if err != nil { t.Errorf("test case %d: %s", i, err) } if len(left) != 0 { t.Errorf("expected 0 bytes left; found %d", len(left)) } if out != v { t.Errorf("%q in; %q out", v, out) } } } func TestReadComplex128Bytes(t *testing.T) { var buf bytes.Buffer en := NewWriter(&buf) tests := []complex128{complex(0, 0), complex(12.8, 32.0)} for i, v := range tests { buf.Reset() en.WriteComplex128(v) en.Flush() out, left, err := ReadComplex128Bytes(buf.Bytes()) if err != nil { t.Errorf("test case %d: %s", i, err) } if len(left) != 0 { t.Errorf("expected 0 bytes left; found %d", len(left)) } if out != v { t.Errorf("%f in; %f out", v, out) } } } // both the 'str' and 'bin' types are acceptable map keys func TestReadMapKey(t *testing.T) { args := []string{ "a", "ab", "qwertyuiop", } var buf bytes.Buffer en := NewWriter(&buf) for i := range args { en.WriteString(args[i]) en.WriteBytes([]byte(args[i])) } en.Flush() b := buf.Bytes() for i := range args { var s0, s1 []byte var err error s0, b, err = ReadMapKeyZC(b) if err != nil { t.Fatalf("couldn't read string as map key: %q", err) } s1, b, err = ReadMapKeyZC(b) if err != nil { t.Fatalf("couldn't read bytes as map key: %q", err) } if !bytes.Equal(s0, s1) { t.Fatalf("%q != %q", s0, s1) } if string(s0) != args[i] { t.Fatalf("%q != %q", s0, args[i]) } } } func TestReadComplex64Bytes(t *testing.T) { var buf bytes.Buffer en := NewWriter(&buf) tests := []complex64{complex(0, 0), complex(12.8, 32.0)} for i, v := range tests { buf.Reset() en.WriteComplex64(v) en.Flush() out, left, err := ReadComplex64Bytes(buf.Bytes()) if err != nil { t.Errorf("test case %d: %s", i, err) } if len(left) != 0 { t.Errorf("expected 0 bytes left; found %d", len(left)) } if out != v { t.Errorf("%f in; %f out", v, out) } } } func TestReadTimeBytes(t *testing.T) { var buf bytes.Buffer en := NewWriter(&buf) now := time.Now() en.WriteTime(now) en.Flush() out, left, err := ReadTimeBytes(buf.Bytes()) if err != nil { t.Fatal(err) } if len(left) != 0 { t.Errorf("expected 0 bytes left; found %d", len(left)) } if !now.Equal(out) { t.Errorf("%s in; %s out", now, out) } } func BenchmarkReadTimeBytes(b *testing.B) { data := AppendTime(nil, time.Now()) b.SetBytes(15) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { ReadTimeBytes(data) } } func TestReadIntfBytes(t *testing.T) { var buf bytes.Buffer en := NewWriter(&buf) tests := make([]any, 0, 10) tests = append(tests, float64(3.5)) tests = append(tests, int64(-49082)) tests = append(tests, uint64(34908)) tests = append(tests, string("hello!")) tests = append(tests, []byte("blah.")) tests = append(tests, map[string]any{ "key_one": 3.5, "key_two": "hi.", }) for i, v := range tests { buf.Reset() if err := en.WriteIntf(v); err != nil { t.Fatal(err) } en.Flush() out, left, err := ReadIntfBytes(buf.Bytes()) if err != nil { t.Errorf("test case %d: %s", i, err) } if len(left) != 0 { t.Errorf("expected 0 bytes left; found %d", len(left)) } if !reflect.DeepEqual(v, out) { t.Errorf("ReadIntf(): %v in; %v out", v, out) } } } func BenchmarkSkipBytes(b *testing.B) { var buf bytes.Buffer en := NewWriter(&buf) en.WriteMapHeader(6) en.WriteString("thing_one") en.WriteString("value_one") en.WriteString("thing_two") en.WriteFloat64(3.14159) en.WriteString("some_bytes") en.WriteBytes([]byte("nkl4321rqw908vxzpojnlk2314rqew098-s09123rdscasd")) en.WriteString("the_time") en.WriteTime(time.Now()) en.WriteString("what?") en.WriteBool(true) en.WriteString("ext") en.WriteExtension(&RawExtension{Type: 55, Data: []byte("raw data!!!")}) en.Flush() bts := buf.Bytes() b.SetBytes(int64(len(bts))) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := Skip(bts) if err != nil { b.Fatal(err) } } } msgp-1.6.1/msgp/read_test.go000066400000000000000000000532041511433505400157410ustar00rootroot00000000000000package msgp import ( "bytes" "errors" "fmt" "io" "math" "math/rand" "reflect" "testing" "time" ) func TestSanity(t *testing.T) { if !isfixint(0) { t.Fatal("WUT.") } } func TestReadIntf(t *testing.T) { // NOTE: if you include cases // with, say, int32s, the test // will fail, b/c integers are // always read out as int64, and // unsigned integers as uint64 testCases := []any{ float64(128.032), float32(9082.092), int64(-40), uint64(9082981), time.Now(), 48*time.Hour + 3*time.Minute + 2*time.Second + 3*time.Nanosecond, "hello!", []byte("hello!"), map[string]any{ "thing-1": "thing-1-value", "thing-2": int64(800), "thing-3": []byte("some inner bytes..."), "thing-4": false, }, } var buf bytes.Buffer var v any dec := NewReader(&buf) enc := NewWriter(&buf) for i, ts := range testCases { buf.Reset() err := enc.WriteIntf(ts) if err != nil { t.Errorf("Test case %d: %s", i, err) continue } err = enc.Flush() if err != nil { t.Fatal(err) } v, err = dec.ReadIntf() if err != nil { t.Errorf("Test case: %d: %s", i, err) } /* for time, use time.Equal instead of reflect.DeepEqual */ if tm, ok := v.(time.Time); ok { if !tm.Equal(v.(time.Time)) { t.Errorf("%v != %v", ts, v) } } else if intd, ok := ts.(time.Duration); ok { /* for time.Duration, cast before comparing */ outtd := time.Duration(v.(int64)) if intd != outtd { t.Errorf("%v in; %v out", intd, outtd) } } else if !reflect.DeepEqual(v, ts) { t.Errorf("%v in; %v out", ts, v) } } } func TestReadIntfRecursion(t *testing.T) { var buf bytes.Buffer dec := NewReader(&buf) enc := NewWriter(&buf) // Test array recursion... for range recursionLimit * 2 { enc.WriteArrayHeader(1) } enc.Flush() b := buf.Bytes() _, err := dec.ReadIntf() if !errors.Is(err, ErrRecursion) { t.Errorf("unexpected Reader error: %v", err) } _, _, err = ReadIntfBytes(b) if !errors.Is(err, ErrRecursion) { t.Errorf("unexpected Bytes error: %v", err) } // Test JSON dec.Reset(bytes.NewReader(b)) _, err = dec.WriteToJSON(io.Discard) if !errors.Is(err, ErrRecursion) { t.Errorf("unexpected Reader error: %v", err) } _, err = UnmarshalAsJSON(io.Discard, b) if !errors.Is(err, ErrRecursion) { t.Errorf("unexpected Bytes error: %v", err) } _, err = CopyToJSON(io.Discard, bytes.NewReader(b)) if !errors.Is(err, ErrRecursion) { t.Errorf("unexpected Bytes error: %v", err) } // Test map recursion... buf.Reset() for range recursionLimit * 2 { enc.WriteMapHeader(1) // Write a key... enc.WriteString("a") } enc.Flush() b = buf.Bytes() dec.Reset(bytes.NewReader(b)) _, err = dec.ReadIntf() if !errors.Is(err, ErrRecursion) { t.Errorf("unexpected Reader error: %v", err) } _, _, err = ReadIntfBytes(b) if !errors.Is(err, ErrRecursion) { t.Errorf("unexpected Bytes error: %v", err) } // Test ReadMapStrInt using same input dec.Reset(bytes.NewReader(b)) err = dec.ReadMapStrIntf(map[string]any{}) if !errors.Is(err, ErrRecursion) { t.Errorf("unexpected Reader error: %v", err) } _, _, err = ReadMapStrIntfBytes(b, map[string]any{}) if !errors.Is(err, ErrRecursion) { t.Errorf("unexpected Bytes error: %v", err) } // Test CopyNext dec.Reset(bytes.NewReader(b)) _, err = dec.CopyNext(io.Discard) if !errors.Is(err, ErrRecursion) { t.Errorf("unexpected Reader error: %v", err) } // Test JSON dec.Reset(bytes.NewReader(b)) _, err = dec.WriteToJSON(io.Discard) if !errors.Is(err, ErrRecursion) { t.Errorf("unexpected Reader error: %v", err) } _, err = UnmarshalAsJSON(io.Discard, b) if !errors.Is(err, ErrRecursion) { t.Errorf("unexpected Bytes error: %v", err) } _, err = CopyToJSON(io.Discard, bytes.NewReader(b)) if !errors.Is(err, ErrRecursion) { t.Errorf("unexpected Bytes error: %v", err) } } func TestSkipRecursion(t *testing.T) { var buf bytes.Buffer dec := NewReader(&buf) enc := NewWriter(&buf) // Test array recursion... for range recursionLimit * 2 { enc.WriteArrayHeader(1) } enc.Flush() b := buf.Bytes() err := dec.Skip() if !errors.Is(err, ErrRecursion) { t.Errorf("unexpected Reader error: %v", err) } _, err = Skip(b) if !errors.Is(err, ErrRecursion) { t.Errorf("unexpected Bytes error: %v", err) } buf.Reset() // Test map recursion... for range recursionLimit * 2 { enc.WriteMapHeader(1) // Write a key... enc.WriteString("a") } enc.Flush() b = buf.Bytes() err = dec.Skip() if !errors.Is(err, ErrRecursion) { t.Errorf("unexpected Reader error: %v", err) } _, err = Skip(b) if !errors.Is(err, ErrRecursion) { t.Errorf("unexpected Bytes error: %v", err) } } func TestReadMapHeader(t *testing.T) { tests := []struct { Sz uint32 }{ {0}, {1}, {tuint16}, {tuint32}, } var buf bytes.Buffer var sz uint32 var err error wr := NewWriter(&buf) rd := NewReader(&buf) for i, test := range tests { buf.Reset() err = wr.WriteMapHeader(test.Sz) if err != nil { t.Fatal(err) } err = wr.Flush() if err != nil { t.Fatal(err) } sz, err = rd.ReadMapHeader() if err != nil { t.Errorf("Test case %d: got error %s", i, err) } if sz != test.Sz { t.Errorf("Test case %d: wrote size %d; got size %d", i, test.Sz, sz) } } } func BenchmarkReadMapHeader(b *testing.B) { sizes := []uint32{0, 1, tuint16, tuint32} data := make([]byte, 0, len(sizes)*5) for _, d := range sizes { data = AppendMapHeader(data, d) } rd := NewReader(NewEndlessReader(data, b)) b.SetBytes(int64(len(data) / len(sizes))) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { rd.ReadMapHeader() } } func TestReadArrayHeader(t *testing.T) { tests := []struct { Sz uint32 }{ {0}, {1}, {tuint16}, {tuint32}, } var buf bytes.Buffer var sz uint32 var err error wr := NewWriter(&buf) rd := NewReader(&buf) for i, test := range tests { buf.Reset() err = wr.WriteArrayHeader(test.Sz) if err != nil { t.Fatal(err) } err = wr.Flush() if err != nil { t.Fatal(err) } sz, err = rd.ReadArrayHeader() if err != nil { t.Errorf("Test case %d: got error %s", i, err) } if sz != test.Sz { t.Errorf("Test case %d: wrote size %d; got size %d", i, test.Sz, sz) } } } func BenchmarkReadArrayHeader(b *testing.B) { sizes := []uint32{0, 1, tuint16, tuint32} data := make([]byte, 0, len(sizes)*5) for _, d := range sizes { data = AppendArrayHeader(data, d) } rd := NewReader(NewEndlessReader(data, b)) b.ReportAllocs() b.SetBytes(int64(len(data) / len(sizes))) b.ResetTimer() for i := 0; i < b.N; i++ { rd.ReadArrayHeader() } } func TestReadNil(t *testing.T) { var buf bytes.Buffer wr := NewWriter(&buf) rd := NewReader(&buf) wr.WriteNil() wr.Flush() err := rd.ReadNil() if err != nil { t.Fatal(err) } } func BenchmarkReadNil(b *testing.B) { data := AppendNil(nil) rd := NewReader(NewEndlessReader(data, b)) b.ReportAllocs() b.SetBytes(1) b.ResetTimer() for i := 0; i < b.N; i++ { err := rd.ReadNil() if err != nil { b.Fatal(err) } } } func TestReadFloat64(t *testing.T) { var buf bytes.Buffer wr := NewWriter(&buf) rd := NewReader(&buf) for range 100 { buf.Reset() flt := (rand.Float64() - 0.5) * math.MaxFloat64 err := wr.WriteFloat64(flt) if err != nil { t.Fatal(err) } err = wr.Flush() if err != nil { t.Fatal(err) } out, err := rd.ReadFloat64() if err != nil { t.Errorf("Error reading %f: %s", flt, err) continue } if out != flt { t.Errorf("Put in %f but got out %f", flt, out) } } } func BenchmarkReadFloat64(b *testing.B) { fs := []float64{rand.Float64(), rand.Float64(), rand.Float64(), rand.Float64()} data := make([]byte, 0, 9*len(fs)) for _, f := range fs { data = AppendFloat64(data, f) } rd := NewReader(NewEndlessReader(data, b)) b.SetBytes(9) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := rd.ReadFloat64() if err != nil { b.Fatal(err) } } } func TestReadFloat32(t *testing.T) { var buf bytes.Buffer wr := NewWriter(&buf) rd := NewReader(&buf) for range 10000 { buf.Reset() flt := (rand.Float32() - 0.5) * math.MaxFloat32 err := wr.WriteFloat32(flt) if err != nil { t.Fatal(err) } err = wr.Flush() if err != nil { t.Fatal(err) } out, err := rd.ReadFloat32() if err != nil { t.Errorf("Error reading %f: %s", flt, err) continue } if out != flt { t.Errorf("Put in %f but got out %f", flt, out) } } } func BenchmarkReadFloat32(b *testing.B) { fs := []float32{rand.Float32(), rand.Float32(), rand.Float32(), rand.Float32()} data := make([]byte, 0, 5*len(fs)) for _, f := range fs { data = AppendFloat32(data, f) } rd := NewReader(NewEndlessReader(data, b)) b.SetBytes(5) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := rd.ReadFloat32() if err != nil { b.Fatal(err) } } } func TestReadInt64(t *testing.T) { var buf bytes.Buffer wr := NewWriter(&buf) rd := NewReader(&buf) ints := []int64{-100000, -5000, -5, 0, 8, 240, int64(tuint16), int64(tuint32), int64(tuint64)} uints := []uint64{0, 8, 240, uint64(tuint16), uint64(tuint32), tuint64} all := make([]any, 0, len(ints)+len(uints)) for _, v := range ints { all = append(all, v) } for _, v := range uints { all = append(all, v) } for i, num := range all { buf.Reset() var err error var in int64 switch num := num.(type) { case int64: err = wr.WriteInt64(num) in = num case uint64: err = wr.WriteUint64(num) in = int64(num) default: panic(num) } if err != nil { t.Fatal(err) } err = wr.Flush() if err != nil { t.Fatal(err) } out, err := rd.ReadInt64() if err != nil { t.Fatal(err) } if out != in { t.Errorf("Test case %d: put %d in and got %d out", i, num, in) } } } func TestReadIntOverflows(t *testing.T) { var buf bytes.Buffer wr := NewWriter(&buf) rd := NewReader(&buf) i8, i16, i32, i64, u8, u16, u32, u64 := 1, 2, 3, 4, 5, 6, 7, 8 overflowErr := func(err error, failBits int) bool { bits := 0 switch err := err.(type) { case IntOverflow: bits = err.FailedBitsize case UintOverflow: bits = err.FailedBitsize } return bits == failBits } belowZeroErr := func(err error, failBits int) bool { switch err.(type) { case UintBelowZero: return true } return false } vs := []struct { v any rdBits int failBits int errCheck func(err error, failBits int) bool }{ {uint64(math.MaxInt64), i32, 32, overflowErr}, {uint64(math.MaxInt64), i16, 16, overflowErr}, {uint64(math.MaxInt64), i8, 8, overflowErr}, {uint64(math.MaxUint64), i64, 64, overflowErr}, {uint64(math.MaxUint64), i32, 64, overflowErr}, {uint64(math.MaxUint64), i16, 64, overflowErr}, {uint64(math.MaxUint64), i8, 64, overflowErr}, {uint64(math.MaxUint32), i32, 32, overflowErr}, {uint64(math.MaxUint32), i16, 16, overflowErr}, {uint64(math.MaxUint32), i8, 8, overflowErr}, {int64(math.MinInt64), u64, 64, belowZeroErr}, {int64(math.MinInt64), u32, 64, belowZeroErr}, {int64(math.MinInt64), u16, 64, belowZeroErr}, {int64(math.MinInt64), u8, 64, belowZeroErr}, {int64(math.MinInt32), u64, 64, belowZeroErr}, {int64(math.MinInt32), u32, 32, belowZeroErr}, {int64(math.MinInt32), u16, 16, belowZeroErr}, {int64(math.MinInt32), u8, 8, belowZeroErr}, {int64(math.MinInt16), u64, 64, belowZeroErr}, {int64(math.MinInt16), u32, 32, belowZeroErr}, {int64(math.MinInt16), u16, 16, belowZeroErr}, {int64(math.MinInt16), u8, 8, belowZeroErr}, {int64(math.MinInt8), u64, 64, belowZeroErr}, {int64(math.MinInt8), u32, 32, belowZeroErr}, {int64(math.MinInt8), u16, 16, belowZeroErr}, {int64(math.MinInt8), u8, 8, belowZeroErr}, {-1, u64, 64, belowZeroErr}, {-1, u32, 32, belowZeroErr}, {-1, u16, 16, belowZeroErr}, {-1, u8, 8, belowZeroErr}, } for i, v := range vs { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { switch num := v.v.(type) { case int: wr.WriteInt64(int64(num)) case int64: wr.WriteInt64(num) case uint64: wr.WriteUint64(num) default: panic(num) } wr.Flush() var err error switch v.rdBits { case i64: _, err = rd.ReadInt64() case i32: _, err = rd.ReadInt32() case i16: _, err = rd.ReadInt16() case i8: _, err = rd.ReadInt8() case u64: _, err = rd.ReadUint64() case u32: _, err = rd.ReadUint32() case u16: _, err = rd.ReadUint16() case u8: _, err = rd.ReadUint8() } if !v.errCheck(err, v.failBits) { t.Fatal(err) } }) } } func BenchmarkReadInt64(b *testing.B) { is := []int64{0, 1, 65000, rand.Int63()} data := make([]byte, 0, 9*len(is)) for _, n := range is { data = AppendInt64(data, n) } rd := NewReader(NewEndlessReader(data, b)) b.SetBytes(int64(len(data) / len(is))) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := rd.ReadInt64() if err != nil { b.Fatal(err) } } } func BenchmarkReadUintWithInt64(b *testing.B) { us := []uint64{0, 1, 10000, uint64(rand.Uint32() * 4)} data := make([]byte, 0, 9*len(us)) for _, n := range us { data = AppendUint64(data, n) } rd := NewReader(NewEndlessReader(data, b)) b.SetBytes(int64(len(data) / len(us))) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := rd.ReadInt64() if err != nil { b.Fatal(err) } } } func TestReadUint64(t *testing.T) { var buf bytes.Buffer wr := NewWriter(&buf) rd := NewReader(&buf) ints := []uint64{0, 8, 240, uint64(tuint16), uint64(tuint32), tuint64} for i, num := range ints { buf.Reset() err := wr.WriteUint64(num) if err != nil { t.Fatal(err) } err = wr.Flush() if err != nil { t.Fatal(err) } out, err := rd.ReadUint64() if err != nil { t.Fatal(err) } if out != num { t.Errorf("Test case %d: put %d in and got %d out", i, num, out) } } } func BenchmarkReadUint64(b *testing.B) { us := []uint64{0, 1, 10000, uint64(rand.Uint32() * 4)} data := make([]byte, 0, 9*len(us)) for _, n := range us { data = AppendUint64(data, n) } rd := NewReader(NewEndlessReader(data, b)) b.SetBytes(int64(len(data) / len(us))) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := rd.ReadUint64() if err != nil { b.Fatal(err) } } } func BenchmarkReadIntWithUint64(b *testing.B) { is := []int64{0, 1, 65000, rand.Int63()} data := make([]byte, 0, 9*len(is)) for _, n := range is { data = AppendInt64(data, n) } rd := NewReader(NewEndlessReader(data, b)) b.SetBytes(int64(len(data) / len(is))) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := rd.ReadUint64() if err != nil { b.Fatal(err) } } } func TestReadBytes(t *testing.T) { var buf bytes.Buffer wr := NewWriter(&buf) rd := NewReader(&buf) sizes := []int{0, 1, 225, int(tuint32)} var scratch []byte for i, size := range sizes { buf.Reset() bts := RandBytes(size) err := wr.WriteBytes(bts) if err != nil { t.Fatal(err) } err = wr.Flush() if err != nil { t.Fatal(err) } out, err := rd.ReadBytes(scratch) if err != nil { t.Errorf("test case %d: %s", i, err) continue } if !bytes.Equal(bts, out) { t.Errorf("test case %d: Bytes not equal.", i) } } } func benchBytes(size uint32, b *testing.B) { data := make([]byte, 0, size+5) data = AppendBytes(data, RandBytes(int(size))) rd := NewReader(NewEndlessReader(data, b)) b.SetBytes(int64(len(data))) b.ReportAllocs() b.ResetTimer() var scratch []byte var err error for i := 0; i < b.N; i++ { scratch, err = rd.ReadBytes(scratch) if err != nil { b.Fatal(err) } } } func BenchmarkRead16Bytes(b *testing.B) { benchBytes(16, b) } func BenchmarkRead256Bytes(b *testing.B) { benchBytes(256, b) } // This particular case creates // an object larger than the default // read buffer size, so it's a decent // indicator of worst-case performance. func BenchmarkRead2048Bytes(b *testing.B) { benchBytes(2048, b) } func TestReadString(t *testing.T) { var buf bytes.Buffer wr := NewWriter(&buf) rd := NewReader(&buf) sizes := []int{0, 1, 225, int(math.MaxUint16 + 5)} for i, size := range sizes { buf.Reset() in := string(RandBytes(size)) err := wr.WriteString(in) if err != nil { t.Fatal(err) } err = wr.Flush() if err != nil { t.Fatal(err) } out, err := rd.ReadString() if err != nil { t.Errorf("test case %d: %s", i, err) } if out != in { t.Errorf("test case %d: strings not equal.", i) t.Errorf("string (len = %d) in; string (len = %d) out", size, len(out)) } } } func benchString(size uint32, b *testing.B) { str := string(RandBytes(int(size))) data := make([]byte, 0, len(str)+5) data = AppendString(data, str) rd := NewReader(NewEndlessReader(data, b)) b.SetBytes(int64(len(data))) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := rd.ReadString() if err != nil { b.Fatal(err) } } } func benchStringAsBytes(size uint32, b *testing.B) { str := string(RandBytes(int(size))) data := make([]byte, 0, len(str)+5) data = AppendString(data, str) rd := NewReader(NewEndlessReader(data, b)) b.SetBytes(int64(len(data))) b.ReportAllocs() b.ResetTimer() var scratch []byte var err error for i := 0; i < b.N; i++ { scratch, err = rd.ReadStringAsBytes(scratch) if err != nil { b.Fatal(err) } } } func BenchmarkRead16StringAsBytes(b *testing.B) { benchStringAsBytes(16, b) } func BenchmarkRead256StringAsBytes(b *testing.B) { benchStringAsBytes(256, b) } func BenchmarkRead16String(b *testing.B) { benchString(16, b) } func BenchmarkRead256String(b *testing.B) { benchString(256, b) } func TestReadComplex64(t *testing.T) { var buf bytes.Buffer wr := NewWriter(&buf) rd := NewReader(&buf) for range 100 { buf.Reset() f := complex(rand.Float32()*math.MaxFloat32, rand.Float32()*math.MaxFloat32) wr.WriteComplex64(f) err := wr.Flush() if err != nil { t.Fatal(err) } out, err := rd.ReadComplex64() if err != nil { t.Error(err) continue } if out != f { t.Errorf("Wrote %f; read %f", f, out) } } } func BenchmarkReadComplex64(b *testing.B) { f := complex(rand.Float32(), rand.Float32()) data := AppendComplex64(nil, f) rd := NewReader(NewEndlessReader(data, b)) b.SetBytes(int64(len(data))) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := rd.ReadComplex64() if err != nil { b.Fatal(err) } } } func TestReadComplex128(t *testing.T) { var buf bytes.Buffer wr := NewWriter(&buf) rd := NewReader(&buf) for range 10 { buf.Reset() f := complex(rand.Float64()*math.MaxFloat64, rand.Float64()*math.MaxFloat64) wr.WriteComplex128(f) err := wr.Flush() if err != nil { t.Fatal(err) } out, err := rd.ReadComplex128() if err != nil { t.Error(err) continue } if out != f { t.Errorf("Wrote %f; read %f", f, out) } } } func BenchmarkReadComplex128(b *testing.B) { f := complex(rand.Float64(), rand.Float64()) data := AppendComplex128(nil, f) rd := NewReader(NewEndlessReader(data, b)) b.SetBytes(int64(len(data))) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := rd.ReadComplex128() if err != nil { b.Fatal(err) } } } func TestTime(t *testing.T) { var buf bytes.Buffer now := time.Now() en := NewWriter(&buf) dc := NewReader(&buf) err := en.WriteTime(now) if err != nil { t.Fatal(err) } err = en.Flush() if err != nil { t.Fatal(err) } out, err := dc.ReadTime() if err != nil { t.Fatal(err) } // check for equivalence if !now.Equal(out) { t.Fatalf("%s in; %s out", now, out) } } func BenchmarkReadTime(b *testing.B) { t := time.Now() data := AppendTime(nil, t) rd := NewReader(NewEndlessReader(data, b)) b.SetBytes(int64(len(data))) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := rd.ReadTime() if err != nil { b.Fatal(err) } } } func TestSkip(t *testing.T) { var buf bytes.Buffer wr := NewWriter(&buf) rd := NewReader(&buf) wr.WriteMapHeader(4) wr.WriteString("key_1") wr.WriteBytes([]byte("value_1")) wr.WriteString("key_2") wr.WriteFloat64(2.0) wr.WriteString("key_3") wr.WriteComplex128(3.0i) wr.WriteString("key_4") wr.WriteInt64(49080432189) wr.Flush() // this should skip the whole map err := rd.Skip() if err != nil { t.Fatal(err) } tp, err := rd.NextType() if err != io.EOF { t.Errorf("expected %q; got %q", io.EOF, err) t.Errorf("returned type %q", tp) } } func BenchmarkSkip(b *testing.B) { var buf bytes.Buffer en := NewWriter(&buf) en.WriteMapHeader(6) en.WriteString("thing_one") en.WriteString("value_one") en.WriteString("thing_two") en.WriteFloat64(3.14159) en.WriteString("some_bytes") en.WriteBytes([]byte("nkl4321rqw908vxzpojnlk2314rqew098-s09123rdscasd")) en.WriteString("the_time") en.WriteTime(time.Now()) en.WriteString("what?") en.WriteBool(true) en.WriteString("ext") en.WriteExtension(&RawExtension{Type: 55, Data: []byte("raw data!!!")}) en.Flush() bts := buf.Bytes() b.SetBytes(int64(len(bts))) b.ReportAllocs() b.ResetTimer() rd := NewReader(NewEndlessReader(bts, b)) for i := 0; i < b.N; i++ { err := rd.Skip() if err != nil { b.Fatal(err) } } } func TestCopyNext(t *testing.T) { var buf bytes.Buffer en := NewWriter(&buf) en.WriteMapHeader(6) en.WriteString("thing_one") en.WriteString("value_one") en.WriteString("thing_two") en.WriteFloat64(3.14159) en.WriteString("some_bytes") en.WriteBytes([]byte("nkl4321rqw908vxzpojnlk2314rqew098-s09123rdscasd")) en.WriteString("the_time") en.WriteTime(time.Now()) en.WriteString("what?") en.WriteBool(true) en.WriteString("ext") en.WriteExtension(&RawExtension{Type: 55, Data: []byte("raw data!!!")}) en.Flush() // Read from a copy of the original buf. de := NewReader(bytes.NewReader(buf.Bytes())) w := new(bytes.Buffer) n, err := de.CopyNext(w) if err != nil { t.Fatal(err) } if n != int64(buf.Len()) { t.Fatalf("CopyNext returned the wrong value (%d != %d)", n, buf.Len()) } if !bytes.Equal(buf.Bytes(), w.Bytes()) { t.Fatalf("not equal! %v, %v", buf.Bytes(), w.Bytes()) } } msgp-1.6.1/msgp/setof/000077500000000000000000000000001511433505400145545ustar00rootroot00000000000000msgp-1.6.1/msgp/setof/_gen/000077500000000000000000000000001511433505400154645ustar00rootroot00000000000000msgp-1.6.1/msgp/setof/_gen/main.go000066400000000000000000000546431511433505400167530ustar00rootroot00000000000000package main import ( "fmt" "os" "os/exec" "strings" ) const template = ` // DecodeMsg decodes the message from the reader. func (s *Foo) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(Foo, sz) } else { clear(dst) } for range sz { var k string k, err = reader.ReadString() if err != nil { return err } dst[string(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *Foo) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(Foo, sz) } else { clear(dst) } for range sz { var k string k, bytes, err = msgp.ReadStringBytes(bytes) if err != nil { return nil, err } dst[string(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s Foo) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.StringPrefixSize return size } // FooFromSlice creates a Foo from a slice. func FooFromSlice(s []string) Foo { if s == nil { return nil } dst := make(Foo, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } ` const unsorted = ` // Foo is a set of strings that will be stored as an array. // Elements are not sorted and the order of elements is not guaranteed. type Foo map[string]struct{} // EncodeMsg encodes the message to the writer. func (s Foo) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } for k := range s { err = writer.WriteString(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s Foo) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) for k := range s { bytes = msgp.AppendString(bytes, string(k)) } return bytes, nil } // AsSlice returns the set as a slice. func (s Foo) AsSlice() []string { if s == nil { return nil } dst := make([]string, 0, len(s)) for k := range s { dst = append(dst, k) } return dst } ` const sorted = ` // Foo is a set of strings that will be stored as an array. // Elements are sorted and the order of elements is guaranteed. type Foo map[string]struct{} // EncodeMsg encodes the message to the writer. func (s Foo) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } keys := make([]string, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b string) int { if a < b { return -1 } return 1 }) for _, k := range keys { err = writer.WriteString(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s Foo) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) keys := make([]string, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b string) int { if a < b { return -1 } return 1 }) for _, k := range keys { bytes = msgp.AppendString(bytes, k) } return bytes, nil } // AsSlice returns the set as a sorted slice. func (s Foo) AsSlice() []string { if s == nil { return nil } keys := make([]string, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b string) int { if a < b { return -1 } return 1 }) return keys } ` const testTemplate = ` func Test{{.TypeName}}_RoundTrip(t *testing.T) { set := make({{.TypeName}}) {{.PopulateSet}} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded {{.TypeName}} err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled {{.TypeName}} _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func Test{{.TypeName}}_AsSlice(t *testing.T) { set := make({{.TypeName}}) {{.PopulateSet}} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[{{.GoType}}]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func Test{{.TypeName}}_FromSlice(t *testing.T) { slice := []{{.GoType}}{{{.SliceValues}}} set := {{.TypeName}}FromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func Test{{.TypeName}}_NilHandling(t *testing.T) { var nilSet {{.TypeName}} // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded {{.TypeName}} err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled {{.TypeName}} _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := {{.TypeName}}FromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func Test{{.TypeName}}_EmptySet(t *testing.T) { set := make({{.TypeName}}) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded {{.TypeName}} err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled {{.TypeName}} _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } ` const benchTemplate = ` func Benchmark{{.TypeName}}_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make({{.TypeName}}) {{.GeneratePopulateCode}} var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func Benchmark{{.TypeName}}_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make({{.TypeName}}) {{.GeneratePopulateCode}} var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded {{.TypeName}} decoded.DecodeMsg(reader) } }) } } func Benchmark{{.TypeName}}_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make({{.TypeName}}) {{.GeneratePopulateCode}} b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func Benchmark{{.TypeName}}_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make({{.TypeName}}) {{.GeneratePopulateCode}} data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded {{.TypeName}} _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func Benchmark{{.TypeName}}_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make({{.TypeName}}) {{.GeneratePopulateCode}} b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func Benchmark{{.TypeName}}_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { {{.GenerateSliceCode}} b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = {{.TypeName}}FromSlice(slice) } }) } } ` type replacer struct { GoType string // 'string' PackageName string // 'Foo' DecodeValue string // 'ReadString' EncodeValue string // 'WriteString' AppendValue string // 'AppendString' KeyLen string // 'size += msgp.StringPrefixSize' Sorter string // 'sort.Slice(keys, func(i, j int) bool { return keys[i] < keys[j] })' } type testGen struct { TypeName string GoType string PopulateSet string SliceValues string Size string } func generateTestValues(goType string, size int) (populateSet, sliceValues string) { var populate []string var values []string switch goType { case "string": for i := 0; i < size; i++ { val := fmt.Sprintf(`"val%d"`, i) populate = append(populate, fmt.Sprintf("set[%s] = struct{}{}", val)) values = append(values, val) } case "int8": for i := 0; i < size; i++ { val := fmt.Sprintf("%d", (i%256)-128) // int8 range: -128 to 127 populate = append(populate, fmt.Sprintf("set[%s] = struct{}{}", val)) values = append(values, val) } case "int16": for i := 0; i < size; i++ { val := fmt.Sprintf("%d", (i%65536)-32768) // int16 range: -32768 to 32767 populate = append(populate, fmt.Sprintf("set[%s] = struct{}{}", val)) values = append(values, val) } case "int", "int32", "int64": for i := 0; i < size; i++ { val := fmt.Sprintf("%d", i) populate = append(populate, fmt.Sprintf("set[%s] = struct{}{}", val)) values = append(values, val) } case "byte": for i := 0; i < size; i++ { val := fmt.Sprintf("%d", i%256) // Prevent byte overflow populate = append(populate, fmt.Sprintf("set[%s] = struct{}{}", val)) values = append(values, val) } case "uint8": for i := 0; i < size; i++ { val := fmt.Sprintf("%d", i%256) // Prevent uint8 overflow populate = append(populate, fmt.Sprintf("set[%s] = struct{}{}", val)) values = append(values, val) } case "uint16": for i := 0; i < size; i++ { val := fmt.Sprintf("%d", i%65536) // Prevent uint16 overflow populate = append(populate, fmt.Sprintf("set[%s] = struct{}{}", val)) values = append(values, val) } case "uint", "uint32", "uint64": for i := 0; i < size; i++ { val := fmt.Sprintf("%d", i) populate = append(populate, fmt.Sprintf("set[%s] = struct{}{}", val)) values = append(values, val) } case "float32", "float64": for i := 0; i < size; i++ { val := fmt.Sprintf("%d.0", i) populate = append(populate, fmt.Sprintf("set[%s] = struct{}{}", val)) values = append(values, val) } } return strings.Join(populate, "\n\t"), strings.Join(values, ", ") } func generateDynamicPopulateCode(goType string) string { switch goType { case "string": return `for i := 0; i < size; i++ { set[fmt.Sprintf("val%d", i)] = struct{}{} }` case "int8": return `for i := 0; i < size; i++ { set[int8((i%256)-128)] = struct{}{} }` case "int16": return `for i := 0; i < size; i++ { set[int16((i%65536)-32768)] = struct{}{} }` case "int", "int32", "int64": return `for i := 0; i < size; i++ { set[` + goType + `(i)] = struct{}{} }` case "byte": return `for i := 0; i < size; i++ { set[byte(i%256)] = struct{}{} }` case "uint8": return `for i := 0; i < size; i++ { set[uint8(i%256)] = struct{}{} }` case "uint16": return `for i := 0; i < size; i++ { set[uint16(i%65536)] = struct{}{} }` case "uint", "uint32", "uint64": return `for i := 0; i < size; i++ { set[` + goType + `(i)] = struct{}{} }` case "float32", "float64": return `for i := 0; i < size; i++ { set[` + goType + `(i)] = struct{}{} }` } return "" } func generateDynamicSliceCode(goType string) string { switch goType { case "string": return `slice := make([]string, size) for i := 0; i < size; i++ { slice[i] = fmt.Sprintf("val%d", i) }` case "int8": return `slice := make([]int8, size) for i := 0; i < size; i++ { slice[i] = int8((i%256)-128) }` case "int16": return `slice := make([]int16, size) for i := 0; i < size; i++ { slice[i] = int16((i%65536)-32768) }` case "int", "int32", "int64": return `slice := make([]` + goType + `, size) for i := 0; i < size; i++ { slice[i] = ` + goType + `(i) }` case "byte": return `slice := make([]byte, size) for i := 0; i < size; i++ { slice[i] = byte(i%256) }` case "uint8": return `slice := make([]uint8, size) for i := 0; i < size; i++ { slice[i] = uint8(i%256) }` case "uint16": return `slice := make([]uint16, size) for i := 0; i < size; i++ { slice[i] = uint16(i%65536) }` case "uint", "uint32", "uint64": return `slice := make([]` + goType + `, size) for i := 0; i < size; i++ { slice[i] = ` + goType + `(i) }` case "float32", "float64": return `slice := make([]` + goType + `, size) for i := 0; i < size; i++ { slice[i] = ` + goType + `(i) }` } return "" } func generateTests(out *os.File, r replacer) { // Generate basic tests (using small set) populateSet, sliceValues := generateTestValues(r.GoType, 5) // Regular type tests testCode := testTemplate testCode = strings.ReplaceAll(testCode, "{{.TypeName}}", r.PackageName) testCode = strings.ReplaceAll(testCode, "{{.GoType}}", r.GoType) testCode = strings.ReplaceAll(testCode, "{{.PopulateSet}}", populateSet) testCode = strings.ReplaceAll(testCode, "{{.SliceValues}}", sliceValues) fmt.Fprintln(out, testCode) // Sorted type tests testCode = testTemplate testCode = strings.ReplaceAll(testCode, "{{.TypeName}}", r.PackageName+"Sorted") testCode = strings.ReplaceAll(testCode, "{{.GoType}}", r.GoType) testCode = strings.ReplaceAll(testCode, "{{.PopulateSet}}", populateSet) testCode = strings.ReplaceAll(testCode, "{{.SliceValues}}", sliceValues) fmt.Fprintln(out, testCode) // Generate consolidated benchmarks populateCode := generateDynamicPopulateCode(r.GoType) sliceCode := generateDynamicSliceCode(r.GoType) // Regular type benchmarks benchCode := benchTemplate benchCode = strings.ReplaceAll(benchCode, "{{.TypeName}}", r.PackageName) benchCode = strings.ReplaceAll(benchCode, "{{.GoType}}", r.GoType) benchCode = strings.ReplaceAll(benchCode, "{{.GeneratePopulateCode}}", populateCode) benchCode = strings.ReplaceAll(benchCode, "{{.GenerateSliceCode}}", sliceCode) fmt.Fprintln(out, benchCode) // Sorted type benchmarks benchCode = benchTemplate benchCode = strings.ReplaceAll(benchCode, "{{.TypeName}}", r.PackageName+"Sorted") benchCode = strings.ReplaceAll(benchCode, "{{.GoType}}", r.GoType) benchCode = strings.ReplaceAll(benchCode, "{{.GeneratePopulateCode}}", populateCode) benchCode = strings.ReplaceAll(benchCode, "{{.GenerateSliceCode}}", sliceCode) fmt.Fprintln(out, benchCode) } var replacers = []replacer{ { GoType: "string", PackageName: "Foo", DecodeValue: "ReadString", EncodeValue: "WriteString", AppendValue: "AppendString", KeyLen: "size += len(s) * msgp.StringPrefixSize", Sorter: "slices.SortFunc(keys, func(a, b string) int {\n\t\tif a < b {\n\t\t\treturn -1\n\t\t}\n\t\treturn 1\n\t})", }, { GoType: "string", PackageName: "String", DecodeValue: "ReadString", EncodeValue: "WriteString", AppendValue: "AppendString", KeyLen: "for key := range s {\n\t\t\tsize += msgp.StringPrefixSize + len(key)\n\t\t}", // Using slices.SortFunc is slower than sort.Strings Sorter: "sort.Strings(keys)", }, { GoType: "int", PackageName: "Int", DecodeValue: "ReadInt", EncodeValue: "WriteInt", AppendValue: "AppendInt", KeyLen: "size += len(s) * msgp.IntSize", }, { GoType: "uint", PackageName: "Uint", DecodeValue: "ReadUint", EncodeValue: "WriteUint", AppendValue: "AppendUint", KeyLen: "size += len(s) * msgp.UintSize", }, { GoType: "byte", PackageName: "Byte", DecodeValue: "ReadByte", EncodeValue: "WriteByte", AppendValue: "AppendByte", KeyLen: "size += len(s) * msgp.ByteSize", }, { GoType: "int8", PackageName: "Int8", DecodeValue: "ReadInt8", EncodeValue: "WriteInt8", AppendValue: "AppendInt8", KeyLen: "size += len(s) * msgp.Int8Size", }, { GoType: "uint8", PackageName: "Uint8", DecodeValue: "ReadUint8", EncodeValue: "WriteUint8", AppendValue: "AppendUint8", KeyLen: "size += len(s) * msgp.Uint8Size", }, { GoType: "int16", PackageName: "Int16", DecodeValue: "ReadInt16", EncodeValue: "WriteInt16", AppendValue: "AppendInt16", KeyLen: "size += len(s) * msgp.Int16Size", }, { GoType: "uint16", PackageName: "Uint16", DecodeValue: "ReadUint16", EncodeValue: "WriteUint16", AppendValue: "AppendUint16", KeyLen: "size += len(s) * msgp.Uint16Size", }, { GoType: "int32", PackageName: "Int32", DecodeValue: "ReadInt32", EncodeValue: "WriteInt32", AppendValue: "AppendInt32", KeyLen: "size += len(s) * msgp.Int32Size", }, { GoType: "uint32", PackageName: "Uint32", DecodeValue: "ReadUint32", EncodeValue: "WriteUint32", AppendValue: "AppendUint32", KeyLen: "size += len(s) * msgp.Uint32Size", }, { GoType: "int64", PackageName: "Int64", DecodeValue: "ReadInt64", EncodeValue: "WriteInt64", AppendValue: "AppendInt64", KeyLen: "size += len(s) * msgp.Int64Size", }, { GoType: "uint64", PackageName: "Uint64", DecodeValue: "ReadUint64", EncodeValue: "WriteUint64", AppendValue: "AppendUint64", KeyLen: "size += len(s) * msgp.Uint64Size", }, { GoType: "float64", PackageName: "Float64", DecodeValue: "ReadFloat64", EncodeValue: "WriteFloat", AppendValue: "AppendFloat", KeyLen: "size += len(s) * msgp.Float64Size", }, { GoType: "float32", PackageName: "Float32", DecodeValue: "ReadFloat32", EncodeValue: "WriteFloat32", AppendValue: "AppendFloat32", KeyLen: "size += len(s) * msgp.Float32Size", }, } func main() { defer func() { if r := recover(); r != nil { panic(r) } else { // Format generated code if err := exec.Command("go", "fmt", "../generated.go").Run(); err != nil { fmt.Printf("Warning: failed to format generated.go: %v\n", err) } if err := exec.Command("go", "fmt", "../generated_test.go").Run(); err != nil { fmt.Printf("Warning: failed to format generated_test.go: %v\n", err) } } }() out, err := os.Create("../generated.go") if err != nil { panic(err) } defer out.Close() fmt.Fprintln(out, `// Code generated by ./gen/main.go. DO NOT EDIT. package setof import ( "slices" "sort" "github.com/tinylib/msgp/msgp" )`) base := replacers[0] for _, r := range replacers[1:] { replaced := unsorted + template replaced = strings.ReplaceAll(replaced, base.GoType, r.GoType) replaced = strings.ReplaceAll(replaced, base.PackageName, r.PackageName) replaced = strings.ReplaceAll(replaced, base.EncodeValue, r.EncodeValue) replaced = strings.ReplaceAll(replaced, base.DecodeValue, r.DecodeValue) replaced = strings.ReplaceAll(replaced, base.AppendValue, r.AppendValue) replaced = strings.ReplaceAll(replaced, base.KeyLen, r.KeyLen) fmt.Fprintln(out, replaced) replaced = sorted + template if r.Sorter != "" { replaced = strings.ReplaceAll(replaced, base.Sorter, r.Sorter) } replaced = strings.ReplaceAll(replaced, base.GoType, r.GoType) replaced = strings.ReplaceAll(replaced, base.PackageName, r.PackageName+"Sorted") replaced = strings.ReplaceAll(replaced, base.EncodeValue, r.EncodeValue) replaced = strings.ReplaceAll(replaced, base.DecodeValue, r.DecodeValue) replaced = strings.ReplaceAll(replaced, base.AppendValue, r.AppendValue) replaced = strings.ReplaceAll(replaced, base.KeyLen, r.KeyLen) fmt.Fprintln(out, replaced) } // Generate test file testOut, err := os.Create("../generated_test.go") if err != nil { panic(err) } defer testOut.Close() fmt.Fprintln(testOut, `// Code generated by ./gen/main.go. DO NOT EDIT. package setof import ( "bytes" "fmt" "testing" "github.com/tinylib/msgp/msgp" )`) // Generate tests for each type (skip the template base type) for _, r := range replacers[1:] { generateTests(testOut, r) } } msgp-1.6.1/msgp/setof/generated.go000066400000000000000000002315571511433505400170560ustar00rootroot00000000000000// Code generated by ./gen/main.go. DO NOT EDIT. package setof import ( "slices" "sort" "github.com/tinylib/msgp/msgp" ) // String is a set of strings that will be stored as an array. // Elements are not sorted and the order of elements is not guaranteed. type String map[string]struct{} // EncodeMsg encodes the message to the writer. func (s String) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } for k := range s { err = writer.WriteString(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s String) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) for k := range s { bytes = msgp.AppendString(bytes, string(k)) } return bytes, nil } // AsSlice returns the set as a slice. func (s String) AsSlice() []string { if s == nil { return nil } dst := make([]string, 0, len(s)) for k := range s { dst = append(dst, k) } return dst } // DecodeMsg decodes the message from the reader. func (s *String) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(String, sz) } else { clear(dst) } for range sz { var k string k, err = reader.ReadString() if err != nil { return err } dst[string(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *String) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(String, sz) } else { clear(dst) } for range sz { var k string k, bytes, err = msgp.ReadStringBytes(bytes) if err != nil { return nil, err } dst[string(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s String) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize for key := range s { size += msgp.StringPrefixSize + len(key) } return size } // StringFromSlice creates a String from a slice. func StringFromSlice(s []string) String { if s == nil { return nil } dst := make(String, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // StringSorted is a set of strings that will be stored as an array. // Elements are sorted and the order of elements is guaranteed. type StringSorted map[string]struct{} // EncodeMsg encodes the message to the writer. func (s StringSorted) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } keys := make([]string, 0, len(s)) for k := range s { keys = append(keys, k) } sort.Strings(keys) for _, k := range keys { err = writer.WriteString(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s StringSorted) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) keys := make([]string, 0, len(s)) for k := range s { keys = append(keys, k) } sort.Strings(keys) for _, k := range keys { bytes = msgp.AppendString(bytes, k) } return bytes, nil } // AsSlice returns the set as a sorted slice. func (s StringSorted) AsSlice() []string { if s == nil { return nil } keys := make([]string, 0, len(s)) for k := range s { keys = append(keys, k) } sort.Strings(keys) return keys } // DecodeMsg decodes the message from the reader. func (s *StringSorted) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(StringSorted, sz) } else { clear(dst) } for range sz { var k string k, err = reader.ReadString() if err != nil { return err } dst[string(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *StringSorted) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(StringSorted, sz) } else { clear(dst) } for range sz { var k string k, bytes, err = msgp.ReadStringBytes(bytes) if err != nil { return nil, err } dst[string(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s StringSorted) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize for key := range s { size += msgp.StringPrefixSize + len(key) } return size } // StringSortedFromSlice creates a StringSorted from a slice. func StringSortedFromSlice(s []string) StringSorted { if s == nil { return nil } dst := make(StringSorted, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // Int is a set of ints that will be stored as an array. // Elements are not sorted and the order of elements is not guaranteed. type Int map[int]struct{} // EncodeMsg encodes the message to the writer. func (s Int) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } for k := range s { err = writer.WriteInt(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s Int) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) for k := range s { bytes = msgp.AppendInt(bytes, int(k)) } return bytes, nil } // AsSlice returns the set as a slice. func (s Int) AsSlice() []int { if s == nil { return nil } dst := make([]int, 0, len(s)) for k := range s { dst = append(dst, k) } return dst } // DecodeMsg decodes the message from the reader. func (s *Int) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(Int, sz) } else { clear(dst) } for range sz { var k int k, err = reader.ReadInt() if err != nil { return err } dst[int(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *Int) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(Int, sz) } else { clear(dst) } for range sz { var k int k, bytes, err = msgp.ReadIntBytes(bytes) if err != nil { return nil, err } dst[int(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s Int) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.IntSize return size } // IntFromSlice creates a Int from a slice. func IntFromSlice(s []int) Int { if s == nil { return nil } dst := make(Int, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // IntSorted is a set of ints that will be stored as an array. // Elements are sorted and the order of elements is guaranteed. type IntSorted map[int]struct{} // EncodeMsg encodes the message to the writer. func (s IntSorted) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } keys := make([]int, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b int) int { if a < b { return -1 } return 1 }) for _, k := range keys { err = writer.WriteInt(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s IntSorted) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) keys := make([]int, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b int) int { if a < b { return -1 } return 1 }) for _, k := range keys { bytes = msgp.AppendInt(bytes, k) } return bytes, nil } // AsSlice returns the set as a sorted slice. func (s IntSorted) AsSlice() []int { if s == nil { return nil } keys := make([]int, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b int) int { if a < b { return -1 } return 1 }) return keys } // DecodeMsg decodes the message from the reader. func (s *IntSorted) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(IntSorted, sz) } else { clear(dst) } for range sz { var k int k, err = reader.ReadInt() if err != nil { return err } dst[int(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *IntSorted) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(IntSorted, sz) } else { clear(dst) } for range sz { var k int k, bytes, err = msgp.ReadIntBytes(bytes) if err != nil { return nil, err } dst[int(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s IntSorted) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.IntSize return size } // IntSortedFromSlice creates a IntSorted from a slice. func IntSortedFromSlice(s []int) IntSorted { if s == nil { return nil } dst := make(IntSorted, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // Uint is a set of uints that will be stored as an array. // Elements are not sorted and the order of elements is not guaranteed. type Uint map[uint]struct{} // EncodeMsg encodes the message to the writer. func (s Uint) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } for k := range s { err = writer.WriteUint(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s Uint) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) for k := range s { bytes = msgp.AppendUint(bytes, uint(k)) } return bytes, nil } // AsSlice returns the set as a slice. func (s Uint) AsSlice() []uint { if s == nil { return nil } dst := make([]uint, 0, len(s)) for k := range s { dst = append(dst, k) } return dst } // DecodeMsg decodes the message from the reader. func (s *Uint) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(Uint, sz) } else { clear(dst) } for range sz { var k uint k, err = reader.ReadUint() if err != nil { return err } dst[uint(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *Uint) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(Uint, sz) } else { clear(dst) } for range sz { var k uint k, bytes, err = msgp.ReadUintBytes(bytes) if err != nil { return nil, err } dst[uint(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s Uint) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.UintSize return size } // UintFromSlice creates a Uint from a slice. func UintFromSlice(s []uint) Uint { if s == nil { return nil } dst := make(Uint, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // UintSorted is a set of uints that will be stored as an array. // Elements are sorted and the order of elements is guaranteed. type UintSorted map[uint]struct{} // EncodeMsg encodes the message to the writer. func (s UintSorted) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } keys := make([]uint, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b uint) int { if a < b { return -1 } return 1 }) for _, k := range keys { err = writer.WriteUint(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s UintSorted) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) keys := make([]uint, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b uint) int { if a < b { return -1 } return 1 }) for _, k := range keys { bytes = msgp.AppendUint(bytes, k) } return bytes, nil } // AsSlice returns the set as a sorted slice. func (s UintSorted) AsSlice() []uint { if s == nil { return nil } keys := make([]uint, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b uint) int { if a < b { return -1 } return 1 }) return keys } // DecodeMsg decodes the message from the reader. func (s *UintSorted) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(UintSorted, sz) } else { clear(dst) } for range sz { var k uint k, err = reader.ReadUint() if err != nil { return err } dst[uint(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *UintSorted) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(UintSorted, sz) } else { clear(dst) } for range sz { var k uint k, bytes, err = msgp.ReadUintBytes(bytes) if err != nil { return nil, err } dst[uint(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s UintSorted) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.UintSize return size } // UintSortedFromSlice creates a UintSorted from a slice. func UintSortedFromSlice(s []uint) UintSorted { if s == nil { return nil } dst := make(UintSorted, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // Byte is a set of bytes that will be stored as an array. // Elements are not sorted and the order of elements is not guaranteed. type Byte map[byte]struct{} // EncodeMsg encodes the message to the writer. func (s Byte) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } for k := range s { err = writer.WriteByte(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s Byte) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) for k := range s { bytes = msgp.AppendByte(bytes, byte(k)) } return bytes, nil } // AsSlice returns the set as a slice. func (s Byte) AsSlice() []byte { if s == nil { return nil } dst := make([]byte, 0, len(s)) for k := range s { dst = append(dst, k) } return dst } // DecodeMsg decodes the message from the reader. func (s *Byte) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(Byte, sz) } else { clear(dst) } for range sz { var k byte k, err = reader.ReadByte() if err != nil { return err } dst[byte(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *Byte) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(Byte, sz) } else { clear(dst) } for range sz { var k byte k, bytes, err = msgp.ReadByteBytes(bytes) if err != nil { return nil, err } dst[byte(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s Byte) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.ByteSize return size } // ByteFromSlice creates a Byte from a slice. func ByteFromSlice(s []byte) Byte { if s == nil { return nil } dst := make(Byte, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // ByteSorted is a set of bytes that will be stored as an array. // Elements are sorted and the order of elements is guaranteed. type ByteSorted map[byte]struct{} // EncodeMsg encodes the message to the writer. func (s ByteSorted) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } keys := make([]byte, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b byte) int { if a < b { return -1 } return 1 }) for _, k := range keys { err = writer.WriteByte(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s ByteSorted) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) keys := make([]byte, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b byte) int { if a < b { return -1 } return 1 }) for _, k := range keys { bytes = msgp.AppendByte(bytes, k) } return bytes, nil } // AsSlice returns the set as a sorted slice. func (s ByteSorted) AsSlice() []byte { if s == nil { return nil } keys := make([]byte, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b byte) int { if a < b { return -1 } return 1 }) return keys } // DecodeMsg decodes the message from the reader. func (s *ByteSorted) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(ByteSorted, sz) } else { clear(dst) } for range sz { var k byte k, err = reader.ReadByte() if err != nil { return err } dst[byte(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *ByteSorted) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(ByteSorted, sz) } else { clear(dst) } for range sz { var k byte k, bytes, err = msgp.ReadByteBytes(bytes) if err != nil { return nil, err } dst[byte(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s ByteSorted) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.ByteSize return size } // ByteSortedFromSlice creates a ByteSorted from a slice. func ByteSortedFromSlice(s []byte) ByteSorted { if s == nil { return nil } dst := make(ByteSorted, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // Int8 is a set of int8s that will be stored as an array. // Elements are not sorted and the order of elements is not guaranteed. type Int8 map[int8]struct{} // EncodeMsg encodes the message to the writer. func (s Int8) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } for k := range s { err = writer.WriteInt8(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s Int8) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) for k := range s { bytes = msgp.AppendInt8(bytes, int8(k)) } return bytes, nil } // AsSlice returns the set as a slice. func (s Int8) AsSlice() []int8 { if s == nil { return nil } dst := make([]int8, 0, len(s)) for k := range s { dst = append(dst, k) } return dst } // DecodeMsg decodes the message from the reader. func (s *Int8) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(Int8, sz) } else { clear(dst) } for range sz { var k int8 k, err = reader.ReadInt8() if err != nil { return err } dst[int8(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *Int8) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(Int8, sz) } else { clear(dst) } for range sz { var k int8 k, bytes, err = msgp.ReadInt8Bytes(bytes) if err != nil { return nil, err } dst[int8(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s Int8) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.Int8Size return size } // Int8FromSlice creates a Int8 from a slice. func Int8FromSlice(s []int8) Int8 { if s == nil { return nil } dst := make(Int8, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // Int8Sorted is a set of int8s that will be stored as an array. // Elements are sorted and the order of elements is guaranteed. type Int8Sorted map[int8]struct{} // EncodeMsg encodes the message to the writer. func (s Int8Sorted) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } keys := make([]int8, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b int8) int { if a < b { return -1 } return 1 }) for _, k := range keys { err = writer.WriteInt8(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s Int8Sorted) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) keys := make([]int8, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b int8) int { if a < b { return -1 } return 1 }) for _, k := range keys { bytes = msgp.AppendInt8(bytes, k) } return bytes, nil } // AsSlice returns the set as a sorted slice. func (s Int8Sorted) AsSlice() []int8 { if s == nil { return nil } keys := make([]int8, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b int8) int { if a < b { return -1 } return 1 }) return keys } // DecodeMsg decodes the message from the reader. func (s *Int8Sorted) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(Int8Sorted, sz) } else { clear(dst) } for range sz { var k int8 k, err = reader.ReadInt8() if err != nil { return err } dst[int8(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *Int8Sorted) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(Int8Sorted, sz) } else { clear(dst) } for range sz { var k int8 k, bytes, err = msgp.ReadInt8Bytes(bytes) if err != nil { return nil, err } dst[int8(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s Int8Sorted) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.Int8Size return size } // Int8SortedFromSlice creates a Int8Sorted from a slice. func Int8SortedFromSlice(s []int8) Int8Sorted { if s == nil { return nil } dst := make(Int8Sorted, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // Uint8 is a set of uint8s that will be stored as an array. // Elements are not sorted and the order of elements is not guaranteed. type Uint8 map[uint8]struct{} // EncodeMsg encodes the message to the writer. func (s Uint8) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } for k := range s { err = writer.WriteUint8(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s Uint8) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) for k := range s { bytes = msgp.AppendUint8(bytes, uint8(k)) } return bytes, nil } // AsSlice returns the set as a slice. func (s Uint8) AsSlice() []uint8 { if s == nil { return nil } dst := make([]uint8, 0, len(s)) for k := range s { dst = append(dst, k) } return dst } // DecodeMsg decodes the message from the reader. func (s *Uint8) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(Uint8, sz) } else { clear(dst) } for range sz { var k uint8 k, err = reader.ReadUint8() if err != nil { return err } dst[uint8(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *Uint8) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(Uint8, sz) } else { clear(dst) } for range sz { var k uint8 k, bytes, err = msgp.ReadUint8Bytes(bytes) if err != nil { return nil, err } dst[uint8(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s Uint8) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.Uint8Size return size } // Uint8FromSlice creates a Uint8 from a slice. func Uint8FromSlice(s []uint8) Uint8 { if s == nil { return nil } dst := make(Uint8, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // Uint8Sorted is a set of uint8s that will be stored as an array. // Elements are sorted and the order of elements is guaranteed. type Uint8Sorted map[uint8]struct{} // EncodeMsg encodes the message to the writer. func (s Uint8Sorted) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } keys := make([]uint8, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b uint8) int { if a < b { return -1 } return 1 }) for _, k := range keys { err = writer.WriteUint8(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s Uint8Sorted) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) keys := make([]uint8, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b uint8) int { if a < b { return -1 } return 1 }) for _, k := range keys { bytes = msgp.AppendUint8(bytes, k) } return bytes, nil } // AsSlice returns the set as a sorted slice. func (s Uint8Sorted) AsSlice() []uint8 { if s == nil { return nil } keys := make([]uint8, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b uint8) int { if a < b { return -1 } return 1 }) return keys } // DecodeMsg decodes the message from the reader. func (s *Uint8Sorted) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(Uint8Sorted, sz) } else { clear(dst) } for range sz { var k uint8 k, err = reader.ReadUint8() if err != nil { return err } dst[uint8(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *Uint8Sorted) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(Uint8Sorted, sz) } else { clear(dst) } for range sz { var k uint8 k, bytes, err = msgp.ReadUint8Bytes(bytes) if err != nil { return nil, err } dst[uint8(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s Uint8Sorted) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.Uint8Size return size } // Uint8SortedFromSlice creates a Uint8Sorted from a slice. func Uint8SortedFromSlice(s []uint8) Uint8Sorted { if s == nil { return nil } dst := make(Uint8Sorted, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // Int16 is a set of int16s that will be stored as an array. // Elements are not sorted and the order of elements is not guaranteed. type Int16 map[int16]struct{} // EncodeMsg encodes the message to the writer. func (s Int16) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } for k := range s { err = writer.WriteInt16(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s Int16) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) for k := range s { bytes = msgp.AppendInt16(bytes, int16(k)) } return bytes, nil } // AsSlice returns the set as a slice. func (s Int16) AsSlice() []int16 { if s == nil { return nil } dst := make([]int16, 0, len(s)) for k := range s { dst = append(dst, k) } return dst } // DecodeMsg decodes the message from the reader. func (s *Int16) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(Int16, sz) } else { clear(dst) } for range sz { var k int16 k, err = reader.ReadInt16() if err != nil { return err } dst[int16(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *Int16) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(Int16, sz) } else { clear(dst) } for range sz { var k int16 k, bytes, err = msgp.ReadInt16Bytes(bytes) if err != nil { return nil, err } dst[int16(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s Int16) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.Int16Size return size } // Int16FromSlice creates a Int16 from a slice. func Int16FromSlice(s []int16) Int16 { if s == nil { return nil } dst := make(Int16, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // Int16Sorted is a set of int16s that will be stored as an array. // Elements are sorted and the order of elements is guaranteed. type Int16Sorted map[int16]struct{} // EncodeMsg encodes the message to the writer. func (s Int16Sorted) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } keys := make([]int16, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b int16) int { if a < b { return -1 } return 1 }) for _, k := range keys { err = writer.WriteInt16(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s Int16Sorted) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) keys := make([]int16, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b int16) int { if a < b { return -1 } return 1 }) for _, k := range keys { bytes = msgp.AppendInt16(bytes, k) } return bytes, nil } // AsSlice returns the set as a sorted slice. func (s Int16Sorted) AsSlice() []int16 { if s == nil { return nil } keys := make([]int16, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b int16) int { if a < b { return -1 } return 1 }) return keys } // DecodeMsg decodes the message from the reader. func (s *Int16Sorted) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(Int16Sorted, sz) } else { clear(dst) } for range sz { var k int16 k, err = reader.ReadInt16() if err != nil { return err } dst[int16(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *Int16Sorted) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(Int16Sorted, sz) } else { clear(dst) } for range sz { var k int16 k, bytes, err = msgp.ReadInt16Bytes(bytes) if err != nil { return nil, err } dst[int16(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s Int16Sorted) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.Int16Size return size } // Int16SortedFromSlice creates a Int16Sorted from a slice. func Int16SortedFromSlice(s []int16) Int16Sorted { if s == nil { return nil } dst := make(Int16Sorted, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // Uint16 is a set of uint16s that will be stored as an array. // Elements are not sorted and the order of elements is not guaranteed. type Uint16 map[uint16]struct{} // EncodeMsg encodes the message to the writer. func (s Uint16) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } for k := range s { err = writer.WriteUint16(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s Uint16) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) for k := range s { bytes = msgp.AppendUint16(bytes, uint16(k)) } return bytes, nil } // AsSlice returns the set as a slice. func (s Uint16) AsSlice() []uint16 { if s == nil { return nil } dst := make([]uint16, 0, len(s)) for k := range s { dst = append(dst, k) } return dst } // DecodeMsg decodes the message from the reader. func (s *Uint16) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(Uint16, sz) } else { clear(dst) } for range sz { var k uint16 k, err = reader.ReadUint16() if err != nil { return err } dst[uint16(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *Uint16) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(Uint16, sz) } else { clear(dst) } for range sz { var k uint16 k, bytes, err = msgp.ReadUint16Bytes(bytes) if err != nil { return nil, err } dst[uint16(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s Uint16) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.Uint16Size return size } // Uint16FromSlice creates a Uint16 from a slice. func Uint16FromSlice(s []uint16) Uint16 { if s == nil { return nil } dst := make(Uint16, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // Uint16Sorted is a set of uint16s that will be stored as an array. // Elements are sorted and the order of elements is guaranteed. type Uint16Sorted map[uint16]struct{} // EncodeMsg encodes the message to the writer. func (s Uint16Sorted) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } keys := make([]uint16, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b uint16) int { if a < b { return -1 } return 1 }) for _, k := range keys { err = writer.WriteUint16(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s Uint16Sorted) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) keys := make([]uint16, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b uint16) int { if a < b { return -1 } return 1 }) for _, k := range keys { bytes = msgp.AppendUint16(bytes, k) } return bytes, nil } // AsSlice returns the set as a sorted slice. func (s Uint16Sorted) AsSlice() []uint16 { if s == nil { return nil } keys := make([]uint16, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b uint16) int { if a < b { return -1 } return 1 }) return keys } // DecodeMsg decodes the message from the reader. func (s *Uint16Sorted) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(Uint16Sorted, sz) } else { clear(dst) } for range sz { var k uint16 k, err = reader.ReadUint16() if err != nil { return err } dst[uint16(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *Uint16Sorted) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(Uint16Sorted, sz) } else { clear(dst) } for range sz { var k uint16 k, bytes, err = msgp.ReadUint16Bytes(bytes) if err != nil { return nil, err } dst[uint16(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s Uint16Sorted) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.Uint16Size return size } // Uint16SortedFromSlice creates a Uint16Sorted from a slice. func Uint16SortedFromSlice(s []uint16) Uint16Sorted { if s == nil { return nil } dst := make(Uint16Sorted, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // Int32 is a set of int32s that will be stored as an array. // Elements are not sorted and the order of elements is not guaranteed. type Int32 map[int32]struct{} // EncodeMsg encodes the message to the writer. func (s Int32) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } for k := range s { err = writer.WriteInt32(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s Int32) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) for k := range s { bytes = msgp.AppendInt32(bytes, int32(k)) } return bytes, nil } // AsSlice returns the set as a slice. func (s Int32) AsSlice() []int32 { if s == nil { return nil } dst := make([]int32, 0, len(s)) for k := range s { dst = append(dst, k) } return dst } // DecodeMsg decodes the message from the reader. func (s *Int32) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(Int32, sz) } else { clear(dst) } for range sz { var k int32 k, err = reader.ReadInt32() if err != nil { return err } dst[int32(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *Int32) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(Int32, sz) } else { clear(dst) } for range sz { var k int32 k, bytes, err = msgp.ReadInt32Bytes(bytes) if err != nil { return nil, err } dst[int32(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s Int32) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.Int32Size return size } // Int32FromSlice creates a Int32 from a slice. func Int32FromSlice(s []int32) Int32 { if s == nil { return nil } dst := make(Int32, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // Int32Sorted is a set of int32s that will be stored as an array. // Elements are sorted and the order of elements is guaranteed. type Int32Sorted map[int32]struct{} // EncodeMsg encodes the message to the writer. func (s Int32Sorted) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } keys := make([]int32, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b int32) int { if a < b { return -1 } return 1 }) for _, k := range keys { err = writer.WriteInt32(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s Int32Sorted) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) keys := make([]int32, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b int32) int { if a < b { return -1 } return 1 }) for _, k := range keys { bytes = msgp.AppendInt32(bytes, k) } return bytes, nil } // AsSlice returns the set as a sorted slice. func (s Int32Sorted) AsSlice() []int32 { if s == nil { return nil } keys := make([]int32, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b int32) int { if a < b { return -1 } return 1 }) return keys } // DecodeMsg decodes the message from the reader. func (s *Int32Sorted) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(Int32Sorted, sz) } else { clear(dst) } for range sz { var k int32 k, err = reader.ReadInt32() if err != nil { return err } dst[int32(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *Int32Sorted) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(Int32Sorted, sz) } else { clear(dst) } for range sz { var k int32 k, bytes, err = msgp.ReadInt32Bytes(bytes) if err != nil { return nil, err } dst[int32(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s Int32Sorted) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.Int32Size return size } // Int32SortedFromSlice creates a Int32Sorted from a slice. func Int32SortedFromSlice(s []int32) Int32Sorted { if s == nil { return nil } dst := make(Int32Sorted, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // Uint32 is a set of uint32s that will be stored as an array. // Elements are not sorted and the order of elements is not guaranteed. type Uint32 map[uint32]struct{} // EncodeMsg encodes the message to the writer. func (s Uint32) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } for k := range s { err = writer.WriteUint32(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s Uint32) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) for k := range s { bytes = msgp.AppendUint32(bytes, uint32(k)) } return bytes, nil } // AsSlice returns the set as a slice. func (s Uint32) AsSlice() []uint32 { if s == nil { return nil } dst := make([]uint32, 0, len(s)) for k := range s { dst = append(dst, k) } return dst } // DecodeMsg decodes the message from the reader. func (s *Uint32) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(Uint32, sz) } else { clear(dst) } for range sz { var k uint32 k, err = reader.ReadUint32() if err != nil { return err } dst[uint32(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *Uint32) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(Uint32, sz) } else { clear(dst) } for range sz { var k uint32 k, bytes, err = msgp.ReadUint32Bytes(bytes) if err != nil { return nil, err } dst[uint32(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s Uint32) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.Uint32Size return size } // Uint32FromSlice creates a Uint32 from a slice. func Uint32FromSlice(s []uint32) Uint32 { if s == nil { return nil } dst := make(Uint32, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // Uint32Sorted is a set of uint32s that will be stored as an array. // Elements are sorted and the order of elements is guaranteed. type Uint32Sorted map[uint32]struct{} // EncodeMsg encodes the message to the writer. func (s Uint32Sorted) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } keys := make([]uint32, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b uint32) int { if a < b { return -1 } return 1 }) for _, k := range keys { err = writer.WriteUint32(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s Uint32Sorted) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) keys := make([]uint32, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b uint32) int { if a < b { return -1 } return 1 }) for _, k := range keys { bytes = msgp.AppendUint32(bytes, k) } return bytes, nil } // AsSlice returns the set as a sorted slice. func (s Uint32Sorted) AsSlice() []uint32 { if s == nil { return nil } keys := make([]uint32, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b uint32) int { if a < b { return -1 } return 1 }) return keys } // DecodeMsg decodes the message from the reader. func (s *Uint32Sorted) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(Uint32Sorted, sz) } else { clear(dst) } for range sz { var k uint32 k, err = reader.ReadUint32() if err != nil { return err } dst[uint32(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *Uint32Sorted) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(Uint32Sorted, sz) } else { clear(dst) } for range sz { var k uint32 k, bytes, err = msgp.ReadUint32Bytes(bytes) if err != nil { return nil, err } dst[uint32(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s Uint32Sorted) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.Uint32Size return size } // Uint32SortedFromSlice creates a Uint32Sorted from a slice. func Uint32SortedFromSlice(s []uint32) Uint32Sorted { if s == nil { return nil } dst := make(Uint32Sorted, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // Int64 is a set of int64s that will be stored as an array. // Elements are not sorted and the order of elements is not guaranteed. type Int64 map[int64]struct{} // EncodeMsg encodes the message to the writer. func (s Int64) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } for k := range s { err = writer.WriteInt64(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s Int64) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) for k := range s { bytes = msgp.AppendInt64(bytes, int64(k)) } return bytes, nil } // AsSlice returns the set as a slice. func (s Int64) AsSlice() []int64 { if s == nil { return nil } dst := make([]int64, 0, len(s)) for k := range s { dst = append(dst, k) } return dst } // DecodeMsg decodes the message from the reader. func (s *Int64) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(Int64, sz) } else { clear(dst) } for range sz { var k int64 k, err = reader.ReadInt64() if err != nil { return err } dst[int64(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *Int64) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(Int64, sz) } else { clear(dst) } for range sz { var k int64 k, bytes, err = msgp.ReadInt64Bytes(bytes) if err != nil { return nil, err } dst[int64(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s Int64) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.Int64Size return size } // Int64FromSlice creates a Int64 from a slice. func Int64FromSlice(s []int64) Int64 { if s == nil { return nil } dst := make(Int64, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // Int64Sorted is a set of int64s that will be stored as an array. // Elements are sorted and the order of elements is guaranteed. type Int64Sorted map[int64]struct{} // EncodeMsg encodes the message to the writer. func (s Int64Sorted) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } keys := make([]int64, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b int64) int { if a < b { return -1 } return 1 }) for _, k := range keys { err = writer.WriteInt64(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s Int64Sorted) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) keys := make([]int64, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b int64) int { if a < b { return -1 } return 1 }) for _, k := range keys { bytes = msgp.AppendInt64(bytes, k) } return bytes, nil } // AsSlice returns the set as a sorted slice. func (s Int64Sorted) AsSlice() []int64 { if s == nil { return nil } keys := make([]int64, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b int64) int { if a < b { return -1 } return 1 }) return keys } // DecodeMsg decodes the message from the reader. func (s *Int64Sorted) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(Int64Sorted, sz) } else { clear(dst) } for range sz { var k int64 k, err = reader.ReadInt64() if err != nil { return err } dst[int64(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *Int64Sorted) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(Int64Sorted, sz) } else { clear(dst) } for range sz { var k int64 k, bytes, err = msgp.ReadInt64Bytes(bytes) if err != nil { return nil, err } dst[int64(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s Int64Sorted) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.Int64Size return size } // Int64SortedFromSlice creates a Int64Sorted from a slice. func Int64SortedFromSlice(s []int64) Int64Sorted { if s == nil { return nil } dst := make(Int64Sorted, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // Uint64 is a set of uint64s that will be stored as an array. // Elements are not sorted and the order of elements is not guaranteed. type Uint64 map[uint64]struct{} // EncodeMsg encodes the message to the writer. func (s Uint64) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } for k := range s { err = writer.WriteUint64(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s Uint64) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) for k := range s { bytes = msgp.AppendUint64(bytes, uint64(k)) } return bytes, nil } // AsSlice returns the set as a slice. func (s Uint64) AsSlice() []uint64 { if s == nil { return nil } dst := make([]uint64, 0, len(s)) for k := range s { dst = append(dst, k) } return dst } // DecodeMsg decodes the message from the reader. func (s *Uint64) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(Uint64, sz) } else { clear(dst) } for range sz { var k uint64 k, err = reader.ReadUint64() if err != nil { return err } dst[uint64(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *Uint64) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(Uint64, sz) } else { clear(dst) } for range sz { var k uint64 k, bytes, err = msgp.ReadUint64Bytes(bytes) if err != nil { return nil, err } dst[uint64(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s Uint64) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.Uint64Size return size } // Uint64FromSlice creates a Uint64 from a slice. func Uint64FromSlice(s []uint64) Uint64 { if s == nil { return nil } dst := make(Uint64, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // Uint64Sorted is a set of uint64s that will be stored as an array. // Elements are sorted and the order of elements is guaranteed. type Uint64Sorted map[uint64]struct{} // EncodeMsg encodes the message to the writer. func (s Uint64Sorted) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } keys := make([]uint64, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b uint64) int { if a < b { return -1 } return 1 }) for _, k := range keys { err = writer.WriteUint64(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s Uint64Sorted) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) keys := make([]uint64, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b uint64) int { if a < b { return -1 } return 1 }) for _, k := range keys { bytes = msgp.AppendUint64(bytes, k) } return bytes, nil } // AsSlice returns the set as a sorted slice. func (s Uint64Sorted) AsSlice() []uint64 { if s == nil { return nil } keys := make([]uint64, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b uint64) int { if a < b { return -1 } return 1 }) return keys } // DecodeMsg decodes the message from the reader. func (s *Uint64Sorted) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(Uint64Sorted, sz) } else { clear(dst) } for range sz { var k uint64 k, err = reader.ReadUint64() if err != nil { return err } dst[uint64(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *Uint64Sorted) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(Uint64Sorted, sz) } else { clear(dst) } for range sz { var k uint64 k, bytes, err = msgp.ReadUint64Bytes(bytes) if err != nil { return nil, err } dst[uint64(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s Uint64Sorted) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.Uint64Size return size } // Uint64SortedFromSlice creates a Uint64Sorted from a slice. func Uint64SortedFromSlice(s []uint64) Uint64Sorted { if s == nil { return nil } dst := make(Uint64Sorted, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // Float64 is a set of float64s that will be stored as an array. // Elements are not sorted and the order of elements is not guaranteed. type Float64 map[float64]struct{} // EncodeMsg encodes the message to the writer. func (s Float64) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } for k := range s { err = writer.WriteFloat(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s Float64) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) for k := range s { bytes = msgp.AppendFloat(bytes, float64(k)) } return bytes, nil } // AsSlice returns the set as a slice. func (s Float64) AsSlice() []float64 { if s == nil { return nil } dst := make([]float64, 0, len(s)) for k := range s { dst = append(dst, k) } return dst } // DecodeMsg decodes the message from the reader. func (s *Float64) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(Float64, sz) } else { clear(dst) } for range sz { var k float64 k, err = reader.ReadFloat64() if err != nil { return err } dst[float64(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *Float64) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(Float64, sz) } else { clear(dst) } for range sz { var k float64 k, bytes, err = msgp.ReadFloat64Bytes(bytes) if err != nil { return nil, err } dst[float64(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s Float64) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.Float64Size return size } // Float64FromSlice creates a Float64 from a slice. func Float64FromSlice(s []float64) Float64 { if s == nil { return nil } dst := make(Float64, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // Float64Sorted is a set of float64s that will be stored as an array. // Elements are sorted and the order of elements is guaranteed. type Float64Sorted map[float64]struct{} // EncodeMsg encodes the message to the writer. func (s Float64Sorted) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } keys := make([]float64, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b float64) int { if a < b { return -1 } return 1 }) for _, k := range keys { err = writer.WriteFloat(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s Float64Sorted) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) keys := make([]float64, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b float64) int { if a < b { return -1 } return 1 }) for _, k := range keys { bytes = msgp.AppendFloat(bytes, k) } return bytes, nil } // AsSlice returns the set as a sorted slice. func (s Float64Sorted) AsSlice() []float64 { if s == nil { return nil } keys := make([]float64, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b float64) int { if a < b { return -1 } return 1 }) return keys } // DecodeMsg decodes the message from the reader. func (s *Float64Sorted) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(Float64Sorted, sz) } else { clear(dst) } for range sz { var k float64 k, err = reader.ReadFloat64() if err != nil { return err } dst[float64(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *Float64Sorted) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(Float64Sorted, sz) } else { clear(dst) } for range sz { var k float64 k, bytes, err = msgp.ReadFloat64Bytes(bytes) if err != nil { return nil, err } dst[float64(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s Float64Sorted) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.Float64Size return size } // Float64SortedFromSlice creates a Float64Sorted from a slice. func Float64SortedFromSlice(s []float64) Float64Sorted { if s == nil { return nil } dst := make(Float64Sorted, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // Float32 is a set of float32s that will be stored as an array. // Elements are not sorted and the order of elements is not guaranteed. type Float32 map[float32]struct{} // EncodeMsg encodes the message to the writer. func (s Float32) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } for k := range s { err = writer.WriteFloat32(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s Float32) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) for k := range s { bytes = msgp.AppendFloat32(bytes, float32(k)) } return bytes, nil } // AsSlice returns the set as a slice. func (s Float32) AsSlice() []float32 { if s == nil { return nil } dst := make([]float32, 0, len(s)) for k := range s { dst = append(dst, k) } return dst } // DecodeMsg decodes the message from the reader. func (s *Float32) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(Float32, sz) } else { clear(dst) } for range sz { var k float32 k, err = reader.ReadFloat32() if err != nil { return err } dst[float32(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *Float32) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(Float32, sz) } else { clear(dst) } for range sz { var k float32 k, bytes, err = msgp.ReadFloat32Bytes(bytes) if err != nil { return nil, err } dst[float32(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s Float32) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.Float32Size return size } // Float32FromSlice creates a Float32 from a slice. func Float32FromSlice(s []float32) Float32 { if s == nil { return nil } dst := make(Float32, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } // Float32Sorted is a set of float32s that will be stored as an array. // Elements are sorted and the order of elements is guaranteed. type Float32Sorted map[float32]struct{} // EncodeMsg encodes the message to the writer. func (s Float32Sorted) EncodeMsg(writer *msgp.Writer) error { if s == nil { return writer.WriteNil() } err := writer.WriteArrayHeader(uint32(len(s))) if err != nil { return err } keys := make([]float32, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b float32) int { if a < b { return -1 } return 1 }) for _, k := range keys { err = writer.WriteFloat32(k) if err != nil { return err } } return nil } // MarshalMsg encodes the message to the bytes. func (s Float32Sorted) MarshalMsg(bytes []byte) ([]byte, error) { if s == nil { return msgp.AppendNil(bytes), nil } if len(s) == 0 { return msgp.AppendArrayHeader(bytes, 0), nil } bytes = ensure(bytes, s.Msgsize()) bytes = msgp.AppendArrayHeader(bytes, uint32(len(s))) keys := make([]float32, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b float32) int { if a < b { return -1 } return 1 }) for _, k := range keys { bytes = msgp.AppendFloat32(bytes, k) } return bytes, nil } // AsSlice returns the set as a sorted slice. func (s Float32Sorted) AsSlice() []float32 { if s == nil { return nil } keys := make([]float32, 0, len(s)) for k := range s { keys = append(keys, k) } slices.SortFunc(keys, func(a, b float32) int { if a < b { return -1 } return 1 }) return keys } // DecodeMsg decodes the message from the reader. func (s *Float32Sorted) DecodeMsg(reader *msgp.Reader) error { if reader.IsNil() { *s = nil return reader.Skip() } sz, err := reader.ReadArrayHeader() if err != nil { return err } dst := *s if dst == nil { dst = make(Float32Sorted, sz) } else { clear(dst) } for range sz { var k float32 k, err = reader.ReadFloat32() if err != nil { return err } dst[float32(k)] = struct{}{} } *s = dst return nil } // UnmarshalMsg decodes the message from the bytes. func (s *Float32Sorted) UnmarshalMsg(bytes []byte) ([]byte, error) { if msgp.IsNil(bytes) { *s = nil return bytes[msgp.NilSize:], nil } // Read the array header sz, bytes, err := msgp.ReadArrayHeaderBytes(bytes) if err != nil { return nil, err } dst := *s if dst == nil { dst = make(Float32Sorted, sz) } else { clear(dst) } for range sz { var k float32 k, bytes, err = msgp.ReadFloat32Bytes(bytes) if err != nil { return nil, err } dst[float32(k)] = struct{}{} } *s = dst return bytes, nil } // Msgsize returns the maximum size of the message. func (s Float32Sorted) Msgsize() int { if s == nil { return msgp.NilSize } size := msgp.ArrayHeaderSize size += len(s) * msgp.Float32Size return size } // Float32SortedFromSlice creates a Float32Sorted from a slice. func Float32SortedFromSlice(s []float32) Float32Sorted { if s == nil { return nil } dst := make(Float32Sorted, len(s)) for _, v := range s { dst[v] = struct{}{} } return dst } msgp-1.6.1/msgp/setof/generated_test.go000066400000000000000000005663061511433505400201200ustar00rootroot00000000000000// Code generated by ./gen/main.go. DO NOT EDIT. package setof import ( "bytes" "fmt" "testing" "github.com/tinylib/msgp/msgp" ) func TestString_RoundTrip(t *testing.T) { set := make(String) set["val0"] = struct{}{} set["val1"] = struct{}{} set["val2"] = struct{}{} set["val3"] = struct{}{} set["val4"] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded String err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled String _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestString_AsSlice(t *testing.T) { set := make(String) set["val0"] = struct{}{} set["val1"] = struct{}{} set["val2"] = struct{}{} set["val3"] = struct{}{} set["val4"] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[string]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestString_FromSlice(t *testing.T) { slice := []string{"val0", "val1", "val2", "val3", "val4"} set := StringFromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestString_NilHandling(t *testing.T) { var nilSet String // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded String err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled String _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := StringFromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestString_EmptySet(t *testing.T) { set := make(String) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded String err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled String _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func TestStringSorted_RoundTrip(t *testing.T) { set := make(StringSorted) set["val0"] = struct{}{} set["val1"] = struct{}{} set["val2"] = struct{}{} set["val3"] = struct{}{} set["val4"] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded StringSorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled StringSorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestStringSorted_AsSlice(t *testing.T) { set := make(StringSorted) set["val0"] = struct{}{} set["val1"] = struct{}{} set["val2"] = struct{}{} set["val3"] = struct{}{} set["val4"] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[string]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestStringSorted_FromSlice(t *testing.T) { slice := []string{"val0", "val1", "val2", "val3", "val4"} set := StringSortedFromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestStringSorted_NilHandling(t *testing.T) { var nilSet StringSorted // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded StringSorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled StringSorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := StringSortedFromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestStringSorted_EmptySet(t *testing.T) { set := make(StringSorted) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded StringSorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled StringSorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func BenchmarkString_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(String) for i := 0; i < size; i++ { set[fmt.Sprintf("val%d", i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkString_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(String) for i := 0; i < size; i++ { set[fmt.Sprintf("val%d", i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded String decoded.DecodeMsg(reader) } }) } } func BenchmarkString_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(String) for i := 0; i < size; i++ { set[fmt.Sprintf("val%d", i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkString_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(String) for i := 0; i < size; i++ { set[fmt.Sprintf("val%d", i)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded String _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkString_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(String) for i := 0; i < size; i++ { set[fmt.Sprintf("val%d", i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkString_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]string, size) for i := 0; i < size; i++ { slice[i] = fmt.Sprintf("val%d", i) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = StringFromSlice(slice) } }) } } func BenchmarkStringSorted_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(StringSorted) for i := 0; i < size; i++ { set[fmt.Sprintf("val%d", i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkStringSorted_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(StringSorted) for i := 0; i < size; i++ { set[fmt.Sprintf("val%d", i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded StringSorted decoded.DecodeMsg(reader) } }) } } func BenchmarkStringSorted_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(StringSorted) for i := 0; i < size; i++ { set[fmt.Sprintf("val%d", i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkStringSorted_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(StringSorted) for i := 0; i < size; i++ { set[fmt.Sprintf("val%d", i)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded StringSorted _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkStringSorted_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(StringSorted) for i := 0; i < size; i++ { set[fmt.Sprintf("val%d", i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkStringSorted_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]string, size) for i := 0; i < size; i++ { slice[i] = fmt.Sprintf("val%d", i) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = StringSortedFromSlice(slice) } }) } } func TestInt_RoundTrip(t *testing.T) { set := make(Int) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded Int err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled Int _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestInt_AsSlice(t *testing.T) { set := make(Int) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[int]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestInt_FromSlice(t *testing.T) { slice := []int{0, 1, 2, 3, 4} set := IntFromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestInt_NilHandling(t *testing.T) { var nilSet Int // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded Int err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled Int _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := IntFromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestInt_EmptySet(t *testing.T) { set := make(Int) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded Int err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled Int _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func TestIntSorted_RoundTrip(t *testing.T) { set := make(IntSorted) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded IntSorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled IntSorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestIntSorted_AsSlice(t *testing.T) { set := make(IntSorted) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[int]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestIntSorted_FromSlice(t *testing.T) { slice := []int{0, 1, 2, 3, 4} set := IntSortedFromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestIntSorted_NilHandling(t *testing.T) { var nilSet IntSorted // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded IntSorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled IntSorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := IntSortedFromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestIntSorted_EmptySet(t *testing.T) { set := make(IntSorted) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded IntSorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled IntSorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func BenchmarkInt_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int) for i := 0; i < size; i++ { set[int(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkInt_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int) for i := 0; i < size; i++ { set[int(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded Int decoded.DecodeMsg(reader) } }) } } func BenchmarkInt_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int) for i := 0; i < size; i++ { set[int(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkInt_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int) for i := 0; i < size; i++ { set[int(i)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded Int _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkInt_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int) for i := 0; i < size; i++ { set[int(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkInt_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]int, size) for i := 0; i < size; i++ { slice[i] = int(i) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = IntFromSlice(slice) } }) } } func BenchmarkIntSorted_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(IntSorted) for i := 0; i < size; i++ { set[int(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkIntSorted_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(IntSorted) for i := 0; i < size; i++ { set[int(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded IntSorted decoded.DecodeMsg(reader) } }) } } func BenchmarkIntSorted_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(IntSorted) for i := 0; i < size; i++ { set[int(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkIntSorted_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(IntSorted) for i := 0; i < size; i++ { set[int(i)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded IntSorted _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkIntSorted_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(IntSorted) for i := 0; i < size; i++ { set[int(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkIntSorted_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]int, size) for i := 0; i < size; i++ { slice[i] = int(i) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = IntSortedFromSlice(slice) } }) } } func TestUint_RoundTrip(t *testing.T) { set := make(Uint) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded Uint err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled Uint _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestUint_AsSlice(t *testing.T) { set := make(Uint) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[uint]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestUint_FromSlice(t *testing.T) { slice := []uint{0, 1, 2, 3, 4} set := UintFromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestUint_NilHandling(t *testing.T) { var nilSet Uint // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded Uint err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled Uint _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := UintFromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestUint_EmptySet(t *testing.T) { set := make(Uint) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded Uint err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled Uint _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func TestUintSorted_RoundTrip(t *testing.T) { set := make(UintSorted) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded UintSorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled UintSorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestUintSorted_AsSlice(t *testing.T) { set := make(UintSorted) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[uint]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestUintSorted_FromSlice(t *testing.T) { slice := []uint{0, 1, 2, 3, 4} set := UintSortedFromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestUintSorted_NilHandling(t *testing.T) { var nilSet UintSorted // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded UintSorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled UintSorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := UintSortedFromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestUintSorted_EmptySet(t *testing.T) { set := make(UintSorted) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded UintSorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled UintSorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func BenchmarkUint_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint) for i := 0; i < size; i++ { set[uint(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkUint_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint) for i := 0; i < size; i++ { set[uint(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded Uint decoded.DecodeMsg(reader) } }) } } func BenchmarkUint_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint) for i := 0; i < size; i++ { set[uint(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkUint_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint) for i := 0; i < size; i++ { set[uint(i)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded Uint _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkUint_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint) for i := 0; i < size; i++ { set[uint(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkUint_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]uint, size) for i := 0; i < size; i++ { slice[i] = uint(i) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = UintFromSlice(slice) } }) } } func BenchmarkUintSorted_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(UintSorted) for i := 0; i < size; i++ { set[uint(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkUintSorted_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(UintSorted) for i := 0; i < size; i++ { set[uint(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded UintSorted decoded.DecodeMsg(reader) } }) } } func BenchmarkUintSorted_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(UintSorted) for i := 0; i < size; i++ { set[uint(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkUintSorted_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(UintSorted) for i := 0; i < size; i++ { set[uint(i)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded UintSorted _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkUintSorted_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(UintSorted) for i := 0; i < size; i++ { set[uint(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkUintSorted_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]uint, size) for i := 0; i < size; i++ { slice[i] = uint(i) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = UintSortedFromSlice(slice) } }) } } func TestByte_RoundTrip(t *testing.T) { set := make(Byte) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded Byte err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled Byte _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestByte_AsSlice(t *testing.T) { set := make(Byte) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[byte]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestByte_FromSlice(t *testing.T) { slice := []byte{0, 1, 2, 3, 4} set := ByteFromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestByte_NilHandling(t *testing.T) { var nilSet Byte // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded Byte err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled Byte _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := ByteFromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestByte_EmptySet(t *testing.T) { set := make(Byte) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded Byte err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled Byte _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func TestByteSorted_RoundTrip(t *testing.T) { set := make(ByteSorted) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded ByteSorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled ByteSorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestByteSorted_AsSlice(t *testing.T) { set := make(ByteSorted) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[byte]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestByteSorted_FromSlice(t *testing.T) { slice := []byte{0, 1, 2, 3, 4} set := ByteSortedFromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestByteSorted_NilHandling(t *testing.T) { var nilSet ByteSorted // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded ByteSorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled ByteSorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := ByteSortedFromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestByteSorted_EmptySet(t *testing.T) { set := make(ByteSorted) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded ByteSorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled ByteSorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func BenchmarkByte_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Byte) for i := 0; i < size; i++ { set[byte(i%256)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkByte_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Byte) for i := 0; i < size; i++ { set[byte(i%256)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded Byte decoded.DecodeMsg(reader) } }) } } func BenchmarkByte_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Byte) for i := 0; i < size; i++ { set[byte(i%256)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkByte_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Byte) for i := 0; i < size; i++ { set[byte(i%256)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded Byte _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkByte_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Byte) for i := 0; i < size; i++ { set[byte(i%256)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkByte_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]byte, size) for i := 0; i < size; i++ { slice[i] = byte(i % 256) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = ByteFromSlice(slice) } }) } } func BenchmarkByteSorted_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(ByteSorted) for i := 0; i < size; i++ { set[byte(i%256)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkByteSorted_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(ByteSorted) for i := 0; i < size; i++ { set[byte(i%256)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded ByteSorted decoded.DecodeMsg(reader) } }) } } func BenchmarkByteSorted_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(ByteSorted) for i := 0; i < size; i++ { set[byte(i%256)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkByteSorted_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(ByteSorted) for i := 0; i < size; i++ { set[byte(i%256)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded ByteSorted _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkByteSorted_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(ByteSorted) for i := 0; i < size; i++ { set[byte(i%256)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkByteSorted_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]byte, size) for i := 0; i < size; i++ { slice[i] = byte(i % 256) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = ByteSortedFromSlice(slice) } }) } } func TestInt8_RoundTrip(t *testing.T) { set := make(Int8) set[-128] = struct{}{} set[-127] = struct{}{} set[-126] = struct{}{} set[-125] = struct{}{} set[-124] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded Int8 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled Int8 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestInt8_AsSlice(t *testing.T) { set := make(Int8) set[-128] = struct{}{} set[-127] = struct{}{} set[-126] = struct{}{} set[-125] = struct{}{} set[-124] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[int8]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestInt8_FromSlice(t *testing.T) { slice := []int8{-128, -127, -126, -125, -124} set := Int8FromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestInt8_NilHandling(t *testing.T) { var nilSet Int8 // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded Int8 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled Int8 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := Int8FromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestInt8_EmptySet(t *testing.T) { set := make(Int8) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded Int8 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled Int8 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func TestInt8Sorted_RoundTrip(t *testing.T) { set := make(Int8Sorted) set[-128] = struct{}{} set[-127] = struct{}{} set[-126] = struct{}{} set[-125] = struct{}{} set[-124] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded Int8Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled Int8Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestInt8Sorted_AsSlice(t *testing.T) { set := make(Int8Sorted) set[-128] = struct{}{} set[-127] = struct{}{} set[-126] = struct{}{} set[-125] = struct{}{} set[-124] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[int8]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestInt8Sorted_FromSlice(t *testing.T) { slice := []int8{-128, -127, -126, -125, -124} set := Int8SortedFromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestInt8Sorted_NilHandling(t *testing.T) { var nilSet Int8Sorted // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded Int8Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled Int8Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := Int8SortedFromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestInt8Sorted_EmptySet(t *testing.T) { set := make(Int8Sorted) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded Int8Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled Int8Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func BenchmarkInt8_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int8) for i := 0; i < size; i++ { set[int8((i%256)-128)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkInt8_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int8) for i := 0; i < size; i++ { set[int8((i%256)-128)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded Int8 decoded.DecodeMsg(reader) } }) } } func BenchmarkInt8_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int8) for i := 0; i < size; i++ { set[int8((i%256)-128)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkInt8_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int8) for i := 0; i < size; i++ { set[int8((i%256)-128)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded Int8 _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkInt8_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int8) for i := 0; i < size; i++ { set[int8((i%256)-128)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkInt8_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]int8, size) for i := 0; i < size; i++ { slice[i] = int8((i % 256) - 128) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = Int8FromSlice(slice) } }) } } func BenchmarkInt8Sorted_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int8Sorted) for i := 0; i < size; i++ { set[int8((i%256)-128)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkInt8Sorted_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int8Sorted) for i := 0; i < size; i++ { set[int8((i%256)-128)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded Int8Sorted decoded.DecodeMsg(reader) } }) } } func BenchmarkInt8Sorted_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int8Sorted) for i := 0; i < size; i++ { set[int8((i%256)-128)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkInt8Sorted_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int8Sorted) for i := 0; i < size; i++ { set[int8((i%256)-128)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded Int8Sorted _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkInt8Sorted_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int8Sorted) for i := 0; i < size; i++ { set[int8((i%256)-128)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkInt8Sorted_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]int8, size) for i := 0; i < size; i++ { slice[i] = int8((i % 256) - 128) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = Int8SortedFromSlice(slice) } }) } } func TestUint8_RoundTrip(t *testing.T) { set := make(Uint8) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded Uint8 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled Uint8 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestUint8_AsSlice(t *testing.T) { set := make(Uint8) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[uint8]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestUint8_FromSlice(t *testing.T) { slice := []uint8{0, 1, 2, 3, 4} set := Uint8FromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestUint8_NilHandling(t *testing.T) { var nilSet Uint8 // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded Uint8 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled Uint8 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := Uint8FromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestUint8_EmptySet(t *testing.T) { set := make(Uint8) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded Uint8 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled Uint8 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func TestUint8Sorted_RoundTrip(t *testing.T) { set := make(Uint8Sorted) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded Uint8Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled Uint8Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestUint8Sorted_AsSlice(t *testing.T) { set := make(Uint8Sorted) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[uint8]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestUint8Sorted_FromSlice(t *testing.T) { slice := []uint8{0, 1, 2, 3, 4} set := Uint8SortedFromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestUint8Sorted_NilHandling(t *testing.T) { var nilSet Uint8Sorted // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded Uint8Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled Uint8Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := Uint8SortedFromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestUint8Sorted_EmptySet(t *testing.T) { set := make(Uint8Sorted) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded Uint8Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled Uint8Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func BenchmarkUint8_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint8) for i := 0; i < size; i++ { set[uint8(i%256)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkUint8_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint8) for i := 0; i < size; i++ { set[uint8(i%256)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded Uint8 decoded.DecodeMsg(reader) } }) } } func BenchmarkUint8_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint8) for i := 0; i < size; i++ { set[uint8(i%256)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkUint8_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint8) for i := 0; i < size; i++ { set[uint8(i%256)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded Uint8 _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkUint8_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint8) for i := 0; i < size; i++ { set[uint8(i%256)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkUint8_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]uint8, size) for i := 0; i < size; i++ { slice[i] = uint8(i % 256) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = Uint8FromSlice(slice) } }) } } func BenchmarkUint8Sorted_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint8Sorted) for i := 0; i < size; i++ { set[uint8(i%256)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkUint8Sorted_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint8Sorted) for i := 0; i < size; i++ { set[uint8(i%256)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded Uint8Sorted decoded.DecodeMsg(reader) } }) } } func BenchmarkUint8Sorted_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint8Sorted) for i := 0; i < size; i++ { set[uint8(i%256)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkUint8Sorted_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint8Sorted) for i := 0; i < size; i++ { set[uint8(i%256)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded Uint8Sorted _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkUint8Sorted_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint8Sorted) for i := 0; i < size; i++ { set[uint8(i%256)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkUint8Sorted_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]uint8, size) for i := 0; i < size; i++ { slice[i] = uint8(i % 256) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = Uint8SortedFromSlice(slice) } }) } } func TestInt16_RoundTrip(t *testing.T) { set := make(Int16) set[-32768] = struct{}{} set[-32767] = struct{}{} set[-32766] = struct{}{} set[-32765] = struct{}{} set[-32764] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded Int16 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled Int16 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestInt16_AsSlice(t *testing.T) { set := make(Int16) set[-32768] = struct{}{} set[-32767] = struct{}{} set[-32766] = struct{}{} set[-32765] = struct{}{} set[-32764] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[int16]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestInt16_FromSlice(t *testing.T) { slice := []int16{-32768, -32767, -32766, -32765, -32764} set := Int16FromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestInt16_NilHandling(t *testing.T) { var nilSet Int16 // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded Int16 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled Int16 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := Int16FromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestInt16_EmptySet(t *testing.T) { set := make(Int16) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded Int16 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled Int16 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func TestInt16Sorted_RoundTrip(t *testing.T) { set := make(Int16Sorted) set[-32768] = struct{}{} set[-32767] = struct{}{} set[-32766] = struct{}{} set[-32765] = struct{}{} set[-32764] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded Int16Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled Int16Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestInt16Sorted_AsSlice(t *testing.T) { set := make(Int16Sorted) set[-32768] = struct{}{} set[-32767] = struct{}{} set[-32766] = struct{}{} set[-32765] = struct{}{} set[-32764] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[int16]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestInt16Sorted_FromSlice(t *testing.T) { slice := []int16{-32768, -32767, -32766, -32765, -32764} set := Int16SortedFromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestInt16Sorted_NilHandling(t *testing.T) { var nilSet Int16Sorted // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded Int16Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled Int16Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := Int16SortedFromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestInt16Sorted_EmptySet(t *testing.T) { set := make(Int16Sorted) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded Int16Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled Int16Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func BenchmarkInt16_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int16) for i := 0; i < size; i++ { set[int16((i%65536)-32768)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkInt16_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int16) for i := 0; i < size; i++ { set[int16((i%65536)-32768)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded Int16 decoded.DecodeMsg(reader) } }) } } func BenchmarkInt16_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int16) for i := 0; i < size; i++ { set[int16((i%65536)-32768)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkInt16_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int16) for i := 0; i < size; i++ { set[int16((i%65536)-32768)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded Int16 _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkInt16_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int16) for i := 0; i < size; i++ { set[int16((i%65536)-32768)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkInt16_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]int16, size) for i := 0; i < size; i++ { slice[i] = int16((i % 65536) - 32768) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = Int16FromSlice(slice) } }) } } func BenchmarkInt16Sorted_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int16Sorted) for i := 0; i < size; i++ { set[int16((i%65536)-32768)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkInt16Sorted_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int16Sorted) for i := 0; i < size; i++ { set[int16((i%65536)-32768)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded Int16Sorted decoded.DecodeMsg(reader) } }) } } func BenchmarkInt16Sorted_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int16Sorted) for i := 0; i < size; i++ { set[int16((i%65536)-32768)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkInt16Sorted_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int16Sorted) for i := 0; i < size; i++ { set[int16((i%65536)-32768)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded Int16Sorted _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkInt16Sorted_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int16Sorted) for i := 0; i < size; i++ { set[int16((i%65536)-32768)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkInt16Sorted_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]int16, size) for i := 0; i < size; i++ { slice[i] = int16((i % 65536) - 32768) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = Int16SortedFromSlice(slice) } }) } } func TestUint16_RoundTrip(t *testing.T) { set := make(Uint16) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded Uint16 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled Uint16 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestUint16_AsSlice(t *testing.T) { set := make(Uint16) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[uint16]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestUint16_FromSlice(t *testing.T) { slice := []uint16{0, 1, 2, 3, 4} set := Uint16FromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestUint16_NilHandling(t *testing.T) { var nilSet Uint16 // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded Uint16 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled Uint16 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := Uint16FromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestUint16_EmptySet(t *testing.T) { set := make(Uint16) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded Uint16 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled Uint16 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func TestUint16Sorted_RoundTrip(t *testing.T) { set := make(Uint16Sorted) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded Uint16Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled Uint16Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestUint16Sorted_AsSlice(t *testing.T) { set := make(Uint16Sorted) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[uint16]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestUint16Sorted_FromSlice(t *testing.T) { slice := []uint16{0, 1, 2, 3, 4} set := Uint16SortedFromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestUint16Sorted_NilHandling(t *testing.T) { var nilSet Uint16Sorted // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded Uint16Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled Uint16Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := Uint16SortedFromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestUint16Sorted_EmptySet(t *testing.T) { set := make(Uint16Sorted) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded Uint16Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled Uint16Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func BenchmarkUint16_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint16) for i := 0; i < size; i++ { set[uint16(i%65536)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkUint16_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint16) for i := 0; i < size; i++ { set[uint16(i%65536)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded Uint16 decoded.DecodeMsg(reader) } }) } } func BenchmarkUint16_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint16) for i := 0; i < size; i++ { set[uint16(i%65536)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkUint16_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint16) for i := 0; i < size; i++ { set[uint16(i%65536)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded Uint16 _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkUint16_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint16) for i := 0; i < size; i++ { set[uint16(i%65536)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkUint16_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]uint16, size) for i := 0; i < size; i++ { slice[i] = uint16(i % 65536) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = Uint16FromSlice(slice) } }) } } func BenchmarkUint16Sorted_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint16Sorted) for i := 0; i < size; i++ { set[uint16(i%65536)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkUint16Sorted_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint16Sorted) for i := 0; i < size; i++ { set[uint16(i%65536)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded Uint16Sorted decoded.DecodeMsg(reader) } }) } } func BenchmarkUint16Sorted_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint16Sorted) for i := 0; i < size; i++ { set[uint16(i%65536)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkUint16Sorted_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint16Sorted) for i := 0; i < size; i++ { set[uint16(i%65536)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded Uint16Sorted _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkUint16Sorted_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint16Sorted) for i := 0; i < size; i++ { set[uint16(i%65536)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkUint16Sorted_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]uint16, size) for i := 0; i < size; i++ { slice[i] = uint16(i % 65536) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = Uint16SortedFromSlice(slice) } }) } } func TestInt32_RoundTrip(t *testing.T) { set := make(Int32) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded Int32 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled Int32 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestInt32_AsSlice(t *testing.T) { set := make(Int32) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[int32]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestInt32_FromSlice(t *testing.T) { slice := []int32{0, 1, 2, 3, 4} set := Int32FromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestInt32_NilHandling(t *testing.T) { var nilSet Int32 // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded Int32 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled Int32 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := Int32FromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestInt32_EmptySet(t *testing.T) { set := make(Int32) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded Int32 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled Int32 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func TestInt32Sorted_RoundTrip(t *testing.T) { set := make(Int32Sorted) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded Int32Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled Int32Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestInt32Sorted_AsSlice(t *testing.T) { set := make(Int32Sorted) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[int32]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestInt32Sorted_FromSlice(t *testing.T) { slice := []int32{0, 1, 2, 3, 4} set := Int32SortedFromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestInt32Sorted_NilHandling(t *testing.T) { var nilSet Int32Sorted // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded Int32Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled Int32Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := Int32SortedFromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestInt32Sorted_EmptySet(t *testing.T) { set := make(Int32Sorted) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded Int32Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled Int32Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func BenchmarkInt32_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int32) for i := 0; i < size; i++ { set[int32(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkInt32_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int32) for i := 0; i < size; i++ { set[int32(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded Int32 decoded.DecodeMsg(reader) } }) } } func BenchmarkInt32_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int32) for i := 0; i < size; i++ { set[int32(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkInt32_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int32) for i := 0; i < size; i++ { set[int32(i)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded Int32 _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkInt32_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int32) for i := 0; i < size; i++ { set[int32(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkInt32_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]int32, size) for i := 0; i < size; i++ { slice[i] = int32(i) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = Int32FromSlice(slice) } }) } } func BenchmarkInt32Sorted_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int32Sorted) for i := 0; i < size; i++ { set[int32(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkInt32Sorted_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int32Sorted) for i := 0; i < size; i++ { set[int32(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded Int32Sorted decoded.DecodeMsg(reader) } }) } } func BenchmarkInt32Sorted_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int32Sorted) for i := 0; i < size; i++ { set[int32(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkInt32Sorted_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int32Sorted) for i := 0; i < size; i++ { set[int32(i)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded Int32Sorted _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkInt32Sorted_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int32Sorted) for i := 0; i < size; i++ { set[int32(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkInt32Sorted_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]int32, size) for i := 0; i < size; i++ { slice[i] = int32(i) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = Int32SortedFromSlice(slice) } }) } } func TestUint32_RoundTrip(t *testing.T) { set := make(Uint32) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded Uint32 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled Uint32 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestUint32_AsSlice(t *testing.T) { set := make(Uint32) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[uint32]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestUint32_FromSlice(t *testing.T) { slice := []uint32{0, 1, 2, 3, 4} set := Uint32FromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestUint32_NilHandling(t *testing.T) { var nilSet Uint32 // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded Uint32 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled Uint32 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := Uint32FromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestUint32_EmptySet(t *testing.T) { set := make(Uint32) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded Uint32 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled Uint32 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func TestUint32Sorted_RoundTrip(t *testing.T) { set := make(Uint32Sorted) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded Uint32Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled Uint32Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestUint32Sorted_AsSlice(t *testing.T) { set := make(Uint32Sorted) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[uint32]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestUint32Sorted_FromSlice(t *testing.T) { slice := []uint32{0, 1, 2, 3, 4} set := Uint32SortedFromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestUint32Sorted_NilHandling(t *testing.T) { var nilSet Uint32Sorted // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded Uint32Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled Uint32Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := Uint32SortedFromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestUint32Sorted_EmptySet(t *testing.T) { set := make(Uint32Sorted) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded Uint32Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled Uint32Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func BenchmarkUint32_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint32) for i := 0; i < size; i++ { set[uint32(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkUint32_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint32) for i := 0; i < size; i++ { set[uint32(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded Uint32 decoded.DecodeMsg(reader) } }) } } func BenchmarkUint32_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint32) for i := 0; i < size; i++ { set[uint32(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkUint32_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint32) for i := 0; i < size; i++ { set[uint32(i)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded Uint32 _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkUint32_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint32) for i := 0; i < size; i++ { set[uint32(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkUint32_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]uint32, size) for i := 0; i < size; i++ { slice[i] = uint32(i) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = Uint32FromSlice(slice) } }) } } func BenchmarkUint32Sorted_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint32Sorted) for i := 0; i < size; i++ { set[uint32(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkUint32Sorted_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint32Sorted) for i := 0; i < size; i++ { set[uint32(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded Uint32Sorted decoded.DecodeMsg(reader) } }) } } func BenchmarkUint32Sorted_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint32Sorted) for i := 0; i < size; i++ { set[uint32(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkUint32Sorted_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint32Sorted) for i := 0; i < size; i++ { set[uint32(i)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded Uint32Sorted _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkUint32Sorted_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint32Sorted) for i := 0; i < size; i++ { set[uint32(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkUint32Sorted_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]uint32, size) for i := 0; i < size; i++ { slice[i] = uint32(i) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = Uint32SortedFromSlice(slice) } }) } } func TestInt64_RoundTrip(t *testing.T) { set := make(Int64) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded Int64 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled Int64 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestInt64_AsSlice(t *testing.T) { set := make(Int64) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[int64]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestInt64_FromSlice(t *testing.T) { slice := []int64{0, 1, 2, 3, 4} set := Int64FromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestInt64_NilHandling(t *testing.T) { var nilSet Int64 // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded Int64 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled Int64 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := Int64FromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestInt64_EmptySet(t *testing.T) { set := make(Int64) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded Int64 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled Int64 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func TestInt64Sorted_RoundTrip(t *testing.T) { set := make(Int64Sorted) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded Int64Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled Int64Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestInt64Sorted_AsSlice(t *testing.T) { set := make(Int64Sorted) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[int64]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestInt64Sorted_FromSlice(t *testing.T) { slice := []int64{0, 1, 2, 3, 4} set := Int64SortedFromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestInt64Sorted_NilHandling(t *testing.T) { var nilSet Int64Sorted // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded Int64Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled Int64Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := Int64SortedFromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestInt64Sorted_EmptySet(t *testing.T) { set := make(Int64Sorted) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded Int64Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled Int64Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func BenchmarkInt64_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int64) for i := 0; i < size; i++ { set[int64(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkInt64_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int64) for i := 0; i < size; i++ { set[int64(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded Int64 decoded.DecodeMsg(reader) } }) } } func BenchmarkInt64_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int64) for i := 0; i < size; i++ { set[int64(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkInt64_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int64) for i := 0; i < size; i++ { set[int64(i)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded Int64 _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkInt64_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int64) for i := 0; i < size; i++ { set[int64(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkInt64_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]int64, size) for i := 0; i < size; i++ { slice[i] = int64(i) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = Int64FromSlice(slice) } }) } } func BenchmarkInt64Sorted_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int64Sorted) for i := 0; i < size; i++ { set[int64(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkInt64Sorted_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int64Sorted) for i := 0; i < size; i++ { set[int64(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded Int64Sorted decoded.DecodeMsg(reader) } }) } } func BenchmarkInt64Sorted_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int64Sorted) for i := 0; i < size; i++ { set[int64(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkInt64Sorted_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int64Sorted) for i := 0; i < size; i++ { set[int64(i)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded Int64Sorted _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkInt64Sorted_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Int64Sorted) for i := 0; i < size; i++ { set[int64(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkInt64Sorted_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]int64, size) for i := 0; i < size; i++ { slice[i] = int64(i) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = Int64SortedFromSlice(slice) } }) } } func TestUint64_RoundTrip(t *testing.T) { set := make(Uint64) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded Uint64 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled Uint64 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestUint64_AsSlice(t *testing.T) { set := make(Uint64) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[uint64]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestUint64_FromSlice(t *testing.T) { slice := []uint64{0, 1, 2, 3, 4} set := Uint64FromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestUint64_NilHandling(t *testing.T) { var nilSet Uint64 // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded Uint64 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled Uint64 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := Uint64FromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestUint64_EmptySet(t *testing.T) { set := make(Uint64) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded Uint64 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled Uint64 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func TestUint64Sorted_RoundTrip(t *testing.T) { set := make(Uint64Sorted) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded Uint64Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled Uint64Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestUint64Sorted_AsSlice(t *testing.T) { set := make(Uint64Sorted) set[0] = struct{}{} set[1] = struct{}{} set[2] = struct{}{} set[3] = struct{}{} set[4] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[uint64]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestUint64Sorted_FromSlice(t *testing.T) { slice := []uint64{0, 1, 2, 3, 4} set := Uint64SortedFromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestUint64Sorted_NilHandling(t *testing.T) { var nilSet Uint64Sorted // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded Uint64Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled Uint64Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := Uint64SortedFromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestUint64Sorted_EmptySet(t *testing.T) { set := make(Uint64Sorted) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded Uint64Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled Uint64Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func BenchmarkUint64_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint64) for i := 0; i < size; i++ { set[uint64(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkUint64_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint64) for i := 0; i < size; i++ { set[uint64(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded Uint64 decoded.DecodeMsg(reader) } }) } } func BenchmarkUint64_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint64) for i := 0; i < size; i++ { set[uint64(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkUint64_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint64) for i := 0; i < size; i++ { set[uint64(i)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded Uint64 _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkUint64_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint64) for i := 0; i < size; i++ { set[uint64(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkUint64_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]uint64, size) for i := 0; i < size; i++ { slice[i] = uint64(i) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = Uint64FromSlice(slice) } }) } } func BenchmarkUint64Sorted_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint64Sorted) for i := 0; i < size; i++ { set[uint64(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkUint64Sorted_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint64Sorted) for i := 0; i < size; i++ { set[uint64(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded Uint64Sorted decoded.DecodeMsg(reader) } }) } } func BenchmarkUint64Sorted_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint64Sorted) for i := 0; i < size; i++ { set[uint64(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkUint64Sorted_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint64Sorted) for i := 0; i < size; i++ { set[uint64(i)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded Uint64Sorted _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkUint64Sorted_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Uint64Sorted) for i := 0; i < size; i++ { set[uint64(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkUint64Sorted_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]uint64, size) for i := 0; i < size; i++ { slice[i] = uint64(i) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = Uint64SortedFromSlice(slice) } }) } } func TestFloat64_RoundTrip(t *testing.T) { set := make(Float64) set[0.0] = struct{}{} set[1.0] = struct{}{} set[2.0] = struct{}{} set[3.0] = struct{}{} set[4.0] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded Float64 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled Float64 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestFloat64_AsSlice(t *testing.T) { set := make(Float64) set[0.0] = struct{}{} set[1.0] = struct{}{} set[2.0] = struct{}{} set[3.0] = struct{}{} set[4.0] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[float64]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestFloat64_FromSlice(t *testing.T) { slice := []float64{0.0, 1.0, 2.0, 3.0, 4.0} set := Float64FromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestFloat64_NilHandling(t *testing.T) { var nilSet Float64 // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded Float64 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled Float64 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := Float64FromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestFloat64_EmptySet(t *testing.T) { set := make(Float64) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded Float64 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled Float64 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func TestFloat64Sorted_RoundTrip(t *testing.T) { set := make(Float64Sorted) set[0.0] = struct{}{} set[1.0] = struct{}{} set[2.0] = struct{}{} set[3.0] = struct{}{} set[4.0] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded Float64Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled Float64Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestFloat64Sorted_AsSlice(t *testing.T) { set := make(Float64Sorted) set[0.0] = struct{}{} set[1.0] = struct{}{} set[2.0] = struct{}{} set[3.0] = struct{}{} set[4.0] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[float64]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestFloat64Sorted_FromSlice(t *testing.T) { slice := []float64{0.0, 1.0, 2.0, 3.0, 4.0} set := Float64SortedFromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestFloat64Sorted_NilHandling(t *testing.T) { var nilSet Float64Sorted // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded Float64Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled Float64Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := Float64SortedFromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestFloat64Sorted_EmptySet(t *testing.T) { set := make(Float64Sorted) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded Float64Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled Float64Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func BenchmarkFloat64_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Float64) for i := 0; i < size; i++ { set[float64(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkFloat64_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Float64) for i := 0; i < size; i++ { set[float64(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded Float64 decoded.DecodeMsg(reader) } }) } } func BenchmarkFloat64_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Float64) for i := 0; i < size; i++ { set[float64(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkFloat64_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Float64) for i := 0; i < size; i++ { set[float64(i)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded Float64 _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkFloat64_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Float64) for i := 0; i < size; i++ { set[float64(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkFloat64_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]float64, size) for i := 0; i < size; i++ { slice[i] = float64(i) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = Float64FromSlice(slice) } }) } } func BenchmarkFloat64Sorted_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Float64Sorted) for i := 0; i < size; i++ { set[float64(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkFloat64Sorted_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Float64Sorted) for i := 0; i < size; i++ { set[float64(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded Float64Sorted decoded.DecodeMsg(reader) } }) } } func BenchmarkFloat64Sorted_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Float64Sorted) for i := 0; i < size; i++ { set[float64(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkFloat64Sorted_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Float64Sorted) for i := 0; i < size; i++ { set[float64(i)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded Float64Sorted _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkFloat64Sorted_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Float64Sorted) for i := 0; i < size; i++ { set[float64(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkFloat64Sorted_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]float64, size) for i := 0; i < size; i++ { slice[i] = float64(i) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = Float64SortedFromSlice(slice) } }) } } func TestFloat32_RoundTrip(t *testing.T) { set := make(Float32) set[0.0] = struct{}{} set[1.0] = struct{}{} set[2.0] = struct{}{} set[3.0] = struct{}{} set[4.0] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded Float32 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled Float32 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestFloat32_AsSlice(t *testing.T) { set := make(Float32) set[0.0] = struct{}{} set[1.0] = struct{}{} set[2.0] = struct{}{} set[3.0] = struct{}{} set[4.0] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[float32]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestFloat32_FromSlice(t *testing.T) { slice := []float32{0.0, 1.0, 2.0, 3.0, 4.0} set := Float32FromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestFloat32_NilHandling(t *testing.T) { var nilSet Float32 // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded Float32 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled Float32 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := Float32FromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestFloat32_EmptySet(t *testing.T) { set := make(Float32) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded Float32 err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled Float32 _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func TestFloat32Sorted_RoundTrip(t *testing.T) { set := make(Float32Sorted) set[0.0] = struct{}{} set[1.0] = struct{}{} set[2.0] = struct{}{} set[3.0] = struct{}{} set[4.0] = struct{}{} // Test EncodeMsg/DecodeMsg var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed: %v", err) } writer.Flush() reader := msgp.NewReader(&buf) var decoded Float32Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed: %v", err) } if len(set) != len(decoded) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(decoded)) } for k := range set { if _, ok := decoded[k]; !ok { t.Fatalf("missing key: %v", k) } } // Test MarshalMsg/UnmarshalMsg data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed: %v", err) } var unmarshaled Float32Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed: %v", err) } if len(set) != len(unmarshaled) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(unmarshaled)) } for k := range set { if _, ok := unmarshaled[k]; !ok { t.Fatalf("missing key: %v", k) } } } func TestFloat32Sorted_AsSlice(t *testing.T) { set := make(Float32Sorted) set[0.0] = struct{}{} set[1.0] = struct{}{} set[2.0] = struct{}{} set[3.0] = struct{}{} set[4.0] = struct{}{} slice := set.AsSlice() if len(slice) != len(set) { t.Fatalf("length mismatch: expected %d, got %d", len(set), len(slice)) } found := make(map[float32]bool) for _, v := range slice { found[v] = true } for k := range set { if !found[k] { t.Fatalf("missing key in slice: %v", k) } } } func TestFloat32Sorted_FromSlice(t *testing.T) { slice := []float32{0.0, 1.0, 2.0, 3.0, 4.0} set := Float32SortedFromSlice(slice) if len(set) != len(slice) { t.Fatalf("length mismatch: expected %d, got %d", len(slice), len(set)) } for _, v := range slice { if _, ok := set[v]; !ok { t.Fatalf("missing key: %v", v) } } } func TestFloat32Sorted_NilHandling(t *testing.T) { var nilSet Float32Sorted // Test nil encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := nilSet.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for nil: %v", err) } writer.Flush() // Test nil decoding reader := msgp.NewReader(&buf) var decoded Float32Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for nil: %v", err) } if decoded != nil { t.Fatal("expected nil, got non-nil") } // Test nil marshaling data, err := nilSet.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for nil: %v", err) } // Test nil unmarshaling var unmarshaled Float32Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for nil: %v", err) } if unmarshaled != nil { t.Fatal("expected nil, got non-nil") } // Test AsSlice on nil slice := nilSet.AsSlice() if slice != nil { t.Fatal("expected nil slice, got non-nil") } // Test FromSlice with nil fromNilSlice := Float32SortedFromSlice(nil) if fromNilSlice != nil { t.Fatal("expected nil from nil slice, got non-nil") } } func TestFloat32Sorted_EmptySet(t *testing.T) { set := make(Float32Sorted) // Test empty set encoding var buf bytes.Buffer writer := msgp.NewWriter(&buf) err := set.EncodeMsg(writer) if err != nil { t.Fatalf("EncodeMsg failed for empty: %v", err) } writer.Flush() // Test empty set decoding reader := msgp.NewReader(&buf) var decoded Float32Sorted err = decoded.DecodeMsg(reader) if err != nil { t.Fatalf("DecodeMsg failed for empty: %v", err) } if len(decoded) != 0 { t.Fatalf("expected empty set, got length %d", len(decoded)) } // Test empty set marshaling data, err := set.MarshalMsg(nil) if err != nil { t.Fatalf("MarshalMsg failed for empty: %v", err) } // Test empty set unmarshaling var unmarshaled Float32Sorted _, err = unmarshaled.UnmarshalMsg(data) if err != nil { t.Fatalf("UnmarshalMsg failed for empty: %v", err) } if len(unmarshaled) != 0 { t.Fatalf("expected empty set, got length %d", len(unmarshaled)) } } func BenchmarkFloat32_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Float32) for i := 0; i < size; i++ { set[float32(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkFloat32_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Float32) for i := 0; i < size; i++ { set[float32(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded Float32 decoded.DecodeMsg(reader) } }) } } func BenchmarkFloat32_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Float32) for i := 0; i < size; i++ { set[float32(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkFloat32_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Float32) for i := 0; i < size; i++ { set[float32(i)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded Float32 _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkFloat32_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Float32) for i := 0; i < size; i++ { set[float32(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkFloat32_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]float32, size) for i := 0; i < size; i++ { slice[i] = float32(i) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = Float32FromSlice(slice) } }) } } func BenchmarkFloat32Sorted_EncodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Float32Sorted) for i := 0; i < size; i++ { set[float32(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { buf.Reset() writer.Reset(&buf) set.EncodeMsg(writer) writer.Flush() } }) } } func BenchmarkFloat32Sorted_DecodeMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Float32Sorted) for i := 0; i < size; i++ { set[float32(i)] = struct{}{} } var buf bytes.Buffer writer := msgp.NewWriter(&buf) set.EncodeMsg(writer) writer.Flush() encoded := buf.Bytes() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { reader := msgp.NewReader(bytes.NewReader(encoded)) var decoded Float32Sorted decoded.DecodeMsg(reader) } }) } } func BenchmarkFloat32Sorted_MarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Float32Sorted) for i := 0; i < size; i++ { set[float32(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := set.MarshalMsg(nil) if err != nil { b.Fatal(err) } } }) } } func BenchmarkFloat32Sorted_UnmarshalMsg(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Float32Sorted) for i := 0; i < size; i++ { set[float32(i)] = struct{}{} } data, _ := set.MarshalMsg(nil) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { var decoded Float32Sorted _, err := decoded.UnmarshalMsg(data) if err != nil { b.Fatal(err) } } }) } } func BenchmarkFloat32Sorted_AsSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { set := make(Float32Sorted) for i := 0; i < size; i++ { set[float32(i)] = struct{}{} } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = set.AsSlice() } }) } } func BenchmarkFloat32Sorted_FromSlice(b *testing.B) { sizes := []int{10, 100, 1000} for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { slice := make([]float32, size) for i := 0; i < size; i++ { slice[i] = float32(i) } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { _ = Float32SortedFromSlice(slice) } }) } } msgp-1.6.1/msgp/setof/setof.go000066400000000000000000000006721511433505400162300ustar00rootroot00000000000000// Package setof allows serializing sets map[T]struct{} as arrays. // // Nil maps are preserved as a nil value on stream. // // A deterministic, sorted version is available, with slightly lower performance. package setof // ensure 'sz' extra bytes in 'b' can be appended without reallocating func ensure(b []byte, sz int) []byte { l := len(b) c := cap(b) if c-l < sz { o := make([]byte, l, l+sz) copy(o, b) return o } return b } msgp-1.6.1/msgp/size.go000066400000000000000000000021121511433505400147310ustar00rootroot00000000000000package msgp // The sizes provided // are the worst-case // encoded sizes for // each type. For variable- // length types ([]byte, string), // the total encoded size is // the prefix size plus the // length of the object. const ( Int64Size = 9 IntSize = Int64Size UintSize = Int64Size Int8Size = 2 Int16Size = 3 Int32Size = 5 Uint8Size = 2 ByteSize = Uint8Size Uint16Size = 3 Uint32Size = 5 Uint64Size = Int64Size Float64Size = 9 Float32Size = 5 Complex64Size = 10 Complex128Size = 18 DurationSize = Int64Size TimeSize = 15 BoolSize = 1 NilSize = 1 JSONNumberSize = Int64Size // Same as Float64Size MapHeaderSize = 5 ArrayHeaderSize = 5 BytesPrefixSize = 5 StringPrefixSize = 5 ExtensionPrefixSize = 6 // We cannot determine the exact size of the marshalled bytes, // so we assume 32 bytes BinaryMarshalerSize = BytesPrefixSize + 32 BinaryAppenderSize TextMarshalerBinSize TextAppenderBinSize TextMarshalerStringSize = StringPrefixSize + 32 TextAppenderStringSize ) msgp-1.6.1/msgp/testdata/000077500000000000000000000000001511433505400152455ustar00rootroot00000000000000msgp-1.6.1/msgp/testdata/FuzzCorpus.zip000066400000000000000000005224731511433505400201400ustar00rootroot00000000000000PKfZ?9-!c08511970c52cac3KW(I-.QH+R(3䊎M,IPHI000HN4&PKfZs&,X9cbd5ff1293cd584KW(I-.QH+R(3䊎M,IPH0@1y PPKfZYЏm0feb94310c45a168JW(I-.QH+R(3䊎M,IPHN4l4J$ 7܊A ^:?BwI/=2``f]bdmٝ:p o_);;\7ЛzOm2K gѨboGDFSe:#c{y)ê?@,7}gX'A'U-յ\&Μ%LDSB"iGUfmY3ibWepi4TL&?homݳM Z!<v4 V͠dLιFEDeA)Tf-[f5 %bnĪbw佡zkRpu,2\d2LI/%$C~]ܽ:zǃ1d[!ఔ.< ͐mz*oq5:6V |@r!`!B! !B! B!U L ӠIժPKfZ9*7e29a70040eadf33KW(I-.QH+R(3䊎M,IPHI00HNa (=JAne&PKfZ+E555071b7ee6c095bKW(I-.QH+R(3䊎M,IPHN00@01&PKfZ +I7828023fc4a65f53KW(I-.QH+R(3䊎M,IPƀ)Bfc@4PKfZqCw8Hafc9d0ac505ca452KW(I-.QH+R(3䊎M,IPHNrH402404qS M1W6%M.PK|fZ#.ecc2404de0eb317cKW(I-.QH+R(3䊎M,IPHN100ܴ0wPKcfZO1Ic5fefcce9c4ca6e3KW(I-.QH+R(3䊎M,IPHJ)520Qpr 4PKGfZwx(G173cafab5d73c1feKW(I-.QH+R(3䊎M,IPHN6 PPKCfZcNi(K468b2e60bf9cb387KW(I-.QH+R(3䊎M,IPL& [⑋4PK9fZg*03eb31eaf7130c9a7KW(I-.QH+R(3䊎M,IP4` t Gb PK4fZ}U)s838d3d47fdbd5112KW(I-.QH+R(3䊎M,IPHN100K+irPK*fZgOC617e3f62b9ef7b9fKW(I-.QH+R(3䊎M,IPHNR1WO4t4q@XȨҨrQF"QPKfZ tEf6fccf0c01bbc193JW(I-.QH+R(3䊎M,IPH13#"9 >Y]1 A@W0v1BB!m+}Ĺc8D|# ԧ!Vf.t4jc?sF iM\`YQOf?: Qb-:f Lz9pn PF2j%` [wU"P\z[ x%+)]ɇiA9=[<$l4 룈@{EC ԻC0A5R]3l7׾o =ԫ恳E v}rS4С5\nhͭ3 ]N!`0ɄٗtP9O_#]/ TI{--\3ngr6v9xI܍Q }ŴB4s0rR0C]gVͥvXM}Z=N/X_AD[ذE+;,hCQ獔ػGxB-N!R ]A_5Si{{4-`0 ҡ4|Ln-Jk],ݧCP񒘋kMV9b,4:H6,ҾfmOSBrQG5 4#GCT82F6n_Gݑ#8]XL.kH$Z1R99;p 2Aa*zGHBJ*;!/MncF.k5 4FS Yڶ925#!eu h՞õ+ =6^"jC\E7DۤܡB{aЌ=>X- .=ɩ2A<}|}CM4b10a112d1248680KW(I-.QH+R(3䊎M,IPHNae-ged`T2-@,m #JJC%M.PKfZX.7Y22ba144b431bb7bdKW(I-.QH+R(3䊎M,IPHT}kvLAAee J\PK eZA`**d2ba6fbf4985a14dgo test fuzz v1 []byte("\xcbE%x++\xd4x1") PKeZGix.Fcddc8d95827bca03KW(I-.QH+R(3䊎M,IPHJ2R##K$&s4PKeZPt#>6b04c9b62eb0046bKW(I-.QH+R(3䊎M,IPHI00HN1T&TX$96ȝDQ42ŀ0@d4<=LXjT D?z1ՔY'd۰+; jsKt<ɂxY ">BJ/n)uT&xwVIc swЛbˋ"g'؋ έ%G8J\PKeZYx'3799b0ecee7a25b0KW(I-.QH+R(3䊎M,IPHN100&PKeZ./F1e97fdf67b639878KW(I-.QH+R(3䊎M,IPHJ)52040p& [I PKeZ^44#30d6744f87e42339KW(I-.QH+R(3䊎M,IPHI00HNa GQzdJ\PKeZ82Cf3ac2ae146f29c91KW(I-.QH+R(3䊎M,IP0HL4 d J\PKeZdx185f27ef9d588f212KW(I-.QH+R(3䊎M,IPLH6óA$4 &PKeZ0#6e030f16df51afa1KW(I-.QH+R(3䊎M,IP0HPKeZeN6c047f1cd57a187cdJW(I-.QH+R(3䊎M,IPQa 㘊$pH kHLI PKkeZ͸bh3>ba1ea6b48d1a37c3KW(I-.QH+R(3䊎M,IP0H45 KS d&PKheZ_W1.9d0cfd610e35c6e4KW(I-.QH+R(3䊎M,IPHHN2$ xHjҡ&PKfeZ7f,9b0fd346afbc5a3cKW(I-.QH+R(3䊎M,IP4 NK3Z 4PKeeZ],xf0a808f5e4a3f9c3KW(I-.QH+R(3䊎M,IP4 NK3j 4PKYeZp7F6Hecc9819e7a64065cKW(I-.QH+R(3䊎M,IPHNrH402400qSlD(J\PKJeZ~8R.'14a80201786a3475KW(I-.QH+R(3䊎M,IPHN100*&PKFeZ,c1d338d0747404cbKW(I-.QH+R(3䊎M,IP0H600aZ4PK@eZ{ x"#f1ac556a385f56beKW(I-.QH+R(3䊎M,IPH6a%M.PK=eZb^,)af4eba763d8d1291KW(I-.QH+R(3䊎M,IP4`D l04PK>!!fe32eaee83abe8f8go test fuzz v1 []byte("\xc100") PK:eZQ)94a33b0bdae2144ceKW(I-.QH+R(3䊎M,IPL5DCtBI PK/eZܔ|.9da1db79e2404886KW(I-.QH+R(3䊎M,IP4` \"DŽ+irPK/eZk)gEcb1b02d1aced37abJW(I-.QH+R(3䊎M,IPH13#~@H2 -Ï4yv$I$I~. Ha&PK eZ?4-Ef2cc9c16249bd607KW(I-.QH+R(3䊎M,IPHN0O000SPKdZd.y3422962f427e8d88KW(I-.QH+R(3䊎M,IP0H600aj 4PKdZ$#27f278a179212851KW(I-.QH+R(3䊎M,IPH6HPKdZId.Te7e180f3c6a21116KW(I-.QH+R(3䊎M,IP44 mPKdZ ){efd25b43e6cf1672KW(I-.QH+R(3䊎M,IPH1HK3Z4PKdZ W-ddefda8f6cd9e85eKW(I-.QH+R(3䊎M,IP+)2=)b1PI PKdZ<)W900fffab2de66871KW(I-.QH+R(3䊎M,IPH1HK3RJ\PKdZ!EMq(3fb546a27c08c248KW(I-.QH+R(3䊎M,IPH6 CJ\PKdZ'$5})K615b32df54036e12KW(I-.QH+R(3䊎M,IPH1HK3bJ\PKdZ݁GU56bfb70f53e0e91dKW(I-.QH+R(3䊎M,IPH4H5H4ЖI1i1@ @P 660 hk0F`4PKdZljR,563908d1e91ccf6bKW(I-.QH+R(3䊎M,IP4bshA+irPKdZ/*p9c84cf6c30290733KW(I-.QH+R(3䊎M,IPH4)!BJ\PKdZݟba.I8ca20b2ee954118dKW(I-.QH+R(3䊎M,IP0H600a|l%M.PKdZ668Oabe9fa99aa281b4cKW(I-.QH+R(3䊎M,IP0HL4 KdӘ J\PKdZܝ';1aeb0e4d19537037KW(I-.QH+R(3䊎M,IPHN100E+irPKdZ3j )3e50756f5d1b5225KW(I-.QH+R(3䊎M,IPHN2Q({$4PK dZ$vp**454b9beedb4522dago test fuzz v1 []byte("\xcbE%x++\xd4x0") PKdZrhO<0085a7883be18fd4JW(I-.QH+R(3䊎M,IPHHCQ w@]RÇ kx###Ӽ3PPKkdZ˲3a7ead904c8b3e876KW(I-.QH+R(3䊎M,IPLH6aa_ L4PKcdZߚe6ma7f3e9d8f97435f7JW(I-.QH+R(3䊎M,IPHN4vPH%ܯ9>?Qp޺~ye8ok@뙋C;żX)Az=Ų=g8a%#SۑUI PK[dZL8)f7563de72baeedd9KW(I-.QH+R(3䊎M,IP4Eɉ@0&PKXdZ3RW57f7b7183b5ff779eJW(I-.QH+R(3䊎M,IPHH6aA l6&F؇ _;B7|F@I PKVdZ144R404ed7d11ebd1fceKW(I-.QH+R(3䊎M,IP0H46002LB)@I PKMdZY0U-8ad6ea53be985c66JW(I-.QH+R(3䊎M,IPLHN;[ZRXB m@?`7JZSPK.dZom5f3a9f1a6267ee3cJW(I-.QH+R(3䊎M,IPHN42i 4Ho :TPKcZS%3ec8954ba504cce5KW(I-.QH+R(3䊎M,IPH6#+irPKcZ?*1f59fd6dc344b767KW(I-.QH+R(3䊎M,IPL3$ %M.PKcZ@-/80f06936f3e91de1KW(I-.QH+R(3䊎M,IPHN0O00c%M.PKcZ ~u+54760bf5bb354fe5KW(I-.QH+R(3䊎M,IPHN4QzGPKcZ ,*34bc8eae94b7e20eKW(I-.QH+R(3䊎M,IPLŃ'lq4PKcZ'ꄀ,H6821189b3d194e02KW(I-.QH+R(3䊎M,IPLA3e`e(irPKcZ˸(0966c927fb092dceKW(I-.QH+R(3䊎M,IPH6000'CI PKcZSKu75cc23e080803409eKW(I-.QH+R(3䊎M,IPHL2 N1)1i@pSfbf.~h#XUkav3S˞m{]dalpx{y>:%M.PKcZo@-0d88a0c626202eed1KW(I-.QH+R(3䊎M,IP2HN0O XI PKcZX=c2b6666474271f65KW(I-.QH+R(3䊎M,IPHH442, :$ %GD(irPKcZ %{4b8a37b87bb60bd0KW(I-.QH+R(3䊎M,IPHI50PKcZ̀'98eb37ff8feaad65KW(I-.QH+R(3䊎M,IPHI3QzdJ\PKcZyedIW5c77798a26c42cec4JW(I-.QH+R(3䊎M,IPH4dp@ ~F@I PKcZ!y(3ed3791a4371b702KW(I-.QH+R(3䊎M,IPLÆ 0(irPKcZ .d3d6995cb96869ce2KW(I-.QH+R(3䊎M,IPHH6000 a`PKcZՇ82gfc5007de6f372011KW(I-.QH+R(3䊎M,IPLH6‰K ,S @L|4PKcZaJ-/b8c598c7665bd47eKW(I-.QH+R(3䊎M,IPHNHK00c%M.PKcZ(d178f1526c70b303KW(I-.QH+R(3䊎M,IPHN2Qa+irPKcZ5&9f3a2801724caa1fKW(I-.QH+R(3䊎M,IPL# (irPKcZU1$/2beb55920bc07522KW(I-.QH+R(3䊎M,IP0HI3QzGPK cZ9---0535ef7002915c93go test fuzz v1 []byte("\x83\xa3000\xdd000") PKcZDFNc86a06301ce4d4deKW(I-.QH+R(3䊎M,IPH4H5H4ЖI1i1@ M F `Sn@:PPKcZGE*89cfe1db7dd66d6eeKW(I-.QH+R(3䊎M,IPHbtPKcZ304cedf90145333654KW(I-.QH+R(3䊎M,IPHNa8k94cOI PKcZ:x'g003178c0972ae2b5KW(I-.QH+R(3䊎M,IP4G`  &PKcZ,Abf04e1d5be312f3fKW(I-.QH+R(3䊎M,IP4Hb PKcZM68763be0f78d455fcKW(I-.QH+R(3䊎M,IPHH4407% DSl(I&PPKcZ.0474bfc3fb2236b2cKW(I-.QH+R(3䊎M,IP0H4600H1J\PKcZdK+dec6020e94179374KW(I-.QH+R(3䊎M,IPH1500FQj(%M.PKcZ~vQ5bf2fbccebcb2e1bKW(I-.QH+R(3䊎M,IPHH5H4ЖI1i1@ M FPys2dyJ\PKcZJݤ*-bea22f2ef7411e27KW(I-.QH+R(3䊎M,IPHI00D%M.PK|cZ$++7f0f62e57a24d5b2KW(I-.QH+R(3䊎M,IPLɩ@0J(f44024f78eee96cdJW(I-.QH+R(3䊎M,IPH$@voJ\PK[cZ){e-}f852a57cfd998123KW(I-.QH+R(3䊎M,IPHH44@&,< %M.PK[cZ&dbf3d514138e601fKW(I-.QH+R(3䊎M,IPHN2VPK YcZA`##f0ec92faff1c40e6go test fuzz v1 []byte("\x91\xcc") PKWcZ}%*11d7506aa953cff3KW(I-.QH+R(3䊎M,IP28/4PKTcZzE2B6d28e4236d9298feKW(I-.QH+R(3䊎M,IP0HL4@dӘ  )%M.PKTcZq(>bca20182215dee88KW(I-.QH+R(3䊎M,IP2D552@!(lSa`Saaa0(J\PKRcZ~*P',66a5aaf00afffa8dKW(I-.QH+R(3䊎M,IPH1006%M.PKQcZd*8($692407aadf9c857dKW(I-.QH+R(3䊎M,IP4`44PK PcZs##a1b0f0ed96fc5a65go test fuzz v1 []byte("\x91\xd0") PKPcZf*'x2ee43439228d1f45KW(I-.QH+R(3䊎M,IPHN6%F ZJ\PKOcZK7q)56a7063f21ddb7c7KW(I-.QH+R(3䊎M,IP@T ZI PKNcZƯ&gfae884e9c85ec359KW(I-.QH+R(3䊎M,IP4G` J&PKLcZ>`3O0c3d7b9c990817c1KW(I-.QH+R(3䊎M,IPH6aa ~10sF=2耒&PKLcZԞ=)*9d6adffda149eb0dKW(I-.QH+R(3䊎M,IPL# PKJcZٽn& b94a3c425071b1cdKW(I-.QH+R(3䊎M,IPH13PPKJcZɪ:76ff3f9de8afa5b8KW(I-.QH+R(3䊎M,IP0H45 KS,63CCPKHcZnr)@1db255c19d7c786fKW(I-.QH+R(3䊎M,IPH13Q(CI PKEcZ%ٟ)580d22619eb40d24KW(I-.QH+R(3䊎M,IPH16Q({4PKEcZ5'sfcf7ce5f8b768d9cKW(I-.QH+R(3䊎M,IPHNaC24PKEcZ.'7f14c59157d91c3fKW(I-.QH+R(3䊎M,IPHN2áVPKEcZMe(c158dd906ebf199b2KW(I-.QH+R(3䊎M,IPH6000PKEcZN_B(cb8eb8162669df94KW(I-.QH+R(3䊎M,IPHNa!TPKDcZL(Zd480fd5dd74aa61bKW(I-.QH+R(3䊎M,IPH6000 PKDcZ~۶x\|116977312ef18a152JW(I-.QH+R(3䊎M,IPC1EWJo;K@ß!WE8ûwdW׊1ˮn`%M.PKDcZY/"l){b74200d49eac5a01KW(I-.QH+R(3䊎M,IPHNaQ& J\PKCcZHM*Vef64c6be555569f7KW(I-.QH+R(3䊎M,IPHNr`0%PKBcZK#7b9d94f81332269fKW(I-.QH+R(3䊎M,IPH6XI PKBcZ!%[ab35b5999a80e6fdKW(I-.QH+R(3䊎M,IPHI3ri%M.PK@cZql(H88f026782efc5be4KW(I-.QH+R(3䊎M,IPH6000 PK@cZ%PP-fca5d5e4f0d6e3ccKW(I-.QH+R(3䊎M,IPH13Q(c1ʠCI PK ⚿D: G[ \PK9cZ!641d726f832ab47044KW(I-.QH+R(3䊎M,IPHNaLF0aQ&PK4cZtu=-:c0d1c5396a7b9cddKW(I-.QH+R(3䊎M,IPHNr`@Gn%G9@X0G1R"(&PK0cZ|K%[57cd8672b16d9b59KW(I-.QH+R(3䊎M,IPHN6%&4PK/cZf%e95025c6255d2f34KW(I-.QH+R(3䊎M,IPHI34PK/cZ%502f48c34e8d867aKW(I-.QH+R(3䊎M,IPHI14PK/cZ:L'%{64a686832c8a049eKW(I-.QH+R(3䊎M,IPHN4ZJ\PK/cZQG%61e1d1ed5fff34d9KW(I-.QH+R(3䊎M,IPHN3Z4PK.cZ;'Gd2e4430e7ebe20a1KW(I-.QH+R(3䊎M,IPHN3Q6~&PK-cZW㱪&+83b40804a0ac2753KW(I-.QH+R(3䊎M,IPHN100J\PK-cZ!W+X2889a63274722d8eKW(I-.QH+R(3䊎M,IPLH1500 2PPK,cZdC9%[02b66a0fb82d327eKW(I-.QH+R(3䊎M,IPHI1ri%M.PK,cZf%0831032d33321b6aKW(I-.QH+R(3䊎M,IPH6#+irPK+cZ\N!-f3a9ec9ff2a83a2aKW(I-.QH+R(3䊎M,IPHN2070ۜvl%M.PK+cZò%c10b5da399bd4a92KW(I-.QH+R(3䊎M,IPH6#+irPK(cZD+96cdaeb7c104d7dc3KW(I-.QH+R(3䊎M,IPHNb tPK(cZ"e&bb32d37fc7a159b1KW(I-.QH+R(3䊎M,IPH626&E&PK&cZ3>%[5a939c6b3da2f834KW(I-.QH+R(3䊎M,IPHN4ri%M.PK&cZ?4_:b5ad934c54deb916!_ !$0޴Mh^p߇שXxO*iko;ixpPK&cZB6efa3b88ceb70136aKW(I-.QH+R(3䊎M,IP0HL6@C!>*0Fy@I PKcZx#[80c14be18de13f11KW(I-.QH+R(3䊎M,IPH6+irPKcZo%84fe2315e44760656KW(I-.QH+R(3䊎M,IPHN6%J\PKbZO&f42cb7a24d2fc461KW(I-.QH+R(3䊎M,IPHI3J+irPKbZ%cab0a0b5e0c93034KW(I-.QH+R(3䊎M,IPH13z24PKbZp،&49a366da449d3e8dKW(I-.QH+R(3䊎M,IPHI1J+irPKbZ.R s0aebd82cf39f40bd4KW(I-.QH+R(3䊎M,IPHNaSM0KI PKbZ+K=:3d57fb4f44fc974cJW(I-.QH+R(3䊎M,IP00P J]r}8 #x\ (irPKbZJM)53c130fe1e367e47KW(I-.QH+R(3䊎M,IPHN3Q({04PKbZt&S88c2896a4c4a66ebKW(I-.QH+R(3䊎M,IPH1500 RPKbZ+Scb912f7b1ae1caa5KW(I-.QH+R(3䊎M,IPHN440@@,PKbZA"&0ba8ef93dd5bc0f2KW(I-.QH+R(3䊎M,IPH1500PK bZ|##b70dbe264c0149ffgo test fuzz v1 []byte("\xc4\x00") PKbZ#%[%2b9273a67dcd0442KW(I-.QH+R(3䊎M,IPH140<&PKbZ .%Q32edba166e178e90KW(I-.QH+R(3䊎M,IPHN10 TPKbZWW[397ddb1232a615035KW(I-.QH+R(3䊎M,IPHH440 jL$ J `PKbZ?Ѓ%Wc64791a3a5b835a1KW(I-.QH+R(3䊎M,IPHN2RJ\PKbZ&/*Sbf13d8343e048884KW(I-.QH+R(3䊎M,IPHN440J\PKbZj7%{1146ee3bbb9d4cafKW(I-.QH+R(3䊎M,IPHI60PKbZU&f16dcaf31ae443eaKW(I-.QH+R(3䊎M,IPH1500&PKbZ!',144e0c547d31fc48KW(I-.QH+R(3䊎M,IPHN00a%M.PK bZ"ɧ2 21a9b7ddcb62a148go test fuzz v1 []byte("0\xc4") PKbZYz c50af70b81cd3bf4KW(I-.QH+R(3䊎M,IP2@I PKbZuT%K5a7d678091af622eKW(I-.QH+R(3䊎M,IPHI1bi%M.PKbZƮ'k2911f3b805d36d2bKW(I-.QH+R(3䊎M,IPH140%E*irPK bZPq##00ac995ad8f0eee3go test fuzz v1 []byte("\x80\xde") PKbZ}%ec0b0a6beee6a660KW(I-.QH+R(3䊎M,IPHN10l&PKbZ-045ae6cecd21dfe59KW(I-.QH+R(3䊎M,IP2HNHK XI PKbZU#5b03c93d1225a9cfKW(I-.QH+R(3䊎M,IP07VPKbZ!$e9574b7ab8d72378KW(I-.QH+R(3䊎M,IPHN6Ą&PKbZyٖ%o8a6b6c9ec6d62fdaKW(I-.QH+R(3䊎M,IPHI60.PKbZT0643291301813718cKW(I-.QH+R(3䊎M,IPHH44af%@I PKbZdK62156ecbef1122eaJW(I-.QH+R(3䊎M,IP0HL$nGζD0N1PPKbZn+)bbbd50b6eb615adaKW(I-.QH+R(3䊎M,IPHN2c+irPKbZl%Sce4d6e619ce3b546KW(I-.QH+R(3䊎M,IPHN4Ri%M.PKbZc&+30648f4693162d69KW(I-.QH+R(3䊎M,IPHN00J\PKbZ{P%130ff6d39194017cKW(I-.QH+R(3䊎M,IPHI60&PKbZ U_u>588025d5104d93ecJW(I-.QH+R(3䊎M,I780!b㩔bY"6F1 ~7_َsrY[.3ZLUϭˏٴx- (*M\ },7690caa3c808994cdKW(I-.QH+R(3䊎M,IP4H67001@J\PKbZ7H)'*83942d7b31157d54KW(I-.QH+R(3䊎M,IPHNr0#%M.PKbZ}R0$50bea6ef5bd59bdeKW(I-.QH+R(3䊎M,IPHN6(BI PKbZT'f7ceb7af64735a58KW(I-.QH+R(3䊎M,IPHI60%TPKbZ .%[d691022079880516KW(I-.QH+R(3䊎M,IPH12ri%M.PKbZC V(983c6ae38c531b1bJW(I-.QH+R(3䊎M,IPHHL6@ > bD: 5ЕH@I PKbZ}P26f191e7e1ae3b719JW(I-.QH+R(3䊎M,IPH13#"9 >F? $,`,PKbZ_%K5c96502c505b5680KW(I-.QH+R(3䊎M,IPHN4bi%M.PKbZY%aadde78735313aacKW(I-.QH+R(3䊎M,IPHN54PK bZEJ##7f1a1ddcde60647ago test fuzz v1 []byte("\xcc\x00") PKbZ %'4d138e8cf97cc221KW(I-.QH+R(3䊎M,IPHNrv4%M.PKbZHeh%C4ea48629b5765b26KW(I-.QH+R(3䊎M,IPHN2|l%M.PKbZy'3cb1ec509da8805fKW(I-.QH+R(3䊎M,IPH0QPKbZF*a843018d04746439KW(I-.QH+R(3䊎M,IPH0@YPI PKbZU&3a7d6c774dbea4f8KW(I-.QH+R(3䊎M,IPH12J+irPKbZhk)5b12e61eb8d37f87KW(I-.QH+R(3䊎M,IPHI60%GɑI*irPKbZ9 "F35bf3f38096ba51551@0+Nls0 e4(/ 7ܺy09X/PKbZu%;ae48aa57e7c71178KW(I-.QH+R(3䊎M,IPHN4\&PKbZ:&ab18e9f8f2f6414dKW(I-.QH+R(3䊎M,IPHN5J+irPK bZC**dc963eb9c2be0b18go test fuzz v1 []byte("\xcb\xc422022Y2") PKbZ߰(6837d622845dad842KW(I-.QH+R(3䊎M,IPH6000d(irPKbZ &'de173e262a0bf03eKW(I-.QH+R(3䊎M,IPHNr0C%M.PKbZgN,B7a484aeea8c361d0KW(I-.QH+R(3䊎M,IPHN0t300q4PKbZoF*$Hfc35ba7ae22bb2e0KW(I-.QH+R(3䊎M,IPHN6 PPKbZ\)b95623213cbef7a2KW(I-.QH+R(3䊎M,IPH0Q(irPK bZA 3759e863bb4871fego test fuzz v1 []byte("0\xce") PKbZK;?)77cb86950aa10b779KW(I-.QH+R(3䊎M,IP4HN3d&PKbZ>4Y4dd4671267ab6ccbKW(I-.QH+R(3䊎M,IPH230H3LHBйJ\PKbZ{H 274329392a450b84JW(I-.QH+R(3䊎M,_G ['~i ?=Pw`&x&K- ̫XXzTptU~x@Т--\ !B!'dՆā-bH=xPKbZDL'1ac2f48d8388f947KW(I-.QH+R(3䊎M,IPH12QzhJ\PKbZ*D`+70ec9963511858f17KW(I-.QH+R(3䊎M,IPL6d#dl`PKbZD=.1280dce35f50221caKW(I-.QH+R(3䊎M,IP0H600dS%M.PKbZr\'?Sdb252dbbea1acb1cKW(I-.QH+R(3䊎M,IPH0LzkALEjRLENi@dSaif4PKbZb` v@a09f4e463e2862f0JW(I-.QH+R(3䊎M,IPH0@>oa0PPKbZz+C16376d04f0669f10KW(I-.QH+R(3䊎M,IPH210)A0(irPKbZzF.U8331e5946d319ff4KW(I-.QH+R(3䊎M,IPHNaih``)FI PK bZJ eda3daae6e5f0a15go test fuzz v1 []byte("0\xd2") PKbZ-$;&>a5b6d8d5525c6f80KW(I-.QH+R(3䊎M,IPH1500G)irPKbZs,Faff2f4c4c61f8523KW(I-.QH+R(3䊎M,IPL30 C4PKbZJt(*96369bbc7f5364c8KW(I-.QH+R(3䊎M,IPHNr `PKbZ{8+9c022b598f003eddKW(I-.QH+R(3䊎M,IPHN5QzGPKbZC|(+d4c17bc2ef2d5275KW(I-.QH+R(3䊎M,IPH67006%M.PK bZі**088569ed28d933fego test fuzz v1 []byte("\xcb\xc822022Y2") PKbZ޸|'-863b87e49eeba142KW(I-.QH+R(3䊎M,IPH600034PKbZֲR)36e6a99cae2eedb18KW(I-.QH+R(3䊎M,IPH1HK3d&PKbZj0%'73921c0aff3936d0KW(I-.QH+R(3䊎M,IPHNr0%M.PKbZ^w8(*52dafe45eb662f12KW(I-.QH+R(3䊎M,IP0C%M.PKbZpTx$G747d4591a53ab5f2KW(I-.QH+R(3䊎M,IPHN6 PPKbZ.M682a5ede907fdff2KW(I-.QH+R(3䊎M,IPH25@ Q<1q&PKbZ>0$Cb0ff742d60aca993KW(I-.QH+R(3䊎M,IPH10 PPKbZ1f)*e557d0d848963c10KW(I-.QH+R(3䊎M,IP0T PKbZ(,b615824a106bf922KW(I-.QH+R(3䊎M,IP2H1HK3%M.PKbZ%/054d54af906ecfa48KW(I-.QH+R(3䊎M,IPHNb   604RPK bZ 5a0e8b33a26c7017go test fuzz v1 []byte("0\xc6") PKbZ. -0c6f3605ca20dbf81KW(I-.QH+R(3䊎M,IP0H45dCPKbZq'0aee990da8a8aa7acKW(I-.QH+R(3䊎M,IPL5@1)iJ\PK bZQ##b4c95cac84e389c4go test fuzz v1 []byte("\xcaa,,,") PK bZƪ 207b2e98276016dcgo test fuzz v1 []byte("0\xcd") PKbZr~)06731bc07597d05a0KW(I-.QH+R(3䊎M,IP4HN30[I PKbZ8%35a4b13fde7fc6314KW(I-.QH+R(3䊎M,IPHN4tZI PKbZ>J+Mc5fcfc936b09983bKW(I-.QH+R(3䊎M,IPHJ5"|D*irPKbZ0/Ae43acea42c214f10KW(I-.QH+R(3䊎M,IPH23P aj̄%M.PKbZI85a9f89bae14d820abKW(I-.QH+R(3䊎M,IPH0aQ `M&PH>QPKbZ>oj+b631a3816c6236f6KW(I-.QH+R(3䊎M,IPH12QzPKbZ.&222253d2f256a689KW(I-.QH+R(3䊎M,IP *irPKbZ.Mk+M2bdb6fab7f4ad4ffKW(I-.QH+R(3䊎M,IPHNa aPKbZ^2?fb25ee4c02d0fb16KW(I-.QH+R(3䊎M,IP0H46002L bi 4PKbZ+)7101cce5394e7b192KW(I-.QH+R(3䊎M,IPL6d J\PK bZ)"] 0f4241db31908ab3go test fuzz v1 []byte("0\xdc") PKbZ1?69609c061f389081KW(I-.QH+R(3䊎M,IP0HL4@dӘ  PPKbZ )/8378bbc57f736d72KW(I-.QH+R(3䊎M,IP4HN5PKbZ y*/9765291b43506962KW(I-.QH+R(3䊎M,IP2H1HKaPPKbZxj/>fbb3f405dffd71d4KW(I-.QH+R(3䊎M,IPH0Lzk X&PKbZ},Pdd762143a9193c90KW(I-.QH+R(3䊎M,IP0H45 ÈRI PKbZ>&+b2119804cf041f29KW(I-.QH+R(3䊎M,IPHN000J\PKbZ-0e1e38c894ed38686KW(I-.QH+R(3䊎M,IP0H45dKPKbZ ,-286b954b2557300bKW(I-.QH+R(3䊎M,IPHNb GCC PI PKbZq.);3d377c969654f002KW(I-.QH+R(3䊎M,IPH21ThJ\PKbZÉ&U826f37368fd82e0bKW(I-.QH+R(3䊎M,IPH4 5)irPK bZAc++8f84dce128f1e9afgo test fuzz v1 []byte("0\xcbD%0700\x130") PKbZ6i#f2c3cc25cee229fcKW(I-.QH+R(3䊎M,IPLXI PKbZ-rjk1c2e74d3c2210601KW(I-.QH+R(3䊎M,IPH2100Q`d (g 1S,CH!"tc8Y d0$t1,4m1K6%M.PKbZq*:491e88853a283327KW(I-.QH+R(3䊎M,IPL30H1F(irPK bZe 22d30eb9b323ee39go test fuzz v1 []byte("0\xd0") PK bZ<##4b45c790cd848ebcgo test fuzz v1 []byte("\xcaN828") PKbZ"&700b37bc5886314f0KW(I-.QH+R(3䊎M,IPH1500J)irPKbZ5T106b78c09b6d9efdKW(I-.QH+R(3䊎M,IPH45$UC(3 l`IFIB&`7 2Tt$ MF%M.PK bZZR##0d4dd6ee73760b42go test fuzz v1 []byte("\xcaay00") PKbZ<0'0e98247f3393631aeKW(I-.QH+R(3䊎M,IP4H6FJ\PK bZ##02000aa5c5ba083bgo test fuzz v1 []byte("\xca[000") PKbZIb$329ebb82bddf3debKW(I-.QH+R(3䊎M,IPH10BI PKbZz%K4ea23aa68c0fcde1KW(I-.QH+R(3䊎M,IPH140 TPKbZߧN1<c439e84c97af4a52KW(I-.QH+R(3䊎M,IP0HL4ds a` *irPKbZK(xs'+9eab89897b411417KW(I-.QH+R(3䊎M,IPH1HK3%M.PKbZ f&/3c4b2ba8b8030cd3KW(I-.QH+R(3䊎M,IPHN00@J\PKbZ4q):31672dca1afe7532KW(I-.QH+R(3䊎M,IPL3  J\PKbZ-9b022d36794dd59b3KW(I-.QH+R(3䊎M,IP0HL4ds[I PKbZpġ).e61197d693a15cf5KW(I-.QH+R(3䊎M,IPH1HKaPPKbZ]Μ%3e017c28f4f9c70b5KW(I-.QH+R(3䊎M,IPH10%0%M.PK bZ%%a1ce55a31ed57937go test fuzz v1 []byte("\xc70\x030") PKbZȇ',9cdaddaec7d02239KW(I-.QH+R(3䊎M,IPHN00a%M.PKbZ[*93fa87b1a3dbf33a2KW(I-.QH+R(3䊎M,IPHNrH254&PKbZ)467319d450633be87KW(I-.QH+R(3䊎M,IPL3PKbZ~.T98220682987dabafKW(I-.QH+R(3䊎M,IPH60H3@aD@I PKbZג*8bf77dc1a16f2f0e4KW(I-.QH+R(3䊎M,IP2H60034&PKbZ){(b45dc5fafb2b2a24KW(I-.QH+R(3䊎M,IPH3Nу+irPKbZ7(*d2a240918db7399eKW(I-.QH+R(3䊎M,IPL54J\PKbZ)?59cbde2ad2ec149eKW(I-.QH+R(3䊎M,IPLHI3\&PKbZrRԃRa3c65ba3e9234151]CQDst˘zL[p^.[xz] EIf\vj JDzqkZ1yMw D'@aF:&اGQò퀆AܤQ]R3sPKbZ*d 1I1a3d6fd1a24da1beKW(I-.QH+R(3䊎M,IPHHL6@@1s PKbZsx*-da0202887134f2bdKW(I-.QH+R(3䊎M,IP00HNJ\PKbZ,9b2b854a238819b20KW(I-.QH+R(3䊎M,IP0HL4d8OI PKbZ&74f0e9119b026652KW(I-.QH+R(3䊎M,IPH6T4PK bZQI&&09e3fd5d009f0963go test fuzz v1 []byte("\xca\xd0000") PKbZH'+ae132544ccf6c2bfKW(I-.QH+R(3䊎M,IPH1005%M.PKbZb b-0f031a9ab2640c9b7KW(I-.QH+R(3䊎M,IP0H45dcPK bZc**7e77954ab59fd0aago test fuzz v1 []byte("\xcb\xc802022Y2") PKbZt:%'d3a58a86db67fbfeKW(I-.QH+R(3䊎M,IPH60%M.PKbZh Zcdf50fcdb9fed59dKW(I-.QH+R(3䊎M,IP (irPKbZP',7a472bc56f336f04KW(I-.QH+R(3䊎M,IPHN00a%M.PK bZ''51871b31df6b597fgo test fuzz v1 []byte("\xd6\xff0000") PKbZv(+a5327139bdfb0baeKW(I-.QH+R(3䊎M,IP4H140J\PKbZ&5%H537e8cfcd3a16324KW(I-.QH+R(3䊎M,IPH13bJ\PKbZk (*76d8e432b866e7faKW(I-.QH+R(3䊎M,IPHNrH25%M.PKbZ=)1868c955821d1328aKW(I-.QH+R(3䊎M,IPL3@$ PK bZ^ ++106d5a4a06a9ddddgo test fuzz v1 []byte("\x93\xd4\xff0000") PKbZ,;9c7c8651ec4d386fKW(I-.QH+R(3䊎M,IPH6I3@` 3OI PKbZBW36b8912cf8e87d85KW(I-.QH+R(3䊎M,IPH45$UC(3 l`IFIB&0S,c* IEWdDOI PKbZ88')35c8b636f2f64bb0KW(I-.QH+R(3䊎M,IP4HN3%M.PKbZ&N-o30f11456db187cb1KW(I-.QH+R(3䊎M,IPL4 `1J\PKbZ}6{)(-e46e0e64cca1dd40KW(I-.QH+R(3䊎M,IPHN00aPPKbZ;[1^8599d9c1a5418f5fKW(I-.QH+R(3䊎M,IPH60L6b*Rp04PKbZ#($)90fe6f0db8c9909fKW(I-.QH+R(3䊎M,IPHNaC%M.PKbZ(*879f00acd57f79ebKW(I-.QH+R(3䊎M,IP0D%M.PKbZ:A";5cbcb028fe775289KW(I-.QH+R(3䊎M,IP04PKbZvT#bb29db531cf90d41KW(I-.QH+R(3䊎M,IPH3XI PKbZZEF%Kd57ddc02261eac0dKW(I-.QH+R(3䊎M,IP0PPKbZW9N).9aa3caf2b40bd374KW(I-.QH+R(3䊎M,IPL6c SI PKbZEʯ@e80330b25945a688KW(I-.QH+R(3䊎M,IPHJ3b*-$d9 !Ū.4PKbZN'sfcb5c2ef2edb215fKW(I-.QH+R(3䊎M,IPH10%F *J\PK bZ|}''159b641156c7236bgo test fuzz v1 []byte("0\xc70\xff00") PKbZ|149cd38d651131496eKW(I-.QH+R(3䊎M,IP2HNb3C Ę &PKbZ;'3b39e1404324e0471KW(I-.QH+R(3䊎M,IPHN6@#4PKbZϷ(*a957663fb088c17aKW(I-.QH+R(3䊎M,IPHNdCPKbZl+F8a299a076cc823fdKW(I-.QH+R(3䊎M,IPHHL64PK bZ S ecb58f468e5c81bcgo test fuzz v1 []byte("0\xcf") PKbZ gsj#091e35bba2ba7ece2KW(I-.QH+R(3䊎M,IP2HNF'4PKbZoK(768dcd2dbb8485503KW(I-.QH+R(3䊎M,IPL6dPKbZ\r%_2f2502e2cd6b50c2KW(I-.QH+R(3䊎M,IPHN5Jh%M.PK bZSP((74f24b1268513f63go test fuzz v1 []byte("\x960000\xcd0") PKbZ6-90dbd3bb36652dea4KW(I-.QH+R(3䊎M,IP0HL4@dS(SI PKbZ-P-9f7050afa9fd792dbKW(I-.QH+R(3䊎M,IP0H420H@I PKbZ,&9c716bcb01e989f0KW(I-.QH+R(3䊎M,IPHK& E&PK bZo3))03c44fafda133431go test fuzz v1 []byte("\xca\xcb\xdd0B") PKbZ:',93afb6f2e6047c44KW(I-.QH+R(3䊎M,IPH1005%M.PKbZȫz/Sdf1ea30296a230ddKW(I-.QH+R(3䊎M,IPHI3dEP&PKbZ$D71ee0d710ebfdf10KW(I-.QH+R(3䊎M,IPH41002 TH40 MIR*(3RpÕ4PKbZ7F',7bbe914327114ff6KW(I-.QH+R(3䊎M,IPH1HK3%M.PKbZ!G#'394c6bcf15359de5KW(I-.QH+R(3䊎M,IPHN3%M.PKbZ!f 35b41542d4c0324aKW(I-.QH+R(3䊎M,IPXPKbZ:\-062316805e2f2ee84KW(I-.QH+R(3䊎M,IP0H45$PKbZj-077743019f97976b3KW(I-.QH+R(3䊎M,IP0H45 K3PK bZ.**70a35473229f4c18go test fuzz v1 []byte("\xcb\xc800222Y2") PKbZZ&)b80f14544beea8e2KW(I-.QH+R(3䊎M,IP2HN3%M.PKbZ4)#0159405efafbf448eKW(I-.QH+R(3䊎M,IPH64@J\PKbZP)O135664452cb4ad7dKW(I-.QH+R(3䊎M,IPH6W0 [)%M.PK bZ^7f62a7fbc91fef1bgo test fuzz v1 []byte("\xce") PKbZ 1z,01b8e61f1a3d9c1e9KW(I-.QH+R(3䊎M,IP0H45 PPKbZ_*046bfead06fa24e89KW(I-.QH+R(3䊎M,IPL54(PPKbZUѥ$391cbbfa5280957b4KW(I-.QH+R(3䊎M,IPHN10$4PKbZb%0u8p6dd52219afb2f29fKW(I-.QH+R(3䊎M,IPHH45$lh(irPK bZ.##32b1f0a50de5867ago test fuzz v1 []byte("\xcaO,C,") PKbZ.b'(7b5ad3dee4be020fKW(I-.QH+R(3䊎M,IPH1HK3%M.PKbZr+3416631125146960KW(I-.QH+R(3䊎M,IP4HlTJ\PKbZ3$'dcffa2890a427599KW(I-.QH+R(3䊎M,IPHNr2%M.PKbZp%?00ed2a45439ee248KW(I-.QH+R(3䊎M,IPH13< %M.PKbZO[)113fa1457fd4acb42KW(I-.QH+R(3䊎M,IPL3$PKbZs3%30fdc1af02e581ef1KW(I-.QH+R(3䊎M,IPHN2d&PK bZ^g((e1deae552f6dea72go test fuzz v1 []byte("0\xd4\xff0000") PKbZ(7bffa6a8b95eba591KW(I-.QH+R(3䊎M,IPHHI50$4PK bZ db3f0b1887e1e487go test fuzz v1 []byte("\xd00") PK bZr 1c42ab505246346bgo test fuzz v1 []byte("0\xd9") PKbZw [bdb34052e0c746deKW(I-.QH+R(3䊎M,IP2(irPKbZVR/.N59198523573af9daKW(I-.QH+R(3䊎M,IP2H60L6 j <%M.PKbZ6b?&'3371ccc512e364acKW(I-.QH+R(3䊎M,IP2HNaC%M.PK bZ##0eb82d3731f066bego test fuzz v1 []byte("\xcaF000") PK bZ!%%14abba83e3fc3f92go test fuzz v1 []byte("\xd4\xff00") PK bZe#P((aa71670f34f28543go test fuzz v1 []byte("0\xd5\x050000") PKbZ6'+ff2d7fdeaaae88a0KW(I-.QH+R(3䊎M,IP4HN3%M.PK bZ*1$$604893782519daabgo test fuzz v1 []byte("0\xcaA000") PKbZ(,1938ed13b31fc17cKW(I-.QH+R(3䊎M,IPL4H4%M.PKbZ *1c3dfc2b1b45363e3KW(I-.QH+R(3䊎M,IPL300H16@%M.PKbZ伫-&,bc905bdfa57fa30eKW(I-.QH+R(3䊎M,IP2HN4PKbZ$'f01966a601fa7a4dKW(I-.QH+R(3䊎M,IPHN3%M.PKbZ;'+c28c1f7a82ab0927KW(I-.QH+R(3䊎M,IP4HN2%M.PK bZ --a0bf20bf817ca92ego test fuzz v1 []byte("\x81\xa3000\xd4000") PKbZ%`S&,c21c321fec84a016KW(I-.QH+R(3䊎M,IP2H12PKbZ*Ed11197f8a129b863KW(I-.QH+R(3䊎M,IPHJ5<De#&PKbZ=D-Z88c63546de12a3a8KW(I-.QH+R(3䊎M,IPH60L6b*Rp04PKbZ>2I#'ad4596439bd03e7dKW(I-.QH+R(3䊎M,IPH64%M.PKbZ~%&273c318c349a0b88KW(I-.QH+R(3䊎M,IPHNaC%M.PKbZ4 {)*5006a54067bffd83KW(I-.QH+R(3䊎M,IP2HNtHL 4PKbZHO'(536f43eb997090e0KW(I-.QH+R(3䊎M,IP4H13%M.PKbZd#&71374973dbfe1244KW(I-.QH+R(3䊎M,IP2H1J\PKbZ˚%*c1ebd4180890ad66KW(I-.QH+R(3䊎M,IPH1aPPKbZ'*20d0b14017ad3685KW(I-.QH+R(3䊎M,IPHI4%M.PKbZnҠQ(+40bb4baebf8379ceKW(I-.QH+R(3䊎M,IP2HN0H5%M.PKbZ%"/45a079189a7f6ffdKW(I-.QH+R(3䊎M,IP0@J\PKbZE*59619a5f25080bd95KW(I-.QH+R(3䊎M,IPHN4 mf4PK bZ":0&&bfc7b6c091165ad5go test fuzz v1 []byte("\xc800\x040") PK bZDe5078d8d62a13bc5go test fuzz v1 []byte("\xca") PK{bZhY)A1f49a7e0a44d4587KW(I-.QH+R(3䊎M,IPHJ5<4@J\PK{bZƄUaed5c14114d35eb2]NA o0t ,a.8e=:_*Y9ʻyݰ%fRqԷ,4ۇFzQvC'4`QsmY]5e]`[V+I ̆M PKybZ O#'c693ee2dd1eeac8fKW(I-.QH+R(3䊎M,IPH16%M.PK ybZ{-k69eec6f09e6bd419go test fuzz v1 []byte("\xdf") PKybZ&){'Ce150dd9ef2bda6c7KW(I-.QH+R(3䊎M,IPH2 4PK ybZ jY[''f46f9d07fdfb0927go test fuzz v1 []byte("\x93\xc60000") PKybZC`(jbe3baab8840c74c4KW(I-.QH+R(3䊎M,IP4CJp(irPKybZ4]#58d490ba11cfc399KW(I-.QH+R(3䊎M,IPHXI PKybZ}&,a6b5640f6626dd01KW(I-.QH+R(3䊎M,IP2HN5PK ybZ@fK&&3a299f4d1e65deddgo test fuzz v1 []byte("\x81\xa3000") PKybZPnk#$b32a411cdaff0e8bKW(I-.QH+R(3䊎M,IPH4%M.PKybZ>+&'a476c59b215d33e5KW(I-.QH+R(3䊎M,IP2HNa %M.PKybZv"#892e0b2fe30ba509KW(I-.QH+R(3䊎M,IPH6a%M.PK ybZ78{##00f94e9e89bf84e5go test fuzz v1 []byte("\xcaA000") PKybZI%bfce69550ea5f02dKW(I-.QH+R(3䊎M,IP00#+irPKybZq|9 63f6bb3d79c9aa0bKW(I-.QH+R(3䊎M,IP2`Q0 F(` H670PPKbbZµO#$d6b439f6019a8a43KW(I-.QH+R(3䊎M,IPH67%M.PKbbZ-9d35acc2391f05d33KW(I-.QH+R(3䊎M,IP0HL4dS[I PKbbZ*w+0a5d15fddaa591435KW(I-.QH+R(3䊎M,IP0H45 L+irPK bbZk2e54acb8fdbccf6fcgo test fuzz v1 []byte("\xcf") PK bbZ@4''c51272640ca653f6go test fuzz v1 []byte("\xc800\xff00") PK bbZ"(**459317e990483bd4go test fuzz v1 []byte("\xcb2100\xc7(1B") PKbbZ蚴%+afc083acf4c7eda7KW(I-.QH+R(3䊎M,IPHI1PKbbZT(34b1823f6cc7bd87fKW(I-.QH+R(3䊎M,IPH20)@PPKbbZ!OD,w8f0aeac1d897c37fKW(I-.QH+R(3䊎M,IPHJ5 b*R,֤PKbbZPbB4G84ed8eea41320da3KW(I-.QH+R(3䊎M,IPH234Ø Ԙ s4(irPKbbZT+@F968ab67d1ec1679a}Q5@ } ?WβR1n_|z>/a(CP Ma~o6Y482"g'da*Ġ6 j@VGLSg4o\=%Jm:; heIC< Y0ӌWu+ƥvF}7`,!ڔO PK `bZY 6b92cb4024aa7026go test fuzz v1 []byte("0\xd1") PK`bZJ";291eb8e4bef0dd11KW(I-.QH+R(3䊎M,IPH6‡4PK`bZ2{-de3fac69bf1b30fdcKW(I-.QH+R(3䊎M,IP(m1 %M.PK`bZdpI:f3748bcecda7c119JW(I-.QH+R(3䊎M,IPH6G>4H46%M.PK YbZc8fb35720121533cgo test fuzz v1 []byte("\xdd") PK YbZy310dada39b0f6930go test fuzz v1 []byte("\xde") PKYbZ%̩)O722b8a1a02f74014KW(I-.QH+R(3䊎M,IPHHI50 TPKXbZĈ()5b2e1fa371b53526KW(I-.QH+R(3䊎M,IP47 PK XbZR##0073638dc475c110go test fuzz v1 []byte("\xce0000") PK XbZ968de876d3c7cc89go test fuzz v1 []byte("\xd3") PKXbZ79'*39826f08ad3852d4KW(I-.QH+R(3䊎M,IPHNHM6%M.PKXbZɴ*)/c4d7d367340535fbKW(I-.QH+R(3䊎M,IPH1HKa(PPK XbZDZ""3ef2b217f3de4c6ego test fuzz v1 []byte("0\xde00") PK XbZ҃ dbc71bf32aba139ago test fuzz v1 []byte("0\xdf") PKXbZwo`d4114174acf20a4cJW(I-.QH+R(3䊎M,IPȍHJ+)HN-lԡG(v00@`;t(:F Ϯd+irPK@bZ|#01bfa74f017461bc1KW(I-.QH+R(3䊎M,IP2H1@'4PK@bZ(0c0501bd3e195b8bdKW(I-.QH+R(3䊎M,IPL5HI5@J\PK@bZZʑ#&e8c5911a58026df3KW(I-.QH+R(3䊎M,IP2HNJ\PK=bZtSr).796384628d94789eKW(I-.QH+R(3䊎M,IPHNasC 414PK=bZ}bfa0aab07ed555c74KW(I-.QH+R(3䊎M,IP2H21P yĄ RP&TB1)f@ *LX,(pdP)X-TUJ\PK=bZ i/ %&2555358db0dcda4eKW(I-.QH+R(3䊎M,IPHNaC%M.PK =bZ))e2ef1462d12a536ago test fuzz v1 []byte("\xca\x7f\xff00") PK=bZ} \W$'8a5e84f8641f9d35KW(I-.QH+R(3䊎M,IPHI50J\PK =bZ͍**a384617f58ef1c04go test fuzz v1 []byte("\xcb\xc800Aa110") PK=bZZa#[ea6c7a9046b93bc7KW(I-.QH+R(3䊎M,IP+irPK =bZ9;sdd0716e54cde9bc8go test fuzz v1 []byte("\xcd") PK=bZ[oIn ef90fb60d9b326ffKW(I-.QH+R(3䊎M,IP2`PK=bZlf(3fb81b3ddc5702527KW(I-.QH+R(3䊎M,IPHL600)BJ\PK=bZC%3793e29afa6040371KW(I-.QH+R(3䊎M,IPL3@I PK =bZW$$8a234f5953618cb2go test fuzz v1 []byte("0\xca<000") PK=bZ5L#[4b71f737dbbe7931KW(I-.QH+R(3䊎M,IPL+irPK ͗uwX#噈TnƚjMpTGX Z8'#-t , E0R$ 9E6eCAӐ?ˌ LEʅ &-&t Ƅdgf`q g8#ӷG"lzif{cg $Tߔ[jvny 4?ΖyPCC'<·3osCSl76HHRkvGWDp!C%\q տ!9",2A@kU7QWGb*4PK8bZCr.;fc99f1048f6177deKW(I-.QH+R(3䊎M,IPH23P ajd4PK 8bZI\7538f9f4f491e08cgo test fuzz v1 []byte("\xdc") PK 8bZK(##4f02154e4c39fe8fgo test fuzz v1 []byte("\xcb0000") PK 8bZAD{.""43021829db3fea60go test fuzz v1 []byte("\xc8000") PK8bZ&*8fa9a4ca15f4028bKW(I-.QH+R(3䊎M,IP410 PK8bZ($%74a0a728f2f606d0KW(I-.QH+R(3䊎M,IPH140J\PK8bZN#`.[4908d79ba1bf0348KW(I-.QH+R(3䊎M,IPb (6H"4PK 8bZe)%%ec5cf7fb0a8d69e4go test fuzz v1 []byte("0\xc7\x000") PK8bZS(3d466d3864667cab2KW(I-.QH+R(3䊎M,IP47 +4PK 8bZC$$de6a0483fb37f2dego test fuzz v1 []byte("0\xca0020") PK 8bZ`=8d4d6a6e3f2e4f68go test fuzz v1 []byte("\xd1") PK 8bZ E4""00d0f1fb7f8660fbgo test fuzz v1 []byte("0\xd100") PK8bZ%/209783af18733d50KW(I-.QH+R(3䊎M,IP4C@PK 8bZi%%db4791269c7cd506go test fuzz v1 []byte("\x930\xc60") PK8bZ6*8f04fe5315f1d2fdKW(I-.QH+R(3䊎M,IP@J\PK8bZja*#$c3ef4fada1de0c6cKW(I-.QH+R(3䊎M,IPH0%M.PK8bZ{h*/c572bed5123c2c81KW(I-.QH+R(3䊎M,IPH17D"%M.PK 8bZ,p5b9c57e6fca72dafgo test fuzz v1 []byte("\xdb") PK8bZ$%9e1b259e6e24139dKW(I-.QH+R(3䊎M,IP2H4%M.PK 8bZ9yg a0991961f7622076go test fuzz v1 []byte("\xa10") PK 8bZ&&da9f0f9f99749b9dgo test fuzz v1 []byte("\x87\xa3000") PK 8bZhn$$2d6ed9f3cf476c07go test fuzz v1 []byte("0\xd20000") PK8bZͺ&*a56831f8fadcc866KW(I-.QH+R(3䊎M,IPHNa0aPK8bZS&'66fce0bc63fa3f54KW(I-.QH+R(3䊎M,IP2HNa%M.PK 8bZu""f3b3a68b968472cbgo test fuzz v1 []byte("0\xdc00") PK8bZŨ,"+a2fbc06c65dc8e9fKW(I-.QH+R(3䊎M,IPH6@J\PK8bZ";83b162ce8cfa4685KW(I-.QH+R(3䊎M,IPH6Ƈ4PK8bZ9r-H135efc083665885fKW(I-.QH+R(3䊎M,IPH60L6b*R %M.PK 7bZ|b##9142ab8e9df5330ego test fuzz v1 []byte("\xca00@2") PK7bZ~8(+7835221c9a10b2aeKW(I-.QH+R(3䊎M,IP4H`4%M.PK7bZ$(cc1975aa5397de04KW(I-.QH+R(3䊎M,IP2HN2%M.PK7bZh1Ib1587bcf5b0f0656KW(I-.QH+R(3䊎M,IP00`T0D1D"\b`PK7bZ/*Ep581c9ef1f5b4b57cKW(I-.QH+R(3䊎M,IPH21Q2 L H4B$UXBSLTr&PK 7bZ#Do!!efc18b4469cd84e2go test fuzz v1 []byte("\xc700") PK7bZE6Udcc694e39c21985dKW(I-.QH+R(3䊎M,IPHL10H6a q,H]I@I PK 7bZI##718845bb7017c673go test fuzz v1 []byte("\xdb0000") PK7bZsV'-a43beeebde9bdc5fKW(I-.QH+R(3䊎M,IP0H45%M.PK 7bZ1dbe634b087d12a9go test fuzz v1 []byte("\xda") PK7bZ`z).52af36a775d2688aKW(I-.QH+R(3䊎M,IPL6$@I PK7bZ,>i"+34a0c781f6c329f1KW(I-.QH+R(3䊎M,IP0DJ\PK7bZz|#$01fe2d71274479caKW(I-.QH+R(3䊎M,IPH0%M.PK7bZ^rbk+/a1c231d7e0b0ac2dKW(I-.QH+R(3䊎M,IPHL600Q"0(irPK 7bZ;(0b13bf4a3f17f531dKW(I-.QH+R(3䊎M,IPHL6@1)J\PK `Z%d00969495fe4d598go test fuzz v1 []byte("\xc3") PK `Z\Jaeb515d5153d5255go test fuzz v1 []byte("\xc9") PK `Zn##59f003e19b453d4bgo test fuzz v1 []byte("\xca0A20") PK `Zrsj""7bce9faa32caef11go test fuzz v1 []byte("0\xc500") PK`Z@087ff12821c398ea0cKW(I-.QH+R(3䊎M,IPH4H1$8HKSPK `ZHJA%%1fb844f21ac13640go test fuzz v1 []byte("00\xdb0000") PK `Zӻ'""b56cec8ff1d6f6dcgo test fuzz v1 []byte("0\xc700") PK`Zx^)#(dd2b18ced537ad8aKW(I-.QH+R(3䊎M,IPH4a%M.PK`Z\V*0daf9746740764f82KW(I-.QH+R(3䊎M,IPH450a#(mPK`Z&-.149d3d354de778f7KW(I-.QH+R(3䊎M,IPHL600Q%5 0PPK `Z'Q1a5390f68da01104go test fuzz v1 []byte("\xc5") PK `Z,iE""c044d35cc17c9b85go test fuzz v1 []byte("\xd5000") PKo`ZP&'512fdf445ea21facKW(I-.QH+R(3䊎M,IPHN402%M.PK o`Z''7bec83f488cf84fdgo test fuzz v1 []byte("\x87\xa30000") PK o`Z<$$923e88edf5309699go test fuzz v1 []byte("\x93\xc40") PK o`Z##95c5c017301dfd3ego test fuzz v1 []byte("0\xd5000") PK o`Z8""79cdf940c49720a0go test fuzz v1 []byte("0\xda00") PKo`Zm%(7f0df905be11530eKW(I-.QH+R(3䊎M,IPH13CI PK o`Z5&&61ece2819c3b61c2go test fuzz v1 []byte("\xde00\xd90") PKo`Z{6328cb4a4e7a9cf1ET58'LQ 33,o^8CC%S0w.G:>)3WF=&wYeP k'Qs4[p !BXs,2%L :|z223Dĵn^uX`Cz3E"mB73JWźo!.vB|dc KHJ4xHg ~}29e_nVR.!PacW[ =/1-MTq3[,r쨛sjȦxMbc3 4]xws%_pS꼣:Vj}7g?" )*-vdxwn9{%/[Po\Eu~y)G*p{sR~SV] +?@1BءsP~u_5%C sd6WzkxP gUJT 8K9҉7k bȜBB%ގtR_k3mS K9wHHdcEmrȏ$Oq\Y"͙ +f6ijՌLGv=ts>}UENڿΉ`,YI mO hD%)vKȟ1gR\{3k͹/ ߸lDm]},Ua3fJ3W=?Y<PKf`Z9O#6e2f08c7f31b402aKW(I-.QH+R(3䊎M,IP%M.PK f`ZQJ!!4d8c915f99937404go test fuzz v1 []byte("\xde00") PKf`Z <,Rf0a0adec759c734bJW(I-.QH+R(3䊎M,IPȍHJ+)HN-lTp@kG(6XpLCc%M.PKf`Zn(093cbf21ba246cb82KW(I-.QH+R(3䊎M,IPH600@†J\PKf`Z }(0a11c931f41569694KW(I-.QH+R(3䊎M,IPHL6@1J\PK f`Z0b&&1ecc3e54e723d94ego test fuzz v1 []byte("\xa500\"0\"") PKf`Z\\y&'c39603326290b194KW(I-.QH+R(3䊎M,IPH4H5a%M.PKf`Zj[ :G4297b0df816e9038KW(I-.QH+R(3䊎M,IPHL14 + LT$D TPKf`Zhw0c8784592168d4a55THa]IVafflxPܥ=ffC=R0[]1tg5h]=?Esvf;PLA2aֱ&ځVب<ĿF޿O~#XR2 8,L߃{8s8 W X؆b{DEH~8 C1F3_n=kjfa=sXbL?C[8]XSFNM}gYcU`Y8ثp錁{j͹l9!(Jnf Nt :TpO\yҋp'%2LvZu}EqPz3EzE\Է oi=JUo!.y 0Xa< ;:&$2<R}tX׿/ӟ~X%iq#br!ut[M\A 8!tY6q>nO%Fn}D_⨝sjPMĦwSN 4]xw/8)suQOUُByd}N v E[rηrzUz!z8W{ݹhuc8¹p^9ISG%a ix9H79{JQmM+ˌ_=TJ&CQ rOWVHg+5?0!0 51+Z*E%˙Ĉ3TNybGWRM 餢Щٯf5gn7q&LxHhJӾ6yk13%I8K`v9snMqAkA&%FQd6%nDU9LMYn|!IHt])O3}o83z=.p:fߗD፧7.Qv[no_=lFN ߱rPK [`ZwDn##a4cbbab596a649e9go test fuzz v1 []byte("\xc60000") PKZ`Zuw*D166c23d7bd356cd5KW(I-.QH+R(3䊎M,IPHL6002, a%M.PK Z`Zk((9445e169da66c11bgo test fuzz v1 []byte("\xa5\x800\"00") PK Z`Z72!!5dece255886f776ago test fuzz v1 []byte("\xa2&&") PKZ`ZMLD'/eb04c71576ff7c99KW(I-.QH+R(3䊎M,IPHL14@J\PK Z`ZŘF%%7cd7e6cf675bfa64go test fuzz v1 []byte("\xdc00\xc0") PKZ`ZI#/a340a72e017b154aKW(I-.QH+R(3䊎M,IPH4@J\PKZ`ZV>a2871c7ca2c7dc0c5THfIၙcwwcΜ33D!WZCMխKҽւ=,yg~+XԳwڞʦѷ[8 i^mO+U^%Vٞ޿nœ߾g[[$-=Ý]v Z<S+O. /~MH׸kBOޑ'љvь[d*80{#St.l-hc[XSZ6q!(i6pw/"֬kiSX)NAA&@)z.3E͓^9QWz(ؒx/".dI{Hv._}W P`[N?4qۇ R~FKT5N3ɼ Mdzl:qtט׿/O?,4ƽq 9ب(mRSm$wXjc ZL쏹p\T5VO;2rivѱ-&nJ76|#givѼ[+2ח'4w] , #R+;kcoʼnfsΧ_;;Jw^~<׍AOY X`_0Ut;&Ĺu`j>Y:GR춺qZmFկݡV[h IIIt{ٮdGw ;goţcnѡ 4y9 ySwKUUN ;);?G.Z9PK Q`Z?8cbf126b7cf0d023go test fuzz v1 []byte("\xc6") PKQ`Z3^93343dd7a6b769cfbcKW(I-.QH+R(3䊎M,IP24PKQ`Z8#1a6159a843f45fe11KW(I-.QH+R(3䊎M,IP47J\PKQ`Zp),Fc1ee882cd469dd21KW(I-.QH+R(3䊎M,IPHLVH20&PKQ`Z,_%;b8f5d828f18eba2aKW(I-.QH+R(3䊎M,IPLb lXI PK Q`ZdU$$d8ba08688915df2bgo test fuzz v1 []byte("0\xce0000") PK Q`Z0($''98e42dbefa1b68e2go test fuzz v1 []byte("\x9f\xce0000") PKQ`Z# $&01ae1c03237fcff3KW(I-.QH+R(3䊎M,IP2H11J\PK Q`Z2++78a0373444a4c190go test fuzz v1 []byte("0\xa5\x800\xff00") PKQ`Z)NSP"3d89474ea77ca6e41KW(I-.QH+R(3䊎M,IPH4†4PK Q`Zh((4a841706b7ac1dddgo test fuzz v1 []byte("\x9300\x8b000") PK Q`Z ͎$$414677d82a69902ago test fuzz v1 []byte("0\xc60000") PKQ`Z5.62377d042801ec922KW(I-.QH+R(3䊎M,IP2HL H$[@&PKQ`ZMy4#,67f16684047d3c2cKW(I-.QH+R(3䊎M,IP2H5FJ\PK Q`Zi]0836e45681fc24f6go test fuzz v1 []byte("\xc2") PKQ`Z@ #'8e5876cd720e270bKW(I-.QH+R(3䊎M,IPH4%M.PKQ`ZKvc6a0eff2895e8e025TFf]IWZa ~̠0suʇ;hsivny zٍ~egNSs8 .GiU㠲/v{oKlo ڼHg;' FGA_]n @)Wiθw8pY@:OËG@S^aw> :]qLFFsosTa[:BT% *eX4Z3x:`+EzF@&\Æ>8`!<34gQEU Ku:WYM} 2n %kyH6Ot׿2~,O>G)LBb ԭ%N3/Dѱ?qۃX'>ˌo}uɮ84.[&41ɢ"W3eV_b,b[+@ua{7`egr[g˃Fo(w^7mW)^NYv D3mtsc`2aJdsL Jr,=ۂЯ<)Cq3\; nv\D?_Ij3E94į+d2e7fd7dc979aec0go test fuzz v1 []byte("\xe2") PK F`ZB66aaf289903cc8fc08go test fuzz v1 []byte("\xc4") PKF`Z@`r+-015664aecf535a36KW(I-.QH+R(3䊎M,IPH41I) PK F`Z`O!!94f48f43e19904a7go test fuzz v1 []byte("0\x9c0") PK F`ZVg65c919510dfc46d8go test fuzz v1 []byte("x0x") PK F`Ze.8705ad4a950664adgo test fuzz v1 []byte("x") PKF`ZYS !66498f377f38b53eKW(I-.QH+R(3䊎M,IP2%M.PK F`Zcb1a9523e20b9df6go test fuzz v1 []byte("xx") PKF`ZY8 ,.828ef32dfefd84f0KW(I-.QH+R(3䊎M,IP00HHJ1%M.PKF`Zx ;#$a07e7ac566c1c3f6KW(I-.QH+R(3䊎M,IP00 %M.PK|Zou~R:2d6a834820be28e4JW(I-.QH+R(3䊎M,IPH12dH$@D;tlPt%!4귐I,&,p[ʉ"7U16[މa p.|96P´&PK|Zq$cffc6497f5042275KW(I-.QH+R(3䊎M,IP4@I PK|Zq} *f282ba758c8201a0퓵T1{wv;wwDjvVtJZ*:g@9w|f􌬜+iFW"dHIg qAAAAA_I)1GMćmT,*0B Ndiy8@)bu.]7J{P%,+Hm˳^lJ0526Ҫ?"t`ڊaC E=k\GP/) 뭛D)`M2/荰8KWtbPO go"v!*[UƔ4(F~_>A, f,vY 1V]>è03`X&/YL엛O9;H&1 X6jpl]7QydOhTu 10ph *x3R'uGfN o>3U8/w1KIf1q;#dEً^eJưβu7˺fۚUB(H6r!ڴp:w|7`^<8ٺG> vtYd#1g"ObZ9֒bhiX9V-@DAuo{8qtr@KJ o'z m)QҤCZ rG6RKߐ    M+~PK|ZDz{-c0ff7c1fb70ef23dJW(I-C Dm"pkpo.4  滾`XORAޙhmVf~2y(d12N WRʵY9dk d4PK|Z}0*848103e4b2a791bdKW(I-.QH+R(3䊎M,IPH6000 %M.PK|Z$X-+/2315462f2096611eKW(I-.QH+R(3䊎M,IP4H1006%M.PK|ZPRc5e1d33c8eec7f59bʡ@@n HFн]?J[nR?tBV֪\gU_ Nru;@I PK|ZVA8ade75f0e8186106JW(I-.QH+R(3䊎M,IPHI50 % HRnz}8$C$[.b* /4PK|Z|ZkvLy68vm:1(E PK{|Z$,39ba91d829ac6caf3KW(I-.QH+R(3䊎M,IPHH)1@I PKt|Z5(06298bcc9a2f866b2KW(I-.QH+R(3䊎M,IPH67005@J\PKf|Z-2225aef8aa99ecd22KW(I-.QH+R(3䊎M,IP4H1HKaPPK]|Zv}<X5b63278dd671edbfKW(I-.QH+R(3䊎M,IP2Ɂ3bܒY`(Ö3QPKP|ZC2+,967daf16b190d6e5KW(I-.QH+R(3䊎M,IPHI60(IQRI PKL|ZW%:457eedd2e1eab444JW(I-.QH+R(3䊎M,IP0 ,MPOG离IRR'`H # %M.PK#|ZjBc2ccf08f912594b0dcJW(I-.QH+R(3䊎M,IP$G(xjKJ4%M.PK|Z2"K6fdbbfb9cc2a7b20fJW(I-.QH+R(3䊎M,IPHI60@UUUUUUUUUUUUUOtI%M.PK|ZGaabb38de1a34ed12bJW(I-.QH+R(3䊎M,IPȍHJ+)HN-lL;t@10`"_x`* ~܆4<8ihPK |Z%(a2c29ded9f544a6feKW(I-.QH+R(3䊎M,IPHIV0H+irPK |ZD}871b83403e2845b3KW(I-.QH+R(3䊎M,IPHI1Gib*4QLYLELEjkLebLEHeZLa Pȶ4I1ɩ@!HI *IKYP* rң4&PK |ZA׀+,732487cb87d7cafcKW(I-.QH+R(3䊎M,IPHI50 %FI%M.PK {ZF-""8c84161e6449a30fgo test fuzz v1 []byte("\xc8 00") PK {ZS{##5e26b9c5e4951c18go test fuzz v1 []byte("\x91\xd9") PK{Zo#(13b60eda7dc483570KW(I-.QH+R(3䊎M,IP2H6H@I PK {ZVq##1719510a19ff65c0go test fuzz v1 []byte("0\xc8 00") PK{Z; )0206bf13edd8ab2d9KW(I-.QH+R(3䊎M,IPHH)1@%M.PK.zZfa/Ofed8cc330eee7424KW(I-.QH+R(3䊎M,IPHI3dE@I PK -zZ; ##c900288ac87c3095go test fuzz v1 []byte("\xd6\xff") PK+zZRӑ1B7bd1b2d93aace9cbKW(I-.QH+R(3䊎M,IP0HL4ds a`j4PK)zZ +/31d6f21377a52418KW(I-.QH+R(3䊎M,IP4H1HK3%M.PKzZ  5d4909b9627db557JW(I-.QH+R(3䊎M,I_690 ^Dv`6Y؏BK BBBX̀)?}!XjqUw1؜c 9C;D[E,eE"`k{O`zUMoqA?Ӧ.44w =IF2:_&PK zZ<{X9##e7612b3bcb919652go test fuzz v1 []byte("\x9c\xc9") PKzZ:6(a26485a258137d0fKW(I-.QH+R(3䊎M,IP2"! 4PK zZka((5bd7b2ae564165b2go test fuzz v1 []byte("\x96\xd6\xff0") PK zZ$$77fe103423067453go test fuzz v1 []byte("\xd7\xff0") PKyZ_ m98539cbc259c5eec1 0 S'*.wpU*wX>^ ө AU6N"7%x_^jzMg-~ H%[de2{PKyZ 5J{d7aa6c45e6612dceKW(I-.QH+R(3䊎M,IPHI00HNa A$i 4ȇt &g RPKyZS'0864f38b9d82832c7KW(I-.QH+R(3䊎M,IPH1005@J\PK yZJ))3845dafd81a6d61ego test fuzz v1 []byte("\x94\xc5 \x000") PKyZ/{19046a9d4f85c1beKW(I-.QH+R(3䊎M,IP0H600aj @I PK yZ)6F%%0d0443b5c9f22815go test fuzz v1 []byte("0\xd6\xff0") PKyZh2@9aa0279bab3cfc96KW(I-.QH+R(3䊎M,IP0H600TT20PPKyZ =:.afafbabc88cfe482KW(I-.QH+R(3䊎M,IPLɩ@0J R(5l!iC%M.PKyZp368facbdd41c0675aKW(I-.QH+R(3䊎M,IP0HI3Qz1?Fi%M.PKyZpbI77b56b364cd9b9225fKW(I-.QH+R(3䊎M,IPH17A!c"38.(irPKyZ T%37424dc37208b4307KW(I-.QH+R(3䊎M,IPHI3tZI PKyZC1c263f88292d7a63KW(I-.QH+R(3䊎M,IPLDIP A4Z!H2YlGdq!$V)%M.PK yZ"q%..a5a9bc18faf2368ago test fuzz v1 []byte("\x83\xa3000\xdd0000") PKyZEs^0206a48e663c516bJW(I-.QH+R(3䊎M,IPgAF :%:~V#|f+v^*|\yw鳬 PKyZˎ(19236fb760048bf86KW(I-.QH+R(3䊎M,IP2H1005@J\PKyZ;/ffc4e4982c99ab15KW(I-.QH+R(3䊎M,IPHI00HNa GQz0ЖF0VPKyZLU:-H7fa7c73a9222ff50KW(I-.QH+R(3䊎M,IPL& [SA(XI PKyZ݅/Hf7edd4382ca65bc9KW(I-.QH+R(3䊎M,IPƀ)Bfc@ ՈSPK yZ ""1d5113f3dac2e8dego test fuzz v1 []byte("0\xc5 0") PK syZUe++6afac65921ed2985go test fuzz v1 []byte("\x93\xd6\xff0000") PK^ZQ,L')98bb01dd867e1f21KW(I-.QH+R(3䊎M,IP2H60J\PK^Z *'(3d2d8afc349e7d86KW(I-.QH+R(3䊎M,IP4H4%M.PK^Zc#H%0edc0bbabc8f08caaKW(I-.QH+R(3䊎M,IPH1500@4PK^ZQ&+af9a24943824debcKW(I-.QH+R(3䊎M,IPHN004J\PK^ZFdab1703619e2af3aá0 @Q)rU<Shq \x\ݻd61b5a9c5866459dKW(I-.QH+R(3䊎M,IP45`Q0 F(#000LH124PK^ZS_%&cffaba9fd298e37cKW(I-.QH+R(3䊎M,IPH45)!%M.PK z^Z%mU$$22682e1d1c156dabgo test fuzz v1 []byte("\x9c\xc90") PK s^Zф##478a031cfb3caec5go test fuzz v1 []byte("\xcaaB10") PK n^Z&##2b9ba77aac5a434cgo test fuzz v1 []byte("\xdd0000") PK \^Zw$$319a57eb1729cc09go test fuzz v1 []byte("\x99\xc50") PK\^Z&/dd598b6f0d7e7b74KW(I-.QH+R(3䊎M,IPHI50@"@I PK[^Z"+03db1d799d2c995bKW(I-.QH+R(3䊎M,IPH6BJ\PKZ^ZeO)42ee384ebafdea3c1KW(I-.QH+R(3䊎M,IP2HN00@`PKV^Z\6)3732adfa9507c0e32KW(I-.QH+R(3䊎M,IPHN00XI PK R^Z T##3ced842d144ce0bfgo test fuzz v1 []byte("\xcaX12B") PK R^ZIW''8fd598c0b0b70c61go test fuzz v1 []byte("\x91\xd20000") PKR^ZY*3270e55f17e1ae88dKW(I-.QH+R(3䊎M,IPHN440ZI PK Q^Z4&&499ee962d3878966go test fuzz v1 []byte("\xd2\xc7000") PK O^Z@|&&04184687c494d0e5go test fuzz v1 []byte("\xca\xc9002") PKO^ZG\o/>8d6e70092c0d60abKW(I-.QH+R(3䊎M,IPHNaB6 %M.PK O^Z //251bd16081c96c92go test fuzz v1 []byte("000\xf3P\xddJ\xe9\ny") PK M^Z6M&&a803e65ab3021535go test fuzz v1 []byte("\xdc00\xd80") PKK^Z}+3c2fbc7d92fb98694KW(I-.QH+R(3䊎M,IPH4200PP&PKJ^ZDzF$3dbe18a320af8a424KW(I-.QH+R(3䊎M,IPHI60$4PK I^Z$$7511f9feb6e2c523go test fuzz v1 []byte("\x97\xc70") PKF^Z"9fd157240144a18628KW(I-.QH+R(3䊎M,IPHJ4Q2 /2@`TT &PK D^Z=f$$3a32871300d0ede9go test fuzz v1 []byte("\x9a\xd90") PK<^Z#%059a69715d3dbcecKW(I-.QH+R(3䊎M,IPHN6J\PK<^Z92%*80c1d69e0fef6f4aKW(I-.QH+R(3䊎M,IP2HNa %M.PK :^Z$$196386ba5dd7f154go test fuzz v1 []byte("0\xcaG000") PK8^Z$(f1cf6b4dda013af3KW(I-.QH+R(3䊎M,IP2HN3%M.PK 7^Z!!00d034de8e93c532go test fuzz v1 []byte("0\xc70") PK7^Z3(-6b356d060408d204KW(I-.QH+R(3䊎M,IP2HNt00a%M.PK6^Z7+=ecd8d50c26536014KW(I-.QH+R(3䊎M,IPHN4maSPK 4^Z`',,e4a2cea59ca94d5ego test fuzz v1 []byte("0\xcbxCa\xdb\"9&a") PK4^Z:c2b5cf2baf909e1eKW(I-.QH+R(3䊎M,IP4PK3^ZR#'3213741e23cf4c66KW(I-.QH+R(3䊎M,IPHN4%M.PK2^Z B'()e14aa6a2e3b262c6KW(I-.QH+R(3䊎M,IPHNbK 0PQPK 1^Z$$b3fccfcb4a1bb3adgo test fuzz v1 []byte("\x96\xd60") PK1^Zb*/72ee205bef46dff6KW(I-.QH+R(3䊎M,IPHN00bC(mPK0^ZY/E86b02b352f66b335KW(I-.QH+R(3䊎M,IP40L10(irPK /^Zr]''dab3c12b28e4eb31go test fuzz v1 []byte("\x96\xdc0000") PK.^Zg~)-916bcf0056d5e5a3KW(I-.QH+R(3䊎M,IPHNHKa0PPK .^Z* n&&994aefe3f3161121go test fuzz v1 []byte("\x95\xc8000") PK -^ZL%%674323bf25e0026ago test fuzz v1 []byte("\x99\xc500") PK^Z/9.@66420b78f19d2766KW(I-.QH+R(3䊎M,IP0@A (irPK^Z1'I1f8e317a5614bd7eKW(I-.QH+R(3䊎M,IPH23 2bJ\PK^Z+I+211a7da1091b353d3KW(I-.QH+R(3䊎M,IPH4200PRI PK^Z+-69bef522584520fcKW(I-.QH+R(3䊎M,IPHL20)M076%M.PK ^Zx_##b0d3c4c0164254d2go test fuzz v1 []byte("\xdf0000") PK^Z֑7M34a9365e2f554d91KW(I-.QH+R(3䊎M,IPHJ4)100HMc*RR\,PK ^Z{$$1f2d8499139dda73go test fuzz v1 []byte("0\xcaX210") PK ^Z&&7509b79e20ab8a9cgo test fuzz v1 []byte("\x89\xa3000") PK x]Z''80c8a68d341efcf9go test fuzz v1 []byte("\x9c\xde0000") PK v]ZD 68d9c4709e37c8fdgo test fuzz v1 []byte("\xc60") PK v]Z*##7a76df2c39c9cd0fgo test fuzz v1 []byte("\xcaX000") PK v]Z}--fbc44fc724e16808go test fuzz v1 []byte("\xcb700710\x80\x0e") PKv]Z'7#[818d3f725c48480fKW(I-.QH+R(3䊎M,IP0+irPKv]Zʁ(-d23d4dc198a4d0fcKW(I-.QH+R(3䊎M,IP2HN00a%M.PK v]ZV''f02654d3d20b0dd2go test fuzz v1 []byte("\x95\xdd0000") PKu]ZUe&+d3e04863c5b77044KW(I-.QH+R(3䊎M,IPH110ɩJ\PKu]Zz&+02947820728d0973KW(I-.QH+R(3䊎M,IPHN00J\PKu]Z)A447f150f114af1d7KW(I-.QH+R(3䊎M,IP40L14PKu]ZAF(-813b8b56fa57b913KW(I-.QH+R(3䊎M,IPH4204PKu]Z?1$39477b1e5e64e1733KW(I-.QH+R(3䊎M,IPH4B*irPK u]ZvU%%b76ea84650793eeago test fuzz v1 []byte("\xa50\r000") PK u]Z=>1 042a211094a537dcgo test fuzz v1 []byte("\xc50") PKu]Zmm"(5d13c09ddc41642d9KW(I-.QH+R(3䊎M,IP2HNa@I PKu]Zd^),a8bbeba97dfc39dbKW(I-.QH+R(3䊎M,IPH420J\PKu]ZD1Wc9bb2689b1df0bb2KW(I-.QH+R(3䊎M,IPHJH3Ƈ "5 WPKu]Zu&'b61bfa90eaf78d62KW(I-.QH+R(3䊎M,IP2HN0%M.PK#]Z3y)+eeeb386783b96f4dKW(I-.QH+R(3䊎M,IPH1500Rf PK"]ZW$'2aaac44fb7ca0ff0KW(I-.QH+R(3䊎M,IP2H11J\PK "]Zp$$90543ddccd935c3cgo test fuzz v1 []byte("\x97\xcc0") PK!]Z\k> Zc80e49df6352f0f7KW(I-.QH+R(3䊎M,IP2 (irPK ]ZJ!!14c88803bc46572cgo test fuzz v1 []byte("0\xc60") PK ]Z*%)c0d69181d8d818feKW(I-.QH+R(3䊎M,IPH4600RJ\PK ]Zq)>315f1e9276a48f57KW(I-.QH+R(3䊎M,IP40L14PK ]Z !!911c9740cb5654b1go test fuzz v1 []byte("0\xc50") PK ]ZL=!!de6ecf5b30c3a230go test fuzz v1 []byte("\xdc00") PK ]Z..$$138134c04a5e8b97go test fuzz v1 []byte("0\xd7\xff") PK ]Z7'95bccec2a2613ad82KW(I-.QH+R(3䊎M,IPH4 b 4PK ]Z´'C307f50f660926130KW(I-.QH+R(3䊎M,IP40 4PK ]Z54.@ef98d73e52f3e3eaKW(I-.QH+R(3䊎M,IPH23%PPK ]Zy.Z(2642739384af97d69KW(I-.QH+R(3䊎M,IPHL4QTPK ]Z7t((d0521842d34183b7go test fuzz v1 []byte("0\xcbx720x202") PK ]ZǍ] $(1c8fcd9caf27d2f9KW(I-.QH+R(3䊎M,IP2H16%M.PK ]Zi}Ժ*?78eb5c3185852504KW(I-.QH+R(3䊎M,IPLA¦D mPK ]ZGD&&5280dd9deb812fb7go test fuzz v1 []byte("\xca\xd9200") PK ]Z$$053969c3f889be77go test fuzz v1 []byte("0\xcaX012") PK ]Z-))3d65d4c355b028d3go test fuzz v1 []byte("\xde000\xc4000") PK ]Z ''34f365504bdba86bgo test fuzz v1 []byte("\xcb70071000") PK ]Za))<22f082d8d07dfc5cKW(I-.QH+R(3䊎M,IP40L14PK ]ZuM75d078845fdafa7cgo test fuzz v1 []byte("\xa0") PK ]Z`c''5189f2f29479f303go test fuzz v1 []byte("\x97\xda0000") PK ]Z 5192e187ce8578e7go test fuzz v1 []byte("\xd90") PK ]ZD$$9d446092f9ced572go test fuzz v1 []byte("0\xca9000") PK ]Z%%f76be9d6a05359b6go test fuzz v1 []byte("\x97\xc700") PK ]Z >&'f1f14a53c1755b58KW(I-.QH+R(3䊎M,IP200HN2%M.PK ]Z&K--efc8e31f0f722c84go test fuzz v1 []byte("\x89\xa200\xc60000") PK ]ZDaE'<1d6c56229985510bKW(I-.QH+R(3䊎M,IPH4b*S4PK ]ZUt 64299a15355d7b83go test fuzz v1 []byte("\xd60") PK ]ZR((15286ba6a881652cgo test fuzz v1 []byte("0\xcbX802A120") PK ]ZmV$'0e017e1d9065d12eKW(I-.QH+R(3䊎M,IPHN0%M.PK ]Zu7c''04e95e9d2a5dd9f2go test fuzz v1 []byte("\x85\xc10000") PK ]Z] b65cb5e49098fcd4go test fuzz v1 []byte("\xd70") PK ]Z\c?`%(5d9aa1e996b49f06KW(I-.QH+R(3䊎M,IP2H150PJ\PK ]Z5Xkcebdd63069600b2f% 0Cw8RxV[Gz=䅐29٤fY×cB4987 :|kD#e8}PK ]Z:Q/55ac92e3cad5127abKW(I-.QH+R(3䊎M,IPHL4H3H10AL%M.PK ]Z]%*8d5742d7ed0627f8KW(I-.QH+R(3䊎M,IPHNaPPK ]ZX3$-fd4f46237f024742KW(I-.QH+R(3䊎M,IPHI60@&4PK ]ZZ%!!e02fb8e99e9bef7bgo test fuzz v1 []byte("0\xcc0") PK]Zh &'c0a485e4a49895dfKW(I-.QH+R(3䊎M,IP2H11J\PK]Z6 (;40a1c480c0925362KW(I-.QH+R(3䊎M,IP00‚  4PK ]Z/E&&f943c2052dccdd73go test fuzz v1 []byte("0\xd400\xca") PK]Z2xGQ^029c5d499f082552KW(I-.QH+R(3䊎M,IPHJ4 b*R-dILELE!6TdC0H52PPK]Zl'+8d875db871234ccdKW(I-.QH+R(3䊎M,IPH43%M.PK]ZO;e14f2158b8abad759KW(I-.QH+R(3䊎M,IPH2302-@4*NN7/$PK]Z(,72fed8fab5235d51KW(I-.QH+R(3䊎M,IP45H14J\PK]ZĮ"#ce011589c7220798KW(I-.QH+R(3䊎M,IPH1a%M.PK ]ZyA0$$36b0866ba52acbf0go test fuzz v1 []byte("\x99\xc60") PK ]ZT796712476d3ab2517go test fuzz v1 []byte("\xc0") PK]Z=eo#$c2e40b76b86a8108KW(I-.QH+R(3䊎M,IPH15%M.PK ]Z4ʤ: 26c2c22372e1046fgo test fuzz v1 []byte("\xd80") PK ]ZX$$22ff85b7bbca8b8ago test fuzz v1 []byte("\x97\xd70") PK]Z38#065ed76fc09e4ab49KW(I-.QH+R(3䊎M,IPH0@J\PK]ZU;356e28f5914a0f16KW(I-.QH+R(3䊎M,IP2 4PK]ZOn)a43abbdbe84acbea8KW(I-.QH+R(3䊎M,IP43AI PK]Zo%X9c4689e67d3c503fKW(I-.QH+R(3䊎M,IPHM`%M.PK]Z+ '(16d075d19260b4abKW(I-.QH+R(3䊎M,IPH4H5a%M.PK ]Z vIr""82a6e840c6a758dago test fuzz v1 []byte("\xc5\b0") PK]ZE@n).920385a8a8c01861KW(I-.QH+R(3䊎M,IP4HNaPPK]Zc&)14f9d7f708e5fed8KW(I-.QH+R(3䊎M,IPHLT5%M.PK]Za&'133a7cefddd2b896KW(I-.QH+R(3䊎M,IPLHKa%M.PK ]Z+ j!!0f6f4e44ab2eaa2dgo test fuzz v1 []byte("0\xc80") PK ]Z\)$$74c3e2bb11a31cb5go test fuzz v1 []byte("0\xca&002") PK \Z\|((3afeedffe2b503f1go test fuzz v1 []byte("0\xc2\xd20000") PK\Z,defcb919f02421cbENřa O8qe#P/q[,vjw00.;5ѩpur)SNH09bތщ {t*u>&ʮliJϓm&亍JMrIJeH}}iϫ .PK \Zs[R''bfecb8fe26b5014fgo test fuzz v1 []byte("\x89\xc70000") PK \ZmA##f105c096c6666235go test fuzz v1 []byte("\x9e\xdc") PK\ZD&'1433da971285d530KW(I-.QH+R(3䊎M,IPH600a%M.PK\Z@M%219aa1260c87a899KW(I-.QH+R(3䊎M,IPHM4PK\ZQ#)97009b9a6b37c29dKW(I-.QH+R(3䊎M,IPHL4%M.PK\ZVC1;3a344f656fa2f474KW(I-.QH+R(3䊎M,IPHHMH6@H 4PK \Z6752914e7cc2f700go test fuzz v1 []byte("\xc8") PK \Z< 85f2617753981286go test fuzz v1 []byte("\xc90") PK \Z͈c))0acf5f605076b759go test fuzz v1 []byte("\xde00\xc40000") PK \ZV$dfc0416521e1e45fgo test fuzz v1 []byte("\x9b") PK\ZT?"7fe2f7764f8571faKW(I-.QH+R(3䊎M,IP%M.PK\Z1:WA'2e4cbedca5da50c77KW(I-.QH+R(3䊎M,IPH4GŖ)J\PK\ZFA'+2abb8db327f808cdKW(I-.QH+R(3䊎M,IP45 4PK\ZT^%;d628d960fabfc4c2KW(I-.QH+R(3䊎M,IP4Gh@I PK \Z -""a3525e9576eef09ago test fuzz v1 []byte("00\xc90") PK\Zf$\1c6d2c062c28efcfKW(I-.QH+R(3䊎M,IP24+irPK\Z#/db623e1d0f2b3accKW(I-.QH+R(3䊎M,IP4@J\PK \ZBS!((ee6c343ba8d8dd03go test fuzz v1 []byte("\xa3\xd50\xd4") PK \ZE419fe3cb21475e17go test fuzz v1 []byte("љ0") PK\Z,.63032602a9e83b75KW(I-.QH+R(3䊎M,IP45 Sbd*irPK \ZKрr##6f8efe3bf521bffcgo test fuzz v1 []byte("0\xc8000") PK\Z7)01011bee1101ef40eKW(I-.QH+R(3䊎M,IPL100Q0l`PK\Z#X%+f49a42001e0d97d2KW(I-.QH+R(3䊎M,IPH460J\PK\ZBib,$%89c9b7c977e2c45eKW(I-.QH+R(3䊎M,IP2H13%M.PK \Zj %%d423c25d7fad3cf9go test fuzz v1 []byte("\xa3\xd500") PK\Z)"+d7015e14e0ca4708KW(I-.QH+R(3䊎M,IP0@J\PK\ZyTg#$ca41f053db2bef30KW(I-.QH+R(3䊎M,IP2HKa%M.PK\Zrl6#'f128b6376d9a7293KW(I-.QH+R(3䊎M,IP4%M.PK\Z:#@3053bf7b821f4aa7KW(I-.QH+R(3䊎M,IPHN1 4PK \Zݰo%%609ef5c82ba2e88dgo test fuzz v1 []byte("\x99\xa200") PK \ZЗ##ce13c0c69cc75abbgo test fuzz v1 []byte("\xca1000") PK \Z|!!c03b67f28cfda21dgo test fuzz v1 []byte("\xd100") PK\Z.l%007625d4dec62c3d7KW(I-.QH+R(3䊎M,IP2@1)`&PK\Z)N&07e3811ab16ca3cc4KW(I-.QH+R(3䊎M,IP4HEJ\PK\ZF,0bf40482b893b33a2KW(I-.QH+R(3䊎M,IPH46QR dX$*irPK\Zӊ'B3b4c24f29f1812d5KW(I-.QH+R(3䊎M,IP2 |DI PK\Zv,Q%0a734fed3bb0c16ebKW(I-.QH+R(3䊎M,IP20H64@J\PK \Zނ&&abf8ac08e8ac878fgo test fuzz v1 []byte("\x80\xd5000") PK \ZB!!a4a053e5d207c10fgo test fuzz v1 []byte("0\xd70") PK \Zvqx 120481f927ef6ebdgo test fuzz v1 []byte("0\xc8") PK\Z^"'21068dcb60967afbKW(I-.QH+R(3䊎M,IPHKa%M.PK\Z *A"#eb59c2cd111f4734KW(I-.QH+R(3䊎M,IP0a%M.PK \Z|q$$c44d74651fd5a054go test fuzz v1 []byte("\xa2\xe80") PK\Zu&()7ee31750dd017749KW(I-.QH+R(3䊎M,IPH4VS1FJ\PK\ZJ#%c7fa459bd5b79b78KW(I-.QH+R(3䊎M,IP4%M.PK \Z:K{&&49896dd177803d65go test fuzz v1 []byte("\xd5000\x80") PK \Zϣ$$903ef559e6786089go test fuzz v1 []byte("0\xe0\xc3") PK\Z ',1887a4e3caba1884KW(I-.QH+R(3䊎M,IPH4214PK \Z]++137b58248be38c1ego test fuzz v1 []byte("\xa1&\xca\ufaf3+") PK\ZR,v '2ab772197dbd67582KW(I-.QH+R(3䊎M,IP200HNR(,%M.PK \Zu!~((e3db54a622b3393cgo test fuzz v1 []byte("\x9500\xa6000") PK \Z" !!fe449b52ccfd882dgo test fuzz v1 []byte("0\xd50") PK\Z(6e9bf03dea82bdb4KW(I-.QH+R(3䊎M,IP2@J\PK\Z@q)+f5b0853f08a18f91KW(I-.QH+R(3䊎M,IPHN100Q1@&PK\ZCT+832745cf220642267KW(I-.QH+R(3䊎M,IP20H46QQ"QI PK \ZRqG!!b7bdce0425e465b4go test fuzz v1 []byte("0\xd00") PK\Zfg"#8a05e93936e0a795KW(I-.QH+R(3䊎M,IPLa%M.PK \Zzd##6b9ef3a78980f61cgo test fuzz v1 []byte("\x85\xbf") PK\ZW%(9ed646e64df4e223KW(I-.QH+R(3䊎M,IP20H15%M.PK \Z' 310d7c7b40724225go test fuzz v1 []byte("\xc80") PK \Z((204619c4e56a0a0cgo test fuzz v1 []byte("\x950\x8b\xb1") PK\ZT%450a97754aa91bb3KW(I-.QH+R(3䊎M,IP2%M.PK\Z=#(979e3c5c8222f8a0KW(I-.QH+R(3䊎M,IP0 %M.PK\Zy*#$6e28740df08b7d4dKW(I-.QH+R(3䊎M,IP4%M.PK \Z?⹤##14d7ed611fe9a614go test fuzz v1 []byte("\x9e\xff") PK\ZNF$'47e310c0d6e96afbKW(I-.QH+R(3䊎M,IP2HN1%M.PK \Z6/""680a71aa168e0900go test fuzz v1 []byte("0\xc400") PK \ZyIq cc02199b09a91c74go test fuzz v1 []byte("\x800") PK \ZxՔ##c5bb29646fdfb8eego test fuzz v1 []byte("0\xa2000") PK \Z@&&b38c7dd0ab6a8126go test fuzz v1 []byte("\u037900x00") PK \Zs|##58b4b6bde519b325go test fuzz v1 []byte("\xe8\x03") PK \ZX&&47938c1f2bf7cab0go test fuzz v1 []byte("000\x95\bx0") PK\Zr$^$)453f87d4fefd3b74KW(I-.QH+R(3䊎M,IP204a%M.PK \ZRbdb8f27314986df9go test fuzz v1 []byte("\xbf") PK \Z)))51c5bd99c574adc4go test fuzz v1 []byte("0\x95\x8b\xb10") PK \Z&##64be2002f14d4048go test fuzz v1 []byte("\xba0000") PK \ZpcG##a059d1b8e49dc8d9go test fuzz v1 []byte("\x890000") PK \Z4tƔ!!f1b7286029f4c707go test fuzz v1 []byte("0\xba0") PK \ZGj 9f3758b4f22471c6go test fuzz v1 []byte("\xffx") PK \ZA U0362f32cb7c6159cgo test fuzz v1 []byte("0x") PK \Z; c002e4f69b9f45bago test fuzz v1 []byte("0\xae") PK \Z=""8521f6bbe11256f1go test fuzz v1 []byte("te\x8at") PK\Zl.&+ddb4f3130bc2a275KW(I-.QH+R(3䊎M,IP00bC(mPK\Z$'efb443cd279f2e81KW(I-.QH+R(3䊎M,IP004%M.PK \Z ""644ccb5a378f3b4cgo test fuzz v1 []byte("\xbaest") PK \Z~e3443030b91d09bbgo test fuzz v1 []byte("\xff") PK \Z!!af2206751755092fgo test fuzz v1 []byte("\xc400") PK \ZZ~p582528ddfad69eb5go test fuzz v1 []byte("0") PKzaZpRT477cdab906e48509KW(I-.QH+R(3䊎M,IPHIHp04400 Q )HN T$Tb*cJ4PK`Z]1dq748df6208a850a47-.DA{O 9ݹ؆- ̽3$ bJT{hh*w9qfN;mtuw׹ãpYfeJ(\{#DԸ,ԓp1M @Jzǫkt׈wlDΓc &rcir(-്k z ><(8ŐK*Y1u$]RSfFEOY08z7pPMe]b X򀽎5H{B_(# *ΰ܀JBѪdV{&4GRΩóGYo3~Qf˜9\VubHT5f d$S P~sHaUI GԫpO1դrviPK`Z{e0c7a42049ed5d0e-N1E|EC"n PP`]HQQRR  4T|gcνwӋvGu;݌[i:.̸6\c k^ uM\#ԓp1 &مF~^rkh׈ ts2\!P7;)l ^[SNʃH ) )Eݓ,s1c,ԥ̀ /WٓLK}X ?fziO3zn ه %v#xĐxDCYux( =w/$u/qu(P .DQ BAvYN?P\OfhHaUIR/_CxB*]!+3PK$]Zvl*07bdd647775b3f571@0@ѽh:1J )c%.a|ÿ;JqZe}kl<``````````@PK ]Z+642b0b48116b9909eaKW(I-.QH+R(3䊎M,IPHIH3׈04ɮH400PPPK\Z(&c00f4dac0f5cbdb9KW(I-.QH+R(3䊎M,IPH4200PPK\ZgŸ64e42d34cef864c690KW(I-.QH+R(3䊎M,IPHIH3׈04ɮH40O3PPKfZ?9-! c08511970c52cac3PKfZs&,X [9cbd5ff1293cd584PKfZYЏm 0feb94310c45a168PKfZ9* 7e29a70040eadf33PKfZ+E 3555071b7ee6c095bPKfZ +I 7828023fc4a65f53PKfZqCw8H afc9d0ac505ca452PK|fZ#. Kecc2404de0eb317cPKcfZO1I c5fefcce9c4ca6e3PKGfZwx(G 173cafab5d73c1fePKCfZcNi(K \468b2e60bf9cb387PK9fZg*0 3eb31eaf7130c9a7PK4fZ}U)s 838d3d47fdbd5112PK*fZgOC g617e3f62b9ef7b9fPKfZ tE f6fccf0c01bbc193PKfZ{6_2 z 3fb1247af5c8e536PKfZ-b>M 4b10a112d1248680PKfZX.7Y F 22ba144b431bb7bdPK eZA`** d2ba6fbf4985a14dPKeZGix.F  cddc8d95827bca03PKeZPt#> _ 6b04c9b62eb0046bPKeZYx' ^3799b0ecee7a25b0PKeZ./F 1e97fdf67b639878PKeZ^44# 30d6744f87e42339PKeZ82C rf3ac2ae146f29c91PKeZdx1 85f27ef9d588f212PKeZ0# 16e030f16df51afa1PKeZeN6 c047f1cd57a187cdPKkeZ͸bh3> ba1ea6b48d1a37c3PKheZ_W1. _9d0cfd610e35c6e4PKfeZ7f, 9b0fd346afbc5a3cPKeeZ],x f0a808f5e4a3f9c3PKYeZp7F6H recc9819e7a64065cPKJeZ~8R.' 14a80201786a3475PKFeZ, +c1d338d0747404cbPK@eZ{ x"# f1ac556a385f56bePK=eZb^,) af4eba763d8d1291PK>!! ofe32eaee83abe8f8PK:eZQ)9 4a33b0bdae2144cePK/eZܔ|. 9da1db79e2404886PK/eZk)gE qcb1b02d1aced37abPK eZ?4-E f2cc9c16249bd607PKdZd.y a3422962f427e8d88PKdZ$# 27f278a179212851PKdZId.T e7e180f3c6a21116PKdZ ){ jefd25b43e6cf1672PKdZ W- ddefda8f6cd9e85ePKdZ<)W 900fffab2de66871PKdZ!EMq( s3fb546a27c08c248PKdZ'$5})K 615b32df54036e12PKdZ݁GU 56bfb70f53e0e91dPKdZljR, 563908d1e91ccf6bPKdZ/*p 9c84cf6c30290733PKdZݟba.I U8ca20b2ee954118dPKdZ668O abe9fa99aa281b4cPKdZܝ'; 1aeb0e4d19537037PKdZ3j ) l3e50756f5d1b5225PK dZ$vp** 454b9beedb4522daPKdZrhO< 0085a7883be18fd4PKkdZ˲3 a7ead904c8b3e876PKcdZߚe6m a7f3e9d8f97435f7PK[dZL8) f7563de72baeedd9PKXdZ3RW5 - 7f7b7183b5ff779ePKVdZ144R 404ed7d11ebd1fcePKMdZY0U- !8ad6ea53be985c66PK.dZom !5f3a9f1a6267ee3cPK-dZ,5N /"196d6ff716ccf6fbPK+dZ1kK "4b465d1aece2205cPK%dZ+S-G- #d474588d95c01a05PK dZN,s #69dfc3facb78a6e6PK dZs'[ #9225ac86632a73e8PK dZKCk)0 /$2d422fb087dff37ePK dZY6E $776babaaf3be87e5PKdZx^< $0582c434ac4e73f4PKdZDل' v%9597aeb203394b91PKdZ/; %f8a52733a4803cabPKdZq 's (&d891cd7ad50b1474PKdZי/A }&13030553c271ebefPKdZ2 -e &f802194fafe56952PKcZv+7 5'7fec58b2bc92f483PKcZߔ5n '15f951851da4cc29PKcZ',n '24c899db97bd5c46PKcZCTp/g K(338e9a7af8a982c5PK cZ@## (94f3e594d7c57e97PKcZĂG. (4e8c003119b502a4PKcZ\F'[ U)42bf0b01ae718d3dPKcZ[)w )d3b11f2b74299b18PKcZ<+) *ea3799d2f2f6313cPKcZL'q' X*189732bac833df86PKcZ}+@ *b59905baefaccf6fPKcZcOs,= +5daf139b5e28aacdPKcZ#+ `+a0070dc23859283bPKcZZ{%\ +cc974ebf60d0a184PKcZxRJ% ,8f4846c1c4da49bePKcZmX'3 _,4136ee3428e3b4a4PKcZLر)= ,b2d35bf3ccb78ad7PKcZcQ: -0b6a97e23d1381d6PKcZE) -d9b8bfb3cc737808PKcZ W(` -264bd5350dff6912PKcZ'; I.db3c087673d8b8bcPKcZJ -*4 .f53db4406cc20c50PKcZL& .ea546b4326364c16PKcZ(Z3#[ J/4d03c3364d2769e8PKcZy<' /89a41a00a5983ba9PKcZ/+& /197639d1590b46a1PKcZ}( D0467dc228b023993aPKcZA*g 008d99cec261d9a2dPKcZH2 01eb2c3df606888d6PKcZ8] R1acc2bdd0cc624007PKcZƤ ' 1d77c3c3257485d5cPKcZu_o3 2bfdfc99b8ab07d17PKcZS% 23ec8954ba504cce5PKcZ?* 21f59fd6dc344b767PKcZ@-/ U380f06936f3e91de1PKcZ ~u+ 354760bf5bb354fe5PKcZ ,* 434bc8eae94b7e20ePKcZ'ꄀ,H c46821189b3d194e02PKcZ˸( 40966c927fb092dcePKcZSKu7 55cc23e080803409ePKcZo@-0 5d88a0c626202eed1PKcZX= 6c2b6666474271f65PKcZ %{ |64b8a37b87bb60bd0PKcZ̀' 698eb37ff8feaad65PKcZyedIW5 $7c77798a26c42cec4PKcZ!y( 73ed3791a4371b702PKcZ .d 73d6995cb96869ce2PKcZՇ82g M8fc5007de6f372011PKcZaJ-/ 8b8c598c7665bd47ePKcZ( 9d178f1526c70b303PKcZ5& ^99f3a2801724caa1fPKcZU1$/ 92beb55920bc07522PK cZ9--- :0535ef7002915c93PKcZDFN j:c86a06301ce4d4dePKcZGE*8 :9cfe1db7dd66d6eePKcZ30 >;4cedf90145333654PKcZ:x'g ;003178c0972ae2b5PKcZ,A ;bf04e1d5be312f3fPKcZM6 K<8763be0f78d455fcPKcZ.0 <474bfc3fb2236b2cPKcZdK+ =dec6020e94179374PKcZ~vQ d=5bf2fbccebcb2e1bPKcZJݤ*- =bea22f2ef7411e27PK|cZ$++ ;>7f0f62e57a24d5b2PKzcZB'4 >7d4406b55311826bPKycZ' >0ca91e1042f6fe66PKwcZV' >?5d564d2569804e4aPKwcZo* ?5bb630fc5cb3b6e9PKwcZ4'K ?f85e0e215968404fPKwcZLb'; @@ba475aa8b0765d56PKvcZ'[9 @ef09df52400fb9cdPKvcZ+t^8 A6cadc21cb7d9a1bfPKvcZf& A4400befbf46e403ePKucZ~'+ A32beac433f732338PKucZ^G7 SBb264387d662a203cPKtcZr)[ Be718f336685d54f1PKscZ;/ C9007ad839ff3e5e5PKscZ{J@, |C470e375ff83631e8PKocZ~a &3 C9102ce5bd7e113e8PKocZB{zL/ HD1748f19cdc175204PKncZB+ D24918f2154bd33adPKlcZM:% D401949dee6270739PKgcZu>( QEf44024f78eee96cdPK[cZ){e-} Ef852a57cfd998123PK[cZ& Fdbf3d514138e601fPK YcZA`## lFf0ec92faff1c40e6PKWcZ}%* F11d7506aa953cff3PKTcZzE2B G6d28e4236d9298fePKTcZq(> pGbca20182215dee88PKRcZ~*P', G66a5aaf00afffa8dPKQcZd*8($ 1H692407aadf9c857dPK PcZs## Ha1b0f0ed96fc5a65PKPcZf*'x H2ee43439228d1f45PKOcZK7q) -I56a7063f21ddb7c7PKNcZƯ&g Ifae884e9c85ec359PKLcZ>`3O I0c3d7b9c990817c1PKLcZԞ=)* 9J9d6adffda149eb0dPKJcZٽn&  Jb94a3c425071b1cdPKJcZɪ: J76ff3f9de8afa5b8PKHcZnr)@ LK1db255c19d7c786fPKEcZ%ٟ) K580d22619eb40d24PKEcZ5's Kfcf7ce5f8b768d9cPKEcZ.' OL7f14c59157d91c3fPKEcZMe(c L158dd906ebf199b2PKEcZN_B( Lcb8eb8162669df94PKDcZL(Z PMd480fd5dd74aa61bPKDcZ~۶x\|1 M16977312ef18a152PKDcZY/"l){ 0Nb74200d49eac5a01PKCcZHM*V Nef64c6be555569f7PKBcZK# N7b9d94f81332269fPKBcZ!%[ 0Oab35b5999a80e6fdPK@cZql(H O88f026782efc5be4PK@cZ%PP- Ofca5d5e4f0d6e3ccPK%[ W5a939c6b3da2f834PK&cZ?4_: Xb5ad934c54deb916PK&cZB6 H_efa3b88ceb70136aPKcZx#[ _80c14be18de13f11PKcZo%8 _4fe2315e44760656PKbZO& P`f42cb7a24d2fc461PKbZ% `cab0a0b5e0c93034PKbZp،& `49a366da449d3e8dPKbZ.R s0 Kaaebd82cf39f40bd4PKbZ+K=: a3d57fb4f44fc974cPKbZJM) "b53c130fe1e367e47PKbZt&S yb88c2896a4c4a66ebPKbZ+S bcb912f7b1ae1caa5PKbZA"& &c0ba8ef93dd5bc0f2PK bZ|## zcb70dbe264c0149ffPKbZ#%[% c2b9273a67dcd0442PKbZ .%Q d32edba166e178e90PKbZWW[3 qd97ddb1232a615035PKbZ?Ѓ%W dc64791a3a5b835a1PKbZ&/*S %ebf13d8343e048884PKbZj7%{ }e1146ee3bbb9d4cafPKbZU& ef16dcaf31ae443eaPKbZ!', $f144e0c547d31fc48PK bZ"ɧ2  yf21a9b7ddcb62a148PKbZYz  fc50af70b81cd3bf4PKbZuT%K g5a7d678091af622ePKbZƮ'k hg2911f3b805d36d2bPK bZPq## g00ac995ad8f0eee3PKbZ}% hec0b0a6beee6a660PKbZ-0 ah45ae6cecd21dfe59PKbZU# h5b03c93d1225a9cfPKbZ!$ ie9574b7ab8d72378PKbZyٖ%o _i8a6b6c9ec6d62fdaPKbZT0 i643291301813718cPKbZdK j62156ecbef1122eaPKbZn+) jbbbd50b6eb615adaPKbZl%S jce4d6e619ce3b546PKbZc&+ 3k30648f4693162d69PKbZ{P% k130ff6d39194017cPKbZ U_u> k588025d5104d93ecPKbZ'3 lb89e983954a6924aPKbZŗK& !me3b3275766ee213cPK bZG  umf56f5df1a03b45e2PKbZx)H%@ me4bb5dfb45bcabc8PK bZE#** 9n20f93677a620078ePKbZ&O(* nb61ebcf2835ed0caPKbZU%K nb49a220f66eb6658PKbZ(۝)9 :ode6f87f624dfc84fPK bZK  of4e1b331027da789PKbZvs0g o8d17bfbef1427724PKbZv'x)3 =p17cb2385e0f2d121PKbZhos4D p611894781b895022PK bZ-P  pa48285a604b159a0PKbZmh;-)7 Dqa9904c4c5f826cb0PKbZLP( qd096d5b040744ef7PKbZSX3 q7a37035edde54e41PKbZ*H wrcac4a2bf2a819bc3PKbZiw&, rde4cfcffef23d5fePKbZ@%? #s18e21fe26370eee3PKbZSJ,6 vs24541ab4eec9edd4PKbZDZ0M s27a7fd3e0af83361PKbZn04 .t3f298a7f1fb71690PKbZbεX# t871f765bf3b3f384PK bZ9}d  t21a246918a0ad1a4PKbZxW  +u1777748b71efb8cbPKbZa5), u3fe8751f6540063cPK bZ=00 Gv657df916da80c69ePKbZ B%)/ vdda5d94b836ee0ebPKbZQ?k$ v14f90b4e095016dbPKbZ 0N%; we9e8c598947beb6dPKbZ{LJQ) w349f3b9d9a7a70aaPKbZX() ?x89e63d4bfdde856cPK bZ}6  x4acd8cff27610c9fPKbZʐs.B xd91157217c4acd6cPKbZCX  ?y712e3819c6f593f9PKbZɡ'0 y00a6dd41f3c3f9efPKbZQ'q yd6d27ac8f0d9b5cdPKbZM'# 7z0d439a9dd82270e3PKbZW*I z59a1cb679d328c2fPKbZ48 z0d5ee4d19128cfc5PK bZT|  {48dde521c357318aPKbZr7P {71392354d097aadcPKbZgf( J|47f20999633b3550PKbZ>,7 |690caa3c808994cdPKbZ7H)'* |83942d7b31157d54PKbZ}R0$ O}50bea6ef5bd59bdePKbZT' }f7ceb7af64735a58PKbZ .%[ }d691022079880516PKbZC V( I~983c6ae38c531b1bPKbZ}P2 ~6f191e7e1ae3b719PKbZ_%K K5c96502c505b5680PKbZY% aadde78735313aacPK bZEJ## 7f1a1ddcde60647aPKbZ %' B4d138e8cf97cc221PKbZHeh%C 4ea48629b5765b26PKbZy' 3cb1ec509da8805fPKbZF* =a843018d04746439PKbZU& 3a7d6c774dbea4f8PKbZhk) 5b12e61eb8d37f87PKbZ9 "F3 @5bf3f38096ba5155PKbZu%; ae48aa57e7c71178PKbZ:& ab18e9f8f2f6414dPK bZC** [dc963eb9c2be0b18PKbZ߰(6 837d622845dad842PKbZ &' de173e262a0bf03ePKbZgN,B ]7a484aeea8c361d0PKbZoF*$H fc35ba7ae22bb2e0PKbZ\) b95623213cbef7a2PK bZA  `3759e863bb4871fePKbZK;?)7 7cb86950aa10b779PKbZ>4Y 4dd4671267ab6ccbPKbZ{H  g274329392a450b84PKbZDL' 1ac2f48d8388f947PKbZ*D`+7 u0ec9963511858f17PKbZD=.1 ·280dce35f50221caPKbZr\'?S *db252dbbea1acb1cPKbZb` v@ a09f4e463e2862f0PKbZz+C 16376d04f0669f10PKbZzF.U ^8331e5946d319ff4PK bZJ  eda3daae6e5f0a15PKbZ-$;&> a5b6d8d5525c6f80PKbZs,F \aff2f4c4c61f8523PKbZJt(* 96369bbc7f5364c8PKbZ{8+ 9c022b598f003eddPKbZC|(+ ed4c17bc2ef2d5275PK bZі** 088569ed28d933fePKbZ޸|'- 863b87e49eeba142PKbZֲR)3 h6e6a99cae2eedb18PKbZj0%' 73921c0aff3936d0PKbZ^w8(* 52dafe45eb662f12PKbZpTx$G h747d4591a53ab5f2PKbZ.M 682a5ede907fdff2PKbZ>0$C b0ff742d60aca993PKbZ1f)* he557d0d848963c10PKbZ(, b615824a106bf922PKbZ%/0 54d54af906ecfa48PK bZ  r5a0e8b33a26c7017PKbZ. -0 c6f3605ca20dbf81PKbZq'0 aee990da8a8aa7acPK bZQ## pb4c95cac84e389c4PK bZƪ  207b2e98276016dcPKbZr~)0 6731bc07597d05a0PKbZ8%3 f5a4b13fde7fc6314PKbZ>J+M c5fcfc936b09983bPKbZ0/A e43acea42c214f10PKbZI85 oa9f89bae14d820abPKbZ>oj+ Ւb631a3816c6236f6PKbZ.& .222253d2f256a689PKbZ.Mk+M 2bdb6fab7f4ad4ffPKbZ^2? ۓfb25ee4c02d0fb16PKbZ+)7 ;101cce5394e7b192PK bZ)"]  0f4241db31908ab3PKbZ1? 69609c061f389081PKbZ )/ ?8378bbc57f736d72PKbZ y*/ 9765291b43506962PKbZxj/> fbb3f405dffd71d4PKbZ},P Kdd762143a9193c90PKbZ>&+ b2119804cf041f29PKbZ-0 e1e38c894ed38686PKbZ ,- T286b954b2557300bPKbZq.); 3d377c969654f002PKbZÉ&U 826f37368fd82e0bPK bZAc++ Y8f84dce128f1e9afPKbZ6i# f2c3cc25cee229fcPKbZ-rjk 1c2e74d3c2210601PKbZq*: 491e88853a283327PK bZe  22d30eb9b323ee39PK bZ<## A4b45c790cd848ebcPKbZ"&7 00b37bc5886314f0PKbZ5T 106b78c09b6d9efdPK bZZR## h0d4dd6ee73760b42PKbZ<0'0 e98247f3393631aePK bZ## 02000aa5c5ba083bPKbZIb$ _329ebb82bddf3debPKbZz%K 4ea23aa68c0fcde1PKbZߧN1< c439e84c97af4a52PKbZK(xs'+ c9eab89897b411417PKbZ f&/ 3c4b2ba8b8030cd3PKbZ4q): 31672dca1afe7532PKbZ-9 cb022d36794dd59b3PKbZpġ). e61197d693a15cf5PKbZ]Μ%3 e017c28f4f9c70b5PK bZ%% ha1ce55a31ed57937PKbZȇ', 9cdaddaec7d02239PKbZ[*9 3fa87b1a3dbf33a2PKbZ)4 h67319d450633be87PKbZ~.T 98220682987dabafPKbZג*8 bf77dc1a16f2f0e4PKbZ){( sb45dc5fafb2b2a24PKbZ7(* ɡd2a240918db7399ePKbZ)? !59cbde2ad2ec149ePKbZrRԃR xa3c65ba3e9234151PKbZ*d 1I )1a3d6fd1a24da1bePKbZsx*- da0202887134f2bdPKbZ,9 b2b854a238819b20PKbZ& :74f0e9119b026652PK bZQI&& 09e3fd5d009f0963PKbZH'+ ae132544ccf6c2bfPKbZb b-0 7f031a9ab2640c9b7PK bZc** 7e77954ab59fd0aaPKbZt:%' d3a58a86db67fbfePKbZh Z =cdf50fcdb9fed59dPKbZP', 7a472bc56f336f04PK bZ'' 51871b31df6b597fPKbZv(+ 5a5327139bdfb0baePKbZ&5%H 537e8cfcd3a16324PKbZk (* ާ76d8e432b866e7faPKbZ=)1 4868c955821d1328aPK bZ^ ++ 106d5a4a06a9ddddPKbZ,; 9c7c8651ec4d386fPKbZBW >36b8912cf8e87d85PKbZ88') é35c8b636f2f64bb0PKbZ&N-o 30f11456db187cb1PKbZ}6{)(- se46e0e64cca1dd40PKbZ;[1^ ɪ8599d9c1a5418f5fPKbZ#($) (90fe6f0db8c9909fPKbZ(* z879f00acd57f79ebPKbZ:A"; Ы5cbcb028fe775289PKbZvT# bb29db531cf90d41PKbZZEF%K qd57ddc02261eac0dPKbZW9N). Ĭ9aa3caf2b40bd374PKbZEʯ@ e80330b25945a688PKbZN's fcb5c2ef2edb215fPK bZ|}'' ޭ159b641156c7236bPKbZ|14 39cd38d651131496ePKbZ;'3 b39e1404324e0471PKbZϷ(* a957663fb088c17aPKbZl+F =8a299a076cc823fdPK bZ S  ecb58f468e5c81bcPKbZ gsj#0 91e35bba2ba7ece2PKbZoK(7 568dcd2dbb8485503PKbZ\r%_ 2f2502e2cd6b50c2PK bZSP(( ް74f24b1268513f63PKbZ6-9 40dbd3bb36652dea4PKbZ-P-9 f7050afa9fd792dbPKbZ,& 9c716bcb01e989f0PK bZo3)) >03c44fafda133431PKbZ:', 93afb6f2e6047c44PKbZȫz/S df1ea30296a230ddPKbZ$D G71ee0d710ebfdf10PKbZ7F', 7bbe914327114ff6PKbZ!G#' 394c6bcf15359de5PKbZ!f  _35b41542d4c0324aPKbZ:\-0 62316805e2f2ee84PKbZj-0 77743019f97976b3PK bZ.** c70a35473229f4c18PKbZZ&) b80f14544beea8e2PKbZ4)#0 159405efafbf448ePKbZP)O `135664452cb4ad7dPK bZ^ 7f62a7fbc91fef1bPKbZ 1z,0 1b8e61f1a3d9c1e9PKbZ_*0 ^46bfead06fa24e89PKbZUѥ$3 91cbbfa5280957b4PKbZb%0u8p 6dd52219afb2f29fPK bZ.## n32b1f0a50de5867aPKbZ.b'( 7b5ad3dee4be020fPKbZr+ 3416631125146960PKbZ3$' mdcffa2890a427599PKbZp%? 00ed2a45439ee248PKbZO[)1 13fa1457fd4acb42PKbZs3%3 i0fdc1af02e581ef1PK bZ^g(( e1deae552f6dea72PKbZ(7 bffa6a8b95eba591PK bZ  hdb3f0b1887e1e487PK bZr  1c42ab505246346bPKbZw [ bdb34052e0c746dePKbZVR/.N R59198523573af9daPKbZ6b?&' 3371ccc512e364acPK bZ## 0eb82d3731f066bePK bZ!%% S14abba83e3fc3f92PK bZe#P(( aa71670f34f28543PKbZ6'+ ff2d7fdeaaae88a0PK bZ*1$$ Q604893782519daabPKbZ(, 1938ed13b31fc17cPKbZ *1 c3dfc2b1b45363e3PKbZ伫-&, Qbc905bdfa57fa30ePKbZ$' f01966a601fa7a4dPKbZ;'+ c28c1f7a82ab0927PK bZ -- La0bf20bf817ca92ePKbZ%`S&, c21c321fec84a016PKbZ*E d11197f8a129b863PKbZ=D-Z S88c63546de12a3a8PKbZ>2I#' ad4596439bd03e7dPKbZ~%& 273c318c349a0b88PKbZ4 {)* R5006a54067bffd83PKbZHO'( 536f43eb997090e0PKbZd#& 71374973dbfe1244PKbZ˚%* Oc1ebd4180890ad66PKbZ'* 20d0b14017ad3685PKbZnҠQ(+ 40bb4baebf8379cePKbZ%"/ M45a079189a7f6ffdPKbZE*5 9619a5f25080bd95PK bZ":0&& bfc7b6c091165ad5PK bZD Ie5078d8d62a13bc5PK{bZhY)A 1f49a7e0a44d4587PK{bZƄU aed5c14114d35eb2PKybZ O#' c693ee2dd1eeac8fPK ybZ{-k 69eec6f09e6bd419PKybZ&){'C =e150dd9ef2bda6c7PK ybZ jY['' f46f9d07fdfb0927PKybZC`(j be3baab8840c74c4PKybZ4]# =58d490ba11cfc399PKybZ}&, a6b5640f6626dd01PK ybZ@fK&& 3a299f4d1e65deddPKybZPnk#$ 6b32a411cdaff0e8bPKybZ>+&' a476c59b215d33e5PKybZv"# 892e0b2fe30ba509PK ybZ78{## +00f94e9e89bf84e5PKybZI% |bfce69550ea5f02dPKybZq|9  63f6bb3d79c9aa0bPKbbZµO#$ 6d6b439f6019a8a43PKbbZ-9 d35acc2391f05d33PKbbZ*w+0 a5d15fddaa591435PK bbZk2 ;e54acb8fdbccf6fcPK bbZ@4'' c51272640ca653f6PK bbZ"(** 459317e990483bd4PKbbZ蚴%+ 5afc083acf4c7eda7PKbbZT(3 4b1823f6cc7bd87fPKbbZ!OD,w 8f0aeac1d897c37fPKbbZPbB4G 884ed8eea41320da3PKbbZT+@F 968ab67d1ec1679aPK `bZY  6b92cb4024aa7026PK`bZJ"; 291eb8e4bef0dd11PK`bZ2{-d 0e3fac69bf1b30fdcPK`bZdpI: f3748bcecda7c119PK YbZ c8fb35720121533cPK YbZy O310dada39b0f6930PKYbZ%̩)O 722b8a1a02f74014PKXbZĈ() 5b2e1fa371b53526PK XbZR## I0073638dc475c110PK XbZ 968de876d3c7cc89PKXbZ79'* 39826f08ad3852d4PKXbZɴ*)/ <c4d7d367340535fbPK XbZDZ"" 3ef2b217f3de4c6ePK XbZ҃  dbc71bf32aba139aPKXbZwo` 1d4114174acf20a4cPK@bZ|#0 1bfa74f017461bc1PK@bZ(0 c0501bd3e195b8bdPK@bZZʑ#& fe8c5911a58026df3PK=bZtSr). 796384628d94789ePK=bZ}b fa0aab07ed555c74PK=bZ i/ %& 2555358db0dcda4ePK =bZ)) e2ef1462d12a536aPK=bZ} \W$' H8a5e84f8641f9d35PK =bZ͍** a384617f58ef1c04PK=bZZa#[ ea6c7a9046b93bc7PK =bZ9;s Cdd0716e54cde9bc8PK=bZ[oIn  ef90fb60d9b326ffPK=bZlf(3 fb81b3ddc5702527PK=bZC%3 4793e29afa6040371PK =bZW$$ 8a234f5953618cb2PK=bZ5L#[ 4b71f737dbbe7931PK ead0a81777eee969PKi"+ 34a0c781f6c329f1PK7bZz|#$ 01fe2d71274479caPK7bZ^rbk+/ Ja1c231d7e0b0ac2dPK 7bZ;(0 b13bf4a3f17f531dPK `Z% ud00969495fe4d598PK `Z\J aeb515d5153d5255PK `Zn## 59f003e19b453d4bPK `Zrsj"" `7bce9faa32caef11PK`Z@08 7ff12821c398ea0cPK `ZHJA%% 1fb844f21ac13640PK `Zӻ'"" ab56cec8ff1d6f6dcPK`Zx^)#( dd2b18ced537ad8aPK`Z\V*0 daf9746740764f82PK`Z&-. Z149d3d354de778f7PK `Z'Q 1a5390f68da01104PK `Z,iE"" c044d35cc17c9b85PKo`ZP&' R512fdf445ea21facPK o`Z'' 7bec83f488cf84fdPK o`Z<$$ 923e88edf5309699PK o`Z## M95c5c017301dfd3ePK o`Z8"" 79cdf940c49720a0PKo`Zm%( 7f0df905be11530ePK o`Z5&& A61ece2819c3b61c2PKo`Z{ 6328cb4a4e7a9cf1PKf`Z9O# w 6e2f08c7f31b402aPK f`ZQJ!! 4d8c915f99937404PKf`Z <,R  f0a0adec759c734bPKf`Zn(0 93cbf21ba246cb82PKf`Z }(0 a11c931f41569694PK f`Z0b&& ? 1ecc3e54e723d94ePKf`Z\\y&' c39603326290b194PKf`Zj[ :G 4297b0df816e9038PKf`Zhw O0c8784592168d4a5PK [`ZwDn## 2a4cbbab596a649e9PKZ`Zuw*D 166c23d7bd356cd5PK Z`Zk(( 9445e169da66c11bPK Z`Z72!! 15dece255886f776aPKZ`ZMLD'/ eb04c71576ff7c99PK Z`ZŘF%% 7cd7e6cf675bfa64PKZ`ZI#/ (a340a72e017b154aPKZ`ZV> ya2871c7ca2c7dc0cPK Q`Z? ]8cbf126b7cf0d023PKQ`Z3^93 343dd7a6b769cfbcPKQ`Z8#1 a6159a843f45fe11PKQ`Zp),F Hc1ee882cd469dd21PKQ`Z,_%; b8f5d828f18eba2aPK Q`ZdU$$ d8ba08688915df2bPK Q`Z0($'' G98e42dbefa1b68e2PKQ`Z# $& 01ae1c03237fcff3PK Q`Z2++ 78a0373444a4c190PKQ`Z)NSP"3 Gd89474ea77ca6e41PK Q`Zh(( 4a841706b7ac1dddPK Q`Z ͎$$ 414677d82a69902aPKQ`Z5.6 ?2377d042801ec922PKQ`ZMy4#, 67f16684047d3c2cPK Q`Zi] 0836e45681fc24f6PKQ`Z@ #' 98e5876cd720e270bPKQ`ZKv c6a0eff2895e8e02PK F`Z## o!17b5cb3bc0b7fe59PK F`Z] !96bcf568b6b09b98PKF`Z *- "f7ffd151838837c2PK F`Zu),, Z"bba6de44d9b249a9PKF`ZM+ "d8729013defaf4cfPKF`Zh$% #73b800ac8f4b90d5PK F`Z`O'' S#3b2e402824012e95PK F`Z& #0dff09cdb27b30c0PK F`Z<ѥ&& #47fd686ea0d83483PK F`Z@!! I$8a4c274f6e390d4dPKF`ZL=(* $fe9d358c57dab7aePKF`ZI?#' $bd5d0fc024805dcbPK F`Zz ?%caf81e9797b19c76PKF`Zf #+ %f504592ab7d00baaPKF`Z.W4# %93d6f7bc0d93f998PKF`Z=l#$ &&f86f6f3af50cb14bPKF`ZH:$9 w&3e1e749a8bd27793PK F`Z> &d2e7fd7dc979aec0PK F`ZB66 'aaf289903cc8fc08PKF`Z@`r+- c'015664aecf535a36PK F`Z`O!! '94f48f43e19904a7PK F`ZVg (65c919510dfc46d8PK F`Ze. W(8705ad4a950664adPKF`ZYS ! (66498f377f38b53ePK F`Z (cb1a9523e20b9df6PKF`ZY8 ,. 9)828ef32dfefd84f0PKF`Zx ;#$ )a07e7ac566c1c3f6PK|Zou~R: )2d6a834820be28e4PK|Zq$ *cffc6497f5042275PK|Zq} * *f282ba758c8201a0PK|ZDz{- -c0ff7c1fb70ef23dPK|Z}0* .848103e4b2a791bdPK|Z$X-+/ .2315462f2096611ePK|ZPRc L/5e1d33c8eec7f59bPK|ZVA /8ade75f0e8186106PK|ZW%: q3457eedd2e1eab444PK#|ZjBc2 3ccf08f912594b0dcPK|Z2"K6 f4fdbbfb9cc2a7b20fPK|ZGa 4abb38de1a34ed12bPK |Z%(a n52c29ded9f544a6fePK |ZD} 5871b83403e2845b3PK |ZA׀+, o6732487cb87d7cafcPK {ZF-"" 68c84161e6449a30fPK {ZS{## 75e26b9c5e4951c18PK{Zo#(1 i73b60eda7dc483570PK {ZVq## 71719510a19ff65c0PK{Z; )0 8206bf13edd8ab2d9PK.zZfa/O g8fed8cc330eee7424PK -zZ; ## 8c900288ac87c3095PK+zZRӑ1B 97bd1b2d93aace9cbPK)zZ +/ t931d6f21377a52418PKzZ   95d4909b9627db557PK zZ<{X9## :e7612b3bcb919652PKzZ:6( ;a26485a258137d0fPK zZka(( Z;5bd7b2ae564165b2PK zZ$$ ;77fe103423067453PKyZ_ m <98539cbc259c5eecPKyZ 5J{ <d7aa6c45e6612dcePKyZS'0 =864f38b9d82832c7PK yZJ)) j=3845dafd81a6d61ePKyZ/{ =19046a9d4f85c1bePK yZ)6F%% >0d0443b5c9f22815PKyZh2@ q>9aa0279bab3cfc96PKyZ =:. >afafbabc88cfe482PKyZp3 9?68facbdd41c0675aPKyZpbI77 ?b56b364cd9b9225fPKyZ T%3 ?7424dc37208b4307PKyZC R@1c263f88292d7a63PK yZ"q%.. @a5a9bc18faf2368aPKyZEs^ A0206a48e663c516bPKyZˎ(1 A9236fb760048bf86PKyZ;/ Bffc4e4982c99ab15PKyZLU:-H jB7fa7c73a9222ff50PKyZ݅/H Bf7edd4382ca65bc9PK yZ "" "C1d5113f3dac2e8dePK syZUe++ rC6afac65921ed2985PK^ZQ,L') C98bb01dd867e1f21PK^Z *'( D3d2d8afc349e7d86PK^Zc#H%0 uDedc0bbabc8f08caaPK^ZQ&+ Daf9a24943824debcPK^ZF Edab1703619e2af3aPK ^Z&& E998c15b48feedccfPK ^Zm$B&& E06dd56d367d00fb0PK^Z`@ 8F5e59fceba0f67eedPK ^ZG,&& F8f7b3cd99ecf7623PK ^Zе## Fc696e14364605930PK ^ZzK## KG5658a22ad56a820cPK^Z51N.6 G0ca905da24c15a83PK^Z{3#( Gcd09ed52c3d37ed6PK ^Z]m  IH2dda7ed8078049e6PK ^Z0zn&& H65de07d749ea1077PK^Zh|t'F Hfdc51e03470dfb20PK^ZhK @I134f0e7a63fff046PK ^Z4Ei$$ 3J78a4bb474958153aPK^Z-0 J94d02ab5753a4693PK ^Z"K&& Je744dba94f30d6cbPK^Z\_$  4K8a917e896f3a443cPK^ZF*- 6L03fcdbce091d68f9PK^Z YW'+ L804df06efb40fa38PK^Zvt;{#8 L8af4702538fbbfecPK^Z%& 4M68a2d7ed364d1e3aPK^ZJ> Md61b5a9c5866459dPK^ZS_%& Mcffaba9fd298e37cPK z^Z%mU$$ FN22682e1d1c156dabPK s^Zф## N478a031cfb3caec5PK n^Z&## N2b9ba77aac5a434cPK \^Zw$$ :O319a57eb1729cc09PK\^Z&/ Odd598b6f0d7e7b74PK[^Z"+ O03db1d799d2c995bPKZ^ZeO)4 0P2ee384ebafdea3c1PKV^Z\6)3 P732adfa9507c0e32PK R^Z T## P3ced842d144ce0bfPK R^ZIW'' /Q8fd598c0b0b70c61PKR^ZY*3 Q270e55f17e1ae88dPK Q^Z4&& Q499ee962d3878966PK O^Z@|&& 0R04184687c494d0e5PKO^ZG\o/> R8d6e70092c0d60abPK O^Z // R251bd16081c96c92PK M^Z6M&& >Sa803e65ab3021535PKK^Z}+3 Sc2fbc7d92fb98694PKJ^ZDzF$3 Sdbe18a320af8a424PK I^Z$$ =T7511f9feb6e2c523PKF^Z"9f Td157240144a18628PK D^Z=f$$ T3a32871300d0ede9PK<^Z#% HU059a69715d3dbcecPK<^Z92%* U80c1d69e0fef6f4aPK :^Z$$ U196386ba5dd7f154PK8^Z$( >Vf1cf6b4dda013af3PK 7^Z!! V00d034de8e93c532PK7^Z3(- V6b356d060408d204PK6^Z7+= 5Wecd8d50c26536014PK 4^Z`',, We4a2cea59ca94d5ePK4^Z: Wc2b5cf2baf909e1ePK3^ZR#' 5X3213741e23cf4c66PK2^Z B'() Xe14aa6a2e3b262c6PK 1^Z$$ Xb3fccfcb4a1bb3adPK1^Zb*/ .Y72ee205bef46dff6PK0^ZY/E Y86b02b352f66b335PK /^Zr]'' Ydab3c12b28e4eb31PK.^Zg~)- 8Z916bcf0056d5e5a3PK .^Z* n&& Z994aefe3f3161121PK -^ZL%% Z674323bf25e0026aPK^Z/9.@ 6[66420b78f19d2766PK^Z1'I [1f8e317a5614bd7ePK^Z+I+2 [11a7da1091b353d3PK^Z+- @\69bef522584520fcPK ^Zx_## \b0d3c4c0164254d2PK^Z֑7M \34a9365e2f554d91PK ^Z{$$ O]1f2d8499139dda73PK ^Z&& ]7509b79e20ab8a9cPK x]Z'' ]80c8a68d341efcf9PK v]ZD  J^68d9c4709e37c8fdPK v]Z*## ^7a76df2c39c9cd0fPK v]Z}-- ^fbc44fc724e16808PKv]Z'7#[ D_818d3f725c48480fPKv]Zʁ(- _d23d4dc198a4d0fcPK v]ZV'' _f02654d3d20b0dd2PKu]ZUe&+ @`d3e04863c5b77044PKu]Zz&+ `02947820728d0973PKu]Z)A `447f150f114af1d7PKu]ZAF(- ?a813b8b56fa57b913PKu]Z?1$3 a9477b1e5e64e1733PK u]ZvU%% ab76ea84650793eeaPK u]Z=>1  :b042a211094a537dcPKu]Zmm"(5 bd13c09ddc41642d9PKu]Zd^), ba8bbeba97dfc39dbPKu]ZD1W 5cc9bb2689b1df0bb2PKu]Zu&' cb61bfa90eaf78d62PK#]Z3y)+ ceeeb386783b96f4dPK"]ZW$' ?d2aaac44fb7ca0ff0PK "]Zp$$ d90543ddccd935c3cPK!]Z\k> Z dc80e49df6352f0f7PK ]ZJ!! 1e14c88803bc46572cPK ]Z*%) ec0d69181d8d818fePK ]Zq)> e315f1e9276a48f57PK ]Z !! *f911c9740cb5654b1PK ]ZL=!! yfde6ecf5b30c3a230PK ]Z..$$ f138134c04a5e8b97PK ]Z7'9 g5bccec2a2613ad82PK ]Z´'C og307f50f660926130PK ]Z54.@ gef98d73e52f3e3eaPK ]Zy.Z(2 h642739384af97d69PK ]Z7t(( vhd0521842d34183b7PK ]ZǍ] $( h1c8fcd9caf27d2f9PK ]Zi}Ժ*? i78eb5c3185852504PK ]ZGD&& vi5280dd9deb812fb7PK ]Z$$ i053969c3f889be77PK ]Z-)) j3d65d4c355b028d3PK ]Z '' sj34f365504bdba86bPK ]Za))< j22f082d8d07dfc5cPK ]ZuM k75d078845fdafa7cPK ]Z`c'' lk5189f2f29479f303PK ]Z  k5192e187ce8578e7PK ]ZD$$ l9d446092f9ced572PK ]Z%% alf76be9d6a05359b6PK ]Z >&' lf1f14a53c1755b58PK ]Z&K-- mefc8e31f0f722c84PK ]ZDaE'< cm1d6c56229985510bPK ]ZUt  m64299a15355d7b83PK ]ZR(( n15286ba6a881652cPK ]ZmV$' \n0e017e1d9065d12ePK ]Zu7c'' n04e95e9d2a5dd9f2PK ]Z]  ob65cb5e49098fcd4PK ]Z\c?`%( Qo5d9aa1e996b49f06PK ]Z5Xk ocebdd63069600b2fPK ]Z:Q/5 *p5ac92e3cad5127abPK ]Z]%* p8d5742d7ed0627f8PK ]ZX3$- pfd4f46237f024742PK ]ZZ%!! ,qe02fb8e99e9bef7bPK]Zh &' {qc0a485e4a49895dfPK]Z6 (; q40a1c480c0925362PK ]Z/E&& %rf943c2052dccdd73PK]Z2xGQ^ yr029c5d499f082552PK]Zl'+ r8d875db871234ccdPK]ZO;e Ms14f2158b8abad759PK]Z(, s72fed8fab5235d51PK]ZĮ"# tce011589c7220798PK ]ZyA0$$ \t36b0866ba52acbf0PK ]ZT7 t96712476d3ab2517PK]Z=eo#$ tc2e40b76b86a8108PK ]Z4ʤ:  Lu26c2c22372e1046fPK ]ZX$$ u22ff85b7bbca8b8aPK]Z38#0 u65ed76fc09e4ab49PK]ZU; =v356e28f5914a0f16PK]ZOn)a v43abbdbe84acbea8PK]Zo%X v9c4689e67d3c503fPK]Z+ '( 4w16d075d19260b4abPK ]Z vIr"" w82a6e840c6a758daPK]ZE@n). w920385a8a8c01861PK]Zc&) 0x14f9d7f708e5fed8PK]Za&' x133a7cefddd2b896PK ]Z+ j!! x0f6f4e44ab2eaa2dPK ]Z\)$$ 'y74c3e2bb11a31cb5PK \Z\|(( yy3afeedffe2b503f1PK\Z, ydefcb919f02421cbPK \Zs[R'' zbfecb8fe26b5014fPK \ZmA## zf105c096c6666235PK\ZD&' C{1433da971285d530PK\Z@M% {219aa1260c87a899PK\ZQ#) {97009b9a6b37c29dPK\ZVC1; ;|3a344f656fa2f474PK \Z |6752914e7cc2f700PK \Z<  |85f2617753981286PK \Z͈c)) 5}0acf5f605076b759PK \ZV$ }dfc0416521e1e45fPK\ZT?" }7fe2f7764f8571faPK\Z1:WA'2 &~e4cbedca5da50c77PK\ZFA'+ {~2abb8db327f808cdPK\ZT^%; ~d628d960fabfc4c2PK \Z -"" #a3525e9576eef09aPK\Zf$\ s1c6d2c062c28efcfPK\Z#/ db623e1d0f2b3accPK \ZBS!(( ee6c343ba8d8dd03PK \ZE l419fe3cb21475e17PK\Z,. 63032602a9e83b75PK \ZKрr## 6f8efe3bf521bffcPK\Z7)0 c1011bee1101ef40ePK\Z#X%+ f49a42001e0d97d2PK\ZBib,$% 89c9b7c977e2c45ePK \Zj %% _d423c25d7fad3cf9PK\Z)"+ d7015e14e0ca4708PK\ZyTg#$ ca41f053db2bef30PK\Zrl6#' Sf128b6376d9a7293PK\Z:#@ 3053bf7b821f4aa7PK \Zݰo%% 609ef5c82ba2e88dPK \ZЗ## Hce13c0c69cc75abbPK \Z|!! c03b67f28cfda21dPK\Z.l%0 07625d4dec62c3d7PK\Z)N&0 ;7e3811ab16ca3cc4PK\ZF,0 bf40482b893b33a2PK\Zӊ'B 3b4c24f29f1812d5PK\Zv,Q%0 >a734fed3bb0c16ebPK \Zނ&& abf8ac08e8ac878fPK \ZB!! a4a053e5d207c10fPK \Zvqx  4120481f927ef6ebdPK\Z^"' 21068dcb60967afbPK\Z *A"# ҇eb59c2cd111f4734PK \Z|q$$ "c44d74651fd5a054PK\Zu&() t7ee31750dd017749PK\ZJ#% ʈc7fa459bd5b79b78PK \Z:K{&& 49896dd177803d65PK \Zϣ$$ o903ef559e6786089PK\Z ', 1887a4e3caba1884PK \Z]++ 137b58248be38c1ePK\ZR,v '2 oab772197dbd67582PK \Zu!~(( Ċe3db54a622b3393cPK \Z" !! fe449b52ccfd882dPK\Z( i6e9bf03dea82bdb4PK\Z@q)+ f5b0853f08a18f91PK\ZCT+8 32745cf220642267PK \ZRqG!! fb7bdce0425e465b4PK\Zfg"# 8a05e93936e0a795PK \Zzd## 6b9ef3a78980f61cPK\ZW%( V9ed646e64df4e223PK \Z'  310d7c7b40724225PK \Z(( 204619c4e56a0a0cPK\ZT% M450a97754aa91bb3PK\Z=#( 979e3c5c8222f8a0PK\Zy*#$ 6e28740df08b7d4dPK \Z?⹤## <14d7ed611fe9a614PK\ZNF$' 47e310c0d6e96afbPK \Z6/"" ߏ680a71aa168e0900PK \ZyIq  /cc02199b09a91c74PK \ZxՔ## }c5bb29646fdfb8eePK \Z@&& ΐb38c7dd0ab6a8126PK \Zs|## "58b4b6bde519b325PK \ZX&& s47938c1f2bf7cab0PK\Zr$^$) Ǒ453f87d4fefd3b74PK \ZR bdb8f27314986df9PK \Z))) f51c5bd99c574adc4PK \Z&## 64be2002f14d4048PK \ZpcG## a059d1b8e49dc8d9PK \Z4tƔ!! _f1b7286029f4c707PK \ZGj  9f3758b4f22471c6PK \ZA U 0362f32cb7c6159cPK \Z;  Gc002e4f69b9f45baPK \Z="" 8521f6bbe11256f1PK\Zl.&+ ddb4f3130bc2a275PK\Z$' 9efb443cd279f2e81PK \Z "" 644ccb5a378f3b4cPK \Z~ ەe3443030b91d09bbPK \Z!! (af2206751755092fPK \ZZ~p w582528ddfad69eb5PKzaZpRT 477cdab906e48509PK`Z]1dq A748df6208a850a47PK`Z{ e0c7a42049ed5d0ePK$]Zvl* 07bdd647775b3f57PK ]Z+64 Q2b0b48116b9909eaPK\Z(& c00f4dac0f5cbdb9PK\ZgŸ64 e42d34cef864c690PKEEomsgp-1.6.1/msgp/unsafe.go000066400000000000000000000015361511433505400152510ustar00rootroot00000000000000//go:build (!purego && !appengine) || (!appengine && purego && unsafe) package msgp import ( "unsafe" ) // NOTE: // all of the definition in this file // should be repeated in appengine.go, // but without using unsafe const ( // spec says int and uint are always // the same size, but that int/uint // size may not be machine word size smallint = unsafe.Sizeof(int(0)) == 4 ) // UnsafeString returns the byte slice as a volatile string // THIS SHOULD ONLY BE USED BY THE CODE GENERATOR. // THIS IS EVIL CODE. // YOU HAVE BEEN WARNED. func UnsafeString(b []byte) string { return *(*string)(unsafe.Pointer(&b)) } // UnsafeBytes returns the string as a byte slice // // Deprecated: // Since this code is no longer used by the code generator, // UnsafeBytes(s) is precisely equivalent to []byte(s) func UnsafeBytes(s string) []byte { return []byte(s) } msgp-1.6.1/msgp/write.go000066400000000000000000000536271511433505400151320ustar00rootroot00000000000000package msgp import ( "encoding" "encoding/binary" "encoding/json" "errors" "fmt" "io" "math" "reflect" "sync" "time" ) const ( // min buffer size for the writer minWriterSize = 18 ) // Sizer is an interface implemented // by types that can estimate their // size when MessagePack encoded. // This interface is optional, but // encoding/marshaling implementations // may use this as a way to pre-allocate // memory for serialization. type Sizer interface { Msgsize() int } var ( // Nowhere is an io.Writer to nowhere Nowhere io.Writer = nwhere{} btsType = reflect.TypeOf(([]byte)(nil)) writerPool = sync.Pool{ New: func() any { return &Writer{buf: make([]byte, 2048)} }, } ) func popWriter(w io.Writer) *Writer { wr := writerPool.Get().(*Writer) wr.Reset(w) return wr } func pushWriter(wr *Writer) { wr.w = nil wr.wloc = 0 writerPool.Put(wr) } // freeW frees a writer for use // by other processes. It is not necessary // to call freeW on a writer. However, maintaining // a reference to a *Writer after calling freeW on // it will cause undefined behavior. func freeW(w *Writer) { pushWriter(w) } // Require ensures that cap(old)-len(old) >= extra. func Require(old []byte, extra int) []byte { l := len(old) c := cap(old) r := l + extra if c >= r { return old } else if l == 0 { return make([]byte, 0, extra) } // the new size is the greater // of double the old capacity // and the sum of the old length // and the number of new bytes // necessary. c <<= 1 if c < r { c = r } n := make([]byte, l, c) copy(n, old) return n } // nowhere writer type nwhere struct{} func (n nwhere) Write(p []byte) (int, error) { return len(p), nil } // Marshaler is the interface implemented // by types that know how to marshal themselves // as MessagePack. MarshalMsg appends the marshalled // form of the object to the provided // byte slice, returning the extended // slice and any errors encountered. type Marshaler interface { MarshalMsg([]byte) ([]byte, error) } // Encodable is the interface implemented // by types that know how to write themselves // as MessagePack using a *msgp.Writer. type Encodable interface { EncodeMsg(*Writer) error } // Writer is a buffered writer // that can be used to write // MessagePack objects to an io.Writer. // You must call *Writer.Flush() in order // to flush all of the buffered data // to the underlying writer. type Writer struct { w io.Writer buf []byte wloc int } // NewWriter returns a new *Writer. func NewWriter(w io.Writer) *Writer { if wr, ok := w.(*Writer); ok { return wr } return popWriter(w) } // NewWriterSize returns a writer with a custom buffer size. func NewWriterSize(w io.Writer, sz int) *Writer { // we must be able to require() 'minWriterSize' // contiguous bytes, so that is the // practical minimum buffer size if sz < minWriterSize { sz = minWriterSize } buf := make([]byte, sz) return NewWriterBuf(w, buf) } // NewWriterBuf returns a writer with a provided buffer. // 'buf' is not used when the capacity is smaller than 18, // custom buffer is allocated instead. func NewWriterBuf(w io.Writer, buf []byte) *Writer { if cap(buf) < minWriterSize { buf = make([]byte, minWriterSize) } buf = buf[:cap(buf)] return &Writer{ w: w, buf: buf, } } // Encode encodes an Encodable to an io.Writer. func Encode(w io.Writer, e Encodable) error { wr := NewWriter(w) err := e.EncodeMsg(wr) if err == nil { err = wr.Flush() } freeW(wr) return err } func (mw *Writer) flush() error { if mw.wloc == 0 { return nil } n, err := mw.w.Write(mw.buf[:mw.wloc]) if err != nil { if n > 0 { mw.wloc = copy(mw.buf, mw.buf[n:mw.wloc]) } return err } mw.wloc = 0 return nil } // Flush flushes all of the buffered // data to the underlying writer. func (mw *Writer) Flush() error { return mw.flush() } // Buffered returns the number bytes in the write buffer func (mw *Writer) Buffered() int { return len(mw.buf) - mw.wloc } func (mw *Writer) avail() int { return len(mw.buf) - mw.wloc } func (mw *Writer) bufsize() int { return len(mw.buf) } // NOTE: this should only be called with // a number that is guaranteed to be less than // len(mw.buf). typically, it is called with a constant. // // NOTE: this is a hot code path func (mw *Writer) require(n int) (int, error) { c := len(mw.buf) wl := mw.wloc if c-wl < n { if err := mw.flush(); err != nil { return 0, err } wl = mw.wloc } mw.wloc += n return wl, nil } func (mw *Writer) Append(b ...byte) error { if mw.avail() < len(b) { err := mw.flush() if err != nil { return err } } mw.wloc += copy(mw.buf[mw.wloc:], b) return nil } // push one byte onto the buffer // // NOTE: this is a hot code path func (mw *Writer) push(b byte) error { if mw.wloc == len(mw.buf) { if err := mw.flush(); err != nil { return err } } mw.buf[mw.wloc] = b mw.wloc++ return nil } func (mw *Writer) prefix8(b byte, u uint8) error { const need = 2 if len(mw.buf)-mw.wloc < need { if err := mw.flush(); err != nil { return err } } prefixu8(mw.buf[mw.wloc:], b, u) mw.wloc += need return nil } func (mw *Writer) prefix16(b byte, u uint16) error { const need = 3 if len(mw.buf)-mw.wloc < need { if err := mw.flush(); err != nil { return err } } prefixu16(mw.buf[mw.wloc:], b, u) mw.wloc += need return nil } func (mw *Writer) prefix32(b byte, u uint32) error { const need = 5 if len(mw.buf)-mw.wloc < need { if err := mw.flush(); err != nil { return err } } prefixu32(mw.buf[mw.wloc:], b, u) mw.wloc += need return nil } func (mw *Writer) prefix64(b byte, u uint64) error { const need = 9 if len(mw.buf)-mw.wloc < need { if err := mw.flush(); err != nil { return err } } prefixu64(mw.buf[mw.wloc:], b, u) mw.wloc += need return nil } // Write implements io.Writer, and writes // data directly to the buffer. func (mw *Writer) Write(p []byte) (int, error) { l := len(p) if mw.avail() < l { if err := mw.flush(); err != nil { return 0, err } if l > len(mw.buf) { return mw.w.Write(p) } } mw.wloc += copy(mw.buf[mw.wloc:], p) return l, nil } // implements io.WriteString func (mw *Writer) writeString(s string) error { l := len(s) if mw.avail() < l { if err := mw.flush(); err != nil { return err } if l > len(mw.buf) { _, err := io.WriteString(mw.w, s) return err } } mw.wloc += copy(mw.buf[mw.wloc:], s) return nil } // Reset changes the underlying writer used by the Writer func (mw *Writer) Reset(w io.Writer) { mw.buf = mw.buf[:cap(mw.buf)] mw.w = w mw.wloc = 0 } // WriteMapHeader writes a map header of the given // size to the writer func (mw *Writer) WriteMapHeader(sz uint32) error { switch { case sz <= 15: return mw.push(wfixmap(uint8(sz))) case sz <= math.MaxUint16: return mw.prefix16(mmap16, uint16(sz)) default: return mw.prefix32(mmap32, sz) } } // WriteArrayHeader writes an array header of the // given size to the writer func (mw *Writer) WriteArrayHeader(sz uint32) error { switch { case sz <= 15: return mw.push(wfixarray(uint8(sz))) case sz <= math.MaxUint16: return mw.prefix16(marray16, uint16(sz)) default: return mw.prefix32(marray32, sz) } } // WriteNil writes a nil byte to the buffer func (mw *Writer) WriteNil() error { return mw.push(mnil) } // WriteFloat writes a float to the writer as either float64 // or float32 when it represents the exact same value func (mw *Writer) WriteFloat(f float64) error { f32 := float32(f) if float64(f32) == f { return mw.prefix32(mfloat32, math.Float32bits(f32)) } return mw.prefix64(mfloat64, math.Float64bits(f)) } // WriteFloat64 writes a float64 to the writer func (mw *Writer) WriteFloat64(f float64) error { return mw.prefix64(mfloat64, math.Float64bits(f)) } // WriteFloat32 writes a float32 to the writer func (mw *Writer) WriteFloat32(f float32) error { return mw.prefix32(mfloat32, math.Float32bits(f)) } // WriteDuration writes a time.Duration to the writer func (mw *Writer) WriteDuration(d time.Duration) error { return mw.WriteInt64(int64(d)) } // WriteInt64 writes an int64 to the writer func (mw *Writer) WriteInt64(i int64) error { if i >= 0 { switch { case i <= math.MaxInt8: return mw.push(wfixint(uint8(i))) case i <= math.MaxInt16: return mw.prefix16(mint16, uint16(i)) case i <= math.MaxInt32: return mw.prefix32(mint32, uint32(i)) default: return mw.prefix64(mint64, uint64(i)) } } switch { case i >= -32: return mw.push(wnfixint(int8(i))) case i >= math.MinInt8: return mw.prefix8(mint8, uint8(i)) case i >= math.MinInt16: return mw.prefix16(mint16, uint16(i)) case i >= math.MinInt32: return mw.prefix32(mint32, uint32(i)) default: return mw.prefix64(mint64, uint64(i)) } } // WriteInt8 writes an int8 to the writer func (mw *Writer) WriteInt8(i int8) error { return mw.WriteInt64(int64(i)) } // WriteInt16 writes an int16 to the writer func (mw *Writer) WriteInt16(i int16) error { return mw.WriteInt64(int64(i)) } // WriteInt32 writes an int32 to the writer func (mw *Writer) WriteInt32(i int32) error { return mw.WriteInt64(int64(i)) } // WriteInt writes an int to the writer func (mw *Writer) WriteInt(i int) error { return mw.WriteInt64(int64(i)) } // WriteUint64 writes a uint64 to the writer func (mw *Writer) WriteUint64(u uint64) error { switch { case u <= (1<<7)-1: return mw.push(wfixint(uint8(u))) case u <= math.MaxUint8: return mw.prefix8(muint8, uint8(u)) case u <= math.MaxUint16: return mw.prefix16(muint16, uint16(u)) case u <= math.MaxUint32: return mw.prefix32(muint32, uint32(u)) default: return mw.prefix64(muint64, u) } } // WriteByte is analogous to WriteUint8 func (mw *Writer) WriteByte(u byte) error { return mw.WriteUint8(u) } // WriteUint8 writes a uint8 to the writer func (mw *Writer) WriteUint8(u uint8) error { return mw.WriteUint64(uint64(u)) } // WriteUint16 writes a uint16 to the writer func (mw *Writer) WriteUint16(u uint16) error { return mw.WriteUint64(uint64(u)) } // WriteUint32 writes a uint32 to the writer func (mw *Writer) WriteUint32(u uint32) error { return mw.WriteUint64(uint64(u)) } // WriteUint writes a uint to the writer func (mw *Writer) WriteUint(u uint) error { return mw.WriteUint64(uint64(u)) } // WriteBytes writes binary as 'bin' to the writer func (mw *Writer) WriteBytes(b []byte) error { if uint64(len(b)) > math.MaxUint32 { return ErrLimitExceeded } sz := uint32(len(b)) var err error switch { case sz <= math.MaxUint8: err = mw.prefix8(mbin8, uint8(sz)) case sz <= math.MaxUint16: err = mw.prefix16(mbin16, uint16(sz)) default: err = mw.prefix32(mbin32, sz) } if err != nil { return err } _, err = mw.Write(b) return err } // WriteBytesHeader writes just the size header // of a MessagePack 'bin' object. The user is responsible // for then writing 'sz' more bytes into the stream. func (mw *Writer) WriteBytesHeader(sz uint32) error { switch { case sz <= math.MaxUint8: return mw.prefix8(mbin8, uint8(sz)) case sz <= math.MaxUint16: return mw.prefix16(mbin16, uint16(sz)) default: return mw.prefix32(mbin32, sz) } } // WriteBool writes a bool to the writer func (mw *Writer) WriteBool(b bool) error { if b { return mw.push(mtrue) } return mw.push(mfalse) } // WriteString writes a messagepack string to the writer. // (This is NOT an implementation of io.StringWriter) func (mw *Writer) WriteString(s string) error { if uint64(len(s)) > math.MaxUint32 { return ErrLimitExceeded } sz := uint32(len(s)) var err error switch { case sz <= 31: err = mw.push(wfixstr(uint8(sz))) case sz <= math.MaxUint8: err = mw.prefix8(mstr8, uint8(sz)) case sz <= math.MaxUint16: err = mw.prefix16(mstr16, uint16(sz)) default: err = mw.prefix32(mstr32, sz) } if err != nil { return err } return mw.writeString(s) } // WriteStringHeader writes just the string size // header of a MessagePack 'str' object. The user // is responsible for writing 'sz' more valid UTF-8 // bytes to the stream. func (mw *Writer) WriteStringHeader(sz uint32) error { switch { case sz <= 31: return mw.push(wfixstr(uint8(sz))) case sz <= math.MaxUint8: return mw.prefix8(mstr8, uint8(sz)) case sz <= math.MaxUint16: return mw.prefix16(mstr16, uint16(sz)) default: return mw.prefix32(mstr32, sz) } } // WriteStringFromBytes writes a 'str' object // from a []byte. func (mw *Writer) WriteStringFromBytes(str []byte) error { if uint64(len(str)) > math.MaxUint32 { return ErrLimitExceeded } sz := uint32(len(str)) var err error switch { case sz <= 31: err = mw.push(wfixstr(uint8(sz))) case sz <= math.MaxUint8: err = mw.prefix8(mstr8, uint8(sz)) case sz <= math.MaxUint16: err = mw.prefix16(mstr16, uint16(sz)) default: err = mw.prefix32(mstr32, sz) } if err != nil { return err } _, err = mw.Write(str) return err } // WriteComplex64 writes a complex64 to the writer func (mw *Writer) WriteComplex64(f complex64) error { o, err := mw.require(10) if err != nil { return err } mw.buf[o] = mfixext8 mw.buf[o+1] = Complex64Extension big.PutUint32(mw.buf[o+2:], math.Float32bits(real(f))) big.PutUint32(mw.buf[o+6:], math.Float32bits(imag(f))) return nil } // WriteComplex128 writes a complex128 to the writer func (mw *Writer) WriteComplex128(f complex128) error { o, err := mw.require(18) if err != nil { return err } mw.buf[o] = mfixext16 mw.buf[o+1] = Complex128Extension big.PutUint64(mw.buf[o+2:], math.Float64bits(real(f))) big.PutUint64(mw.buf[o+10:], math.Float64bits(imag(f))) return nil } // WriteMapStrStr writes a map[string]string to the writer func (mw *Writer) WriteMapStrStr(mp map[string]string) (err error) { err = mw.WriteMapHeader(uint32(len(mp))) if err != nil { return } for key, val := range mp { err = mw.WriteString(key) if err != nil { return } err = mw.WriteString(val) if err != nil { return } } return nil } // WriteMapStrIntf writes a map[string]interface to the writer func (mw *Writer) WriteMapStrIntf(mp map[string]any) (err error) { err = mw.WriteMapHeader(uint32(len(mp))) if err != nil { return } for key, val := range mp { err = mw.WriteString(key) if err != nil { return } err = mw.WriteIntf(val) if err != nil { return } } return } // WriteTime writes a time.Time object to the wire. // // Time is encoded as Unix time, which means that // location (time zone) data is removed from the object. // The encoded object itself is 12 bytes: 8 bytes for // a big-endian 64-bit integer denoting seconds // elapsed since "zero" Unix time, followed by 4 bytes // for a big-endian 32-bit signed integer denoting // the nanosecond offset of the time. This encoding // is intended to ease portability across languages. // (Note that this is *not* the standard time.Time // binary encoding, because its implementation relies // heavily on the internal representation used by the // time package.) func (mw *Writer) WriteTime(t time.Time) error { t = t.UTC() o, err := mw.require(15) if err != nil { return err } mw.buf[o] = mext8 mw.buf[o+1] = 12 mw.buf[o+2] = TimeExtension putUnix(mw.buf[o+3:], t.Unix(), int32(t.Nanosecond())) return nil } // WriteTimeExt will write t using the official msgpack extension spec. // https://github.com/msgpack/msgpack/blob/master/spec.md#timestamp-extension-type func (mw *Writer) WriteTimeExt(t time.Time) error { // Time rounded towards zero. secPrec := t.Truncate(time.Second) remain := t.Sub(secPrec).Nanoseconds() asSecs := secPrec.Unix() switch { case remain == 0 && asSecs > 0 && asSecs <= math.MaxUint32: // 4 bytes o, err := mw.require(6) if err != nil { return err } mw.buf[o] = mfixext4 mw.buf[o+1] = byte(msgTimeExtension) binary.BigEndian.PutUint32(mw.buf[o+2:], uint32(asSecs)) return nil case asSecs < 0 || asSecs >= (1<<34): // 12 bytes o, err := mw.require(12 + 3) if err != nil { return err } mw.buf[o] = mext8 mw.buf[o+1] = 12 mw.buf[o+2] = byte(msgTimeExtension) binary.BigEndian.PutUint32(mw.buf[o+3:], uint32(remain)) binary.BigEndian.PutUint64(mw.buf[o+3+4:], uint64(asSecs)) default: // 8 bytes o, err := mw.require(10) if err != nil { return err } mw.buf[o] = mfixext8 mw.buf[o+1] = byte(msgTimeExtension) binary.BigEndian.PutUint64(mw.buf[o+2:], uint64(asSecs)|(uint64(remain)<<34)) } return nil } // WriteJSONNumber writes the json.Number to the stream as either integer or float. func (mw *Writer) WriteJSONNumber(n json.Number) error { if n == "" { // The zero value outputs the 0 integer. return mw.push(0) } ii, err := n.Int64() if err == nil { return mw.WriteInt64(ii) } ff, err := n.Float64() if err == nil { return mw.WriteFloat(ff) } return err } // WriteIntf writes the concrete type of 'v'. // WriteIntf will error if 'v' is not one of the following: // - A bool, float, string, []byte, int, uint, or complex // - A map of supported types (with string keys) // - An array or slice of supported types // - A pointer to a supported type // - A type that satisfies the msgp.Encodable interface // - A type that satisfies the msgp.Extension interface func (mw *Writer) WriteIntf(v any) error { if v == nil { return mw.WriteNil() } switch v := v.(type) { // preferred interfaces case Encodable: return v.EncodeMsg(mw) case Extension: return mw.WriteExtension(v) // concrete types case bool: return mw.WriteBool(v) case float32: return mw.WriteFloat32(v) case float64: return mw.WriteFloat64(v) case complex64: return mw.WriteComplex64(v) case complex128: return mw.WriteComplex128(v) case uint8: return mw.WriteUint8(v) case uint16: return mw.WriteUint16(v) case uint32: return mw.WriteUint32(v) case uint64: return mw.WriteUint64(v) case uint: return mw.WriteUint(v) case int8: return mw.WriteInt8(v) case int16: return mw.WriteInt16(v) case int32: return mw.WriteInt32(v) case int64: return mw.WriteInt64(v) case int: return mw.WriteInt(v) case string: return mw.WriteString(v) case []byte: return mw.WriteBytes(v) case map[string]string: return mw.WriteMapStrStr(v) case map[string]any: return mw.WriteMapStrIntf(v) case time.Time: return mw.WriteTime(v) case time.Duration: return mw.WriteDuration(v) case json.Number: return mw.WriteJSONNumber(v) } val := reflect.ValueOf(v) if !isSupported(val.Kind()) || !val.IsValid() { return errors.New("msgp: type " + val.String() + " not supported") } switch val.Kind() { case reflect.Ptr: if val.IsNil() { return mw.WriteNil() } return mw.WriteIntf(val.Elem().Interface()) case reflect.Slice: return mw.writeSlice(val) case reflect.Map: return mw.writeMap(val) } return &ErrUnsupportedType{T: val.Type()} } func (mw *Writer) writeMap(v reflect.Value) (err error) { if v.Type().Key().Kind() != reflect.String { return errors.New("msgp: map keys must be strings") } ks := v.MapKeys() err = mw.WriteMapHeader(uint32(len(ks))) if err != nil { return } for _, key := range ks { val := v.MapIndex(key) err = mw.WriteString(key.String()) if err != nil { return } err = mw.WriteIntf(val.Interface()) if err != nil { return } } return } func (mw *Writer) writeSlice(v reflect.Value) (err error) { // is []byte if v.Type().ConvertibleTo(btsType) { return mw.WriteBytes(v.Bytes()) } sz := uint32(v.Len()) err = mw.WriteArrayHeader(sz) if err != nil { return } for i := range sz { err = mw.WriteIntf(v.Index(int(i)).Interface()) if err != nil { return } } return } // is the reflect.Kind encodable? func isSupported(k reflect.Kind) bool { switch k { case reflect.Func, reflect.Chan, reflect.Invalid, reflect.UnsafePointer: return false default: return true } } // GuessSize guesses the size of the underlying // value of 'i'. If the underlying value is not // a simple builtin (or []byte), GuessSize defaults // to 512. func GuessSize(i any) int { if i == nil { return NilSize } switch i := i.(type) { case Sizer: return i.Msgsize() case Extension: return ExtensionPrefixSize + i.Len() case float64: return Float64Size case float32: return Float32Size case uint8, uint16, uint32, uint64, uint: return UintSize case int8, int16, int32, int64, int: return IntSize case []byte: return BytesPrefixSize + len(i) case string: return StringPrefixSize + len(i) case complex64: return Complex64Size case complex128: return Complex128Size case bool: return BoolSize case map[string]any: s := MapHeaderSize for key, val := range i { s += StringPrefixSize + len(key) + GuessSize(val) } return s case map[string]string: s := MapHeaderSize for key, val := range i { s += 2*StringPrefixSize + len(key) + len(val) } return s default: return 512 } } // Temporary buffer for reading/writing binary data. var bytesPool = sync.Pool{New: func() any { return make([]byte, 0, 1024) }} // WriteBinaryAppender will write the bytes from the given // encoding.BinaryAppender as a bin array. func (mw *Writer) WriteBinaryAppender(b encoding.BinaryAppender) (err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("msgp: panic during AppendBinary: %v", r) } }() dst := bytesPool.Get().([]byte) defer bytesPool.Put(dst) //nolint:staticcheck dst, err = b.AppendBinary(dst[:0]) if err != nil { return err } return mw.WriteBytes(dst) } // WriteTextAppender will write the bytes from the given // encoding.TextAppender as a bin array. func (mw *Writer) WriteTextAppender(b encoding.TextAppender) (err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("msgp: panic during AppendText: %v", r) } }() dst := bytesPool.Get().([]byte) defer bytesPool.Put(dst) //nolint:staticcheck dst, err = b.AppendText(dst[:0]) if err != nil { return err } return mw.WriteBytes(dst) } // WriteTextAppenderString will write the bytes from the given // encoding.TextAppender as a string. func (mw *Writer) WriteTextAppenderString(b encoding.TextAppender) (err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("msgp: panic during AppendText: %v", r) } }() dst := bytesPool.Get().([]byte) defer bytesPool.Put(dst) //nolint:staticcheck dst, err = b.AppendText(dst[:0]) if err != nil { return err } return mw.WriteStringFromBytes(dst) } msgp-1.6.1/msgp/write_bytes.go000066400000000000000000000333221511433505400163260ustar00rootroot00000000000000package msgp import ( "encoding/binary" "encoding/json" "errors" "math" "reflect" "time" ) // ensure 'sz' extra bytes in 'b' btw len(b) and cap(b) func ensure(b []byte, sz int) ([]byte, int) { l := len(b) c := cap(b) if c-l < sz { o := make([]byte, (2*c)+sz) // exponential growth n := copy(o, b) return o[:n+sz], n } return b[:l+sz], l } // AppendMapHeader appends a map header with the // given size to the slice func AppendMapHeader(b []byte, sz uint32) []byte { switch { case sz <= 15: return append(b, wfixmap(uint8(sz))) case sz <= math.MaxUint16: o, n := ensure(b, 3) prefixu16(o[n:], mmap16, uint16(sz)) return o default: o, n := ensure(b, 5) prefixu32(o[n:], mmap32, sz) return o } } // AppendArrayHeader appends an array header with // the given size to the slice func AppendArrayHeader(b []byte, sz uint32) []byte { switch { case sz <= 15: return append(b, wfixarray(uint8(sz))) case sz <= math.MaxUint16: o, n := ensure(b, 3) prefixu16(o[n:], marray16, uint16(sz)) return o default: o, n := ensure(b, 5) prefixu32(o[n:], marray32, sz) return o } } // AppendNil appends a 'nil' byte to the slice func AppendNil(b []byte) []byte { return append(b, mnil) } // AppendFloat appends a float to the slice as either float64 // or float32 when it represents the exact same value func AppendFloat(b []byte, f float64) []byte { f32 := float32(f) if float64(f32) == f { return AppendFloat32(b, f32) } return AppendFloat64(b, f) } // AppendFloat64 appends a float64 to the slice func AppendFloat64(b []byte, f float64) []byte { o, n := ensure(b, Float64Size) prefixu64(o[n:], mfloat64, math.Float64bits(f)) return o } // AppendFloat32 appends a float32 to the slice func AppendFloat32(b []byte, f float32) []byte { o, n := ensure(b, Float32Size) prefixu32(o[n:], mfloat32, math.Float32bits(f)) return o } // AppendDuration appends a time.Duration to the slice func AppendDuration(b []byte, d time.Duration) []byte { return AppendInt64(b, int64(d)) } // AppendInt64 appends an int64 to the slice func AppendInt64(b []byte, i int64) []byte { if i >= 0 { switch { case i <= math.MaxInt8: return append(b, wfixint(uint8(i))) case i <= math.MaxInt16: o, n := ensure(b, 3) putMint16(o[n:], int16(i)) return o case i <= math.MaxInt32: o, n := ensure(b, 5) putMint32(o[n:], int32(i)) return o default: o, n := ensure(b, 9) putMint64(o[n:], i) return o } } switch { case i >= -32: return append(b, wnfixint(int8(i))) case i >= math.MinInt8: o, n := ensure(b, 2) putMint8(o[n:], int8(i)) return o case i >= math.MinInt16: o, n := ensure(b, 3) putMint16(o[n:], int16(i)) return o case i >= math.MinInt32: o, n := ensure(b, 5) putMint32(o[n:], int32(i)) return o default: o, n := ensure(b, 9) putMint64(o[n:], i) return o } } // AppendInt appends an int to the slice func AppendInt(b []byte, i int) []byte { return AppendInt64(b, int64(i)) } // AppendInt8 appends an int8 to the slice func AppendInt8(b []byte, i int8) []byte { return AppendInt64(b, int64(i)) } // AppendInt16 appends an int16 to the slice func AppendInt16(b []byte, i int16) []byte { return AppendInt64(b, int64(i)) } // AppendInt32 appends an int32 to the slice func AppendInt32(b []byte, i int32) []byte { return AppendInt64(b, int64(i)) } // AppendUint64 appends a uint64 to the slice func AppendUint64(b []byte, u uint64) []byte { switch { case u <= (1<<7)-1: return append(b, wfixint(uint8(u))) case u <= math.MaxUint8: o, n := ensure(b, 2) putMuint8(o[n:], uint8(u)) return o case u <= math.MaxUint16: o, n := ensure(b, 3) putMuint16(o[n:], uint16(u)) return o case u <= math.MaxUint32: o, n := ensure(b, 5) putMuint32(o[n:], uint32(u)) return o default: o, n := ensure(b, 9) putMuint64(o[n:], u) return o } } // AppendUint appends a uint to the slice func AppendUint(b []byte, u uint) []byte { return AppendUint64(b, uint64(u)) } // AppendUint8 appends a uint8 to the slice func AppendUint8(b []byte, u uint8) []byte { return AppendUint64(b, uint64(u)) } // AppendByte is analogous to AppendUint8 func AppendByte(b []byte, u byte) []byte { return AppendUint8(b, u) } // AppendUint16 appends a uint16 to the slice func AppendUint16(b []byte, u uint16) []byte { return AppendUint64(b, uint64(u)) } // AppendUint32 appends a uint32 to the slice func AppendUint32(b []byte, u uint32) []byte { return AppendUint64(b, uint64(u)) } // AppendBytes appends bytes to the slice as MessagePack 'bin' data func AppendBytes(b []byte, bts []byte) []byte { sz := len(bts) var o []byte var n int switch { case sz <= math.MaxUint8: o, n = ensure(b, 2+sz) prefixu8(o[n:], mbin8, uint8(sz)) n += 2 case sz <= math.MaxUint16: o, n = ensure(b, 3+sz) prefixu16(o[n:], mbin16, uint16(sz)) n += 3 default: o, n = ensure(b, 5+sz) prefixu32(o[n:], mbin32, uint32(sz)) n += 5 } return o[:n+copy(o[n:], bts)] } // AppendBytesHeader appends an 'bin' header with // the given size to the slice. func AppendBytesHeader(b []byte, sz uint32) []byte { var o []byte var n int switch { case sz <= math.MaxUint8: o, n = ensure(b, 2) prefixu8(o[n:], mbin8, uint8(sz)) return o case sz <= math.MaxUint16: o, n = ensure(b, 3) prefixu16(o[n:], mbin16, uint16(sz)) return o } o, n = ensure(b, 5) prefixu32(o[n:], mbin32, sz) return o } // AppendBool appends a bool to the slice func AppendBool(b []byte, t bool) []byte { if t { return append(b, mtrue) } return append(b, mfalse) } // AppendString appends a string as a MessagePack 'str' to the slice func AppendString(b []byte, s string) []byte { sz := len(s) var n int var o []byte switch { case sz <= 31: o, n = ensure(b, 1+sz) o[n] = wfixstr(uint8(sz)) n++ case sz <= math.MaxUint8: o, n = ensure(b, 2+sz) prefixu8(o[n:], mstr8, uint8(sz)) n += 2 case sz <= math.MaxUint16: o, n = ensure(b, 3+sz) prefixu16(o[n:], mstr16, uint16(sz)) n += 3 default: o, n = ensure(b, 5+sz) prefixu32(o[n:], mstr32, uint32(sz)) n += 5 } return o[:n+copy(o[n:], s)] } // AppendStringFromBytes appends a []byte // as a MessagePack 'str' to the slice 'b.' func AppendStringFromBytes(b []byte, str []byte) []byte { sz := len(str) var n int var o []byte switch { case sz <= 31: o, n = ensure(b, 1+sz) o[n] = wfixstr(uint8(sz)) n++ case sz <= math.MaxUint8: o, n = ensure(b, 2+sz) prefixu8(o[n:], mstr8, uint8(sz)) n += 2 case sz <= math.MaxUint16: o, n = ensure(b, 3+sz) prefixu16(o[n:], mstr16, uint16(sz)) n += 3 default: o, n = ensure(b, 5+sz) prefixu32(o[n:], mstr32, uint32(sz)) n += 5 } return o[:n+copy(o[n:], str)] } // AppendComplex64 appends a complex64 to the slice as a MessagePack extension func AppendComplex64(b []byte, c complex64) []byte { o, n := ensure(b, Complex64Size) o[n] = mfixext8 o[n+1] = Complex64Extension big.PutUint32(o[n+2:], math.Float32bits(real(c))) big.PutUint32(o[n+6:], math.Float32bits(imag(c))) return o } // AppendComplex128 appends a complex128 to the slice as a MessagePack extension func AppendComplex128(b []byte, c complex128) []byte { o, n := ensure(b, Complex128Size) o[n] = mfixext16 o[n+1] = Complex128Extension big.PutUint64(o[n+2:], math.Float64bits(real(c))) big.PutUint64(o[n+10:], math.Float64bits(imag(c))) return o } // AppendTime appends a time.Time to the slice as a MessagePack extension func AppendTime(b []byte, t time.Time) []byte { o, n := ensure(b, TimeSize) t = t.UTC() o[n] = mext8 o[n+1] = 12 o[n+2] = TimeExtension putUnix(o[n+3:], t.Unix(), int32(t.Nanosecond())) return o } // AppendTimeExt will write t using the official msgpack extension spec. // https://github.com/msgpack/msgpack/blob/master/spec.md#timestamp-extension-type func AppendTimeExt(b []byte, t time.Time) []byte { // Time rounded towards zero. secPrec := t.Truncate(time.Second) remain := t.Sub(secPrec).Nanoseconds() asSecs := secPrec.Unix() switch { case remain == 0 && asSecs > 0 && asSecs <= math.MaxUint32: // 4 bytes o, n := ensure(b, 2+4) o[n+0] = mfixext4 o[n+1] = byte(msgTimeExtension) binary.BigEndian.PutUint32(o[n+2:], uint32(asSecs)) return o case asSecs < 0 || asSecs >= (1<<34): // 12 bytes o, n := ensure(b, 3+12) o[n+0] = mext8 o[n+1] = 12 o[n+2] = byte(msgTimeExtension) binary.BigEndian.PutUint32(o[n+3:], uint32(remain)) binary.BigEndian.PutUint64(o[n+3+4:], uint64(asSecs)) return o default: // 8 bytes o, n := ensure(b, 2+8) o[n+0] = mfixext8 o[n+1] = byte(msgTimeExtension) binary.BigEndian.PutUint64(o[n+2:], uint64(asSecs)|(uint64(remain)<<34)) return o } } // AppendMapStrStr appends a map[string]string to the slice // as a MessagePack map with 'str'-type keys and values func AppendMapStrStr(b []byte, m map[string]string) []byte { sz := uint32(len(m)) b = AppendMapHeader(b, sz) for key, val := range m { b = AppendString(b, key) b = AppendString(b, val) } return b } // AppendMapStrIntf appends a map[string]interface{} to the slice // as a MessagePack map with 'str'-type keys. func AppendMapStrIntf(b []byte, m map[string]any) ([]byte, error) { sz := uint32(len(m)) b = AppendMapHeader(b, sz) var err error for key, val := range m { b = AppendString(b, key) b, err = AppendIntf(b, val) if err != nil { return b, err } } return b, nil } // AppendIntf appends the concrete type of 'i' to the // provided []byte. 'i' must be one of the following: // - 'nil' // - A bool, float, string, []byte, int, uint, or complex // - A map[string]T where T is another supported type // - A []T, where T is another supported type // - A *T, where T is another supported type // - A type that satisfies the msgp.Marshaler interface // - A type that satisfies the msgp.Extension interface func AppendIntf(b []byte, i any) ([]byte, error) { if i == nil { return AppendNil(b), nil } // all the concrete types // for which we have methods switch i := i.(type) { case Marshaler: return i.MarshalMsg(b) case Extension: return AppendExtension(b, i) case bool: return AppendBool(b, i), nil case float32: return AppendFloat32(b, i), nil case float64: return AppendFloat64(b, i), nil case complex64: return AppendComplex64(b, i), nil case complex128: return AppendComplex128(b, i), nil case string: return AppendString(b, i), nil case []byte: return AppendBytes(b, i), nil case int8: return AppendInt8(b, i), nil case int16: return AppendInt16(b, i), nil case int32: return AppendInt32(b, i), nil case int64: return AppendInt64(b, i), nil case int: return AppendInt64(b, int64(i)), nil case uint: return AppendUint64(b, uint64(i)), nil case uint8: return AppendUint8(b, i), nil case uint16: return AppendUint16(b, i), nil case uint32: return AppendUint32(b, i), nil case uint64: return AppendUint64(b, i), nil case time.Time: return AppendTime(b, i), nil case time.Duration: return AppendDuration(b, i), nil case map[string]any: return AppendMapStrIntf(b, i) case map[string]string: return AppendMapStrStr(b, i), nil case json.Number: return AppendJSONNumber(b, i) case []any: b = AppendArrayHeader(b, uint32(len(i))) var err error for _, k := range i { b, err = AppendIntf(b, k) if err != nil { return b, err } } return b, nil } var err error v := reflect.ValueOf(i) switch v.Kind() { case reflect.Map: if v.Type().Key().Kind() != reflect.String { return b, errors.New("msgp: map keys must be strings") } ks := v.MapKeys() b = AppendMapHeader(b, uint32(len(ks))) for _, key := range ks { val := v.MapIndex(key) b = AppendString(b, key.String()) b, err = AppendIntf(b, val.Interface()) if err != nil { return nil, err } } return b, nil case reflect.Array, reflect.Slice: l := v.Len() b = AppendArrayHeader(b, uint32(l)) for i := range l { b, err = AppendIntf(b, v.Index(i).Interface()) if err != nil { return b, err } } return b, nil case reflect.Ptr: if v.IsNil() { return AppendNil(b), err } b, err = AppendIntf(b, v.Elem().Interface()) return b, err default: return b, &ErrUnsupportedType{T: v.Type()} } } // AppendJSONNumber appends a json.Number to the slice. // An error will be returned if the json.Number returns error as both integer and float. func AppendJSONNumber(b []byte, n json.Number) ([]byte, error) { if n == "" { // The zero value outputs the 0 integer. return append(b, 0), nil } ii, err := n.Int64() if err == nil { return AppendInt64(b, ii), nil } ff, err := n.Float64() if err == nil { return AppendFloat(b, ff), nil } return b, err } // AppendBytesTwoPrefixed will add the length to a bin section written with // 2 bytes of space saved for a bin8 header. // If the sz cannot fit inside a bin8, the data will be moved to make space for the header. func AppendBytesTwoPrefixed(b []byte, sz int) []byte { off := len(b) - sz - 2 switch { case sz <= math.MaxUint8: // Just write header... prefixu8(b[off:], mbin8, uint8(sz)) case sz <= math.MaxUint16: // Scoot one b = append(b, 0) copy(b[off+1:], b[off:]) prefixu16(b[off:], mbin16, uint16(sz)) default: // Scoot three b = append(b, 0, 0, 0) copy(b[off+3:], b[off:]) prefixu32(b[off:], mbin32, uint32(sz)) } return b } // AppendBytesStringTwoPrefixed will add the length to a string section written with // 2 bytes of space saved for a str8 header. // If the sz cannot fit inside a str8, the data will be moved to make space for the header. func AppendBytesStringTwoPrefixed(b []byte, sz int) []byte { off := len(b) - sz - 2 switch { case sz <= math.MaxUint8: // Just write header... prefixu8(b[off:], mstr8, uint8(sz)) case sz <= math.MaxUint16: // Scoot one b = append(b, 0) copy(b[off+1:], b[off:]) prefixu16(b[off:], mstr16, uint16(sz)) default: // Scoot three b = append(b, 0, 0, 0) copy(b[off+3:], b[off:]) prefixu32(b[off:], mstr32, uint32(sz)) } return b } msgp-1.6.1/msgp/write_bytes_test.go000066400000000000000000000307631511433505400173730ustar00rootroot00000000000000package msgp import ( "bytes" "math" "math/rand" "reflect" "strings" "testing" "time" ) func TestIssue116(t *testing.T) { data := AppendInt64(nil, math.MinInt64) i, _, err := ReadInt64Bytes(data) if err != nil { t.Fatal(err) } if i != math.MinInt64 { t.Errorf("put %d in and got %d out", int64(math.MinInt64), i) } var buf bytes.Buffer w := NewWriter(&buf) w.WriteInt64(math.MinInt64) w.Flush() i, err = NewReader(&buf).ReadInt64() if err != nil { t.Fatal(err) } if i != math.MinInt64 { t.Errorf("put %d in and got %d out", int64(math.MinInt64), i) } } func TestAppendMapHeader(t *testing.T) { szs := []uint32{0, 1, uint32(tint8), uint32(tint16), tuint32} var buf bytes.Buffer en := NewWriter(&buf) var bts []byte for _, sz := range szs { buf.Reset() en.WriteMapHeader(sz) en.Flush() bts = AppendMapHeader(bts[0:0], sz) if !bytes.Equal(buf.Bytes(), bts) { t.Errorf("for size %d, encoder wrote %q and append wrote %q", sz, buf.Bytes(), bts) } } } func BenchmarkAppendMapHeader(b *testing.B) { buf := make([]byte, 0, 9) N := b.N / 4 b.ReportAllocs() b.ResetTimer() for range N { AppendMapHeader(buf[:0], 0) AppendMapHeader(buf[:0], uint32(tint8)) AppendMapHeader(buf[:0], tuint16) AppendMapHeader(buf[:0], tuint32) } } func TestAppendArrayHeader(t *testing.T) { szs := []uint32{0, 1, uint32(tint8), uint32(tint16), tuint32} var buf bytes.Buffer en := NewWriter(&buf) var bts []byte for _, sz := range szs { buf.Reset() en.WriteArrayHeader(sz) en.Flush() bts = AppendArrayHeader(bts[0:0], sz) if !bytes.Equal(buf.Bytes(), bts) { t.Errorf("for size %d, encoder wrote %q and append wrote %q", sz, buf.Bytes(), bts) } } } func BenchmarkAppendArrayHeader(b *testing.B) { buf := make([]byte, 0, 9) N := b.N / 4 b.ReportAllocs() b.ResetTimer() for range N { AppendArrayHeader(buf[:0], 0) AppendArrayHeader(buf[:0], uint32(tint8)) AppendArrayHeader(buf[:0], tuint16) AppendArrayHeader(buf[:0], tuint32) } } func TestAppendBytesHeader(t *testing.T) { szs := []uint32{0, 1, uint32(tint8), uint32(tint16), tuint32, math.MaxUint32} var buf bytes.Buffer en := NewWriter(&buf) var bts []byte for _, sz := range szs { buf.Reset() en.WriteBytesHeader(sz) en.Flush() bts = AppendBytesHeader(bts[0:0], sz) if !bytes.Equal(buf.Bytes(), bts) { t.Errorf("for size %d, encoder wrote %q and append wrote %q", sz, buf.Bytes(), bts) } } } func BenchmarkAppendBytesHeader(b *testing.B) { buf := make([]byte, 0, 9) N := b.N / 4 b.ReportAllocs() b.ResetTimer() for range N { AppendBytesHeader(buf[:0], 0) AppendBytesHeader(buf[:0], uint32(tint8)) AppendBytesHeader(buf[:0], tuint16) AppendBytesHeader(buf[:0], tuint32) } } func TestAppendNil(t *testing.T) { var bts []byte bts = AppendNil(bts[0:0]) if bts[0] != mnil { t.Fatal("bts[0] is not 'nil'") } } func TestAppendFloat(t *testing.T) { rng := rand.New(rand.NewSource(0)) const n = 1e7 src := make([]float64, n) for i := range src { // ~50% full float64, 50% converted from float32. if rng.Uint32()&1 == 1 { src[i] = rng.NormFloat64() } else { src[i] = float64(math.MaxFloat32 * (0.5 - rng.Float32())) } } var buf bytes.Buffer en := NewWriter(&buf) var bts []byte for _, f := range src { en.WriteFloat(f) bts = AppendFloat(bts, f) } en.Flush() if buf.Len() != len(bts) { t.Errorf("encoder wrote %d; append wrote %d bytes", buf.Len(), len(bts)) } t.Logf("%f bytes/value", float64(buf.Len())/n) a, b := bts, buf.Bytes() for i := range a { if a[i] != b[i] { t.Errorf("mismatch at byte %d, %d != %d", i, a[i], b[i]) break } } for i, want := range src { var got float64 var err error got, a, err = ReadFloat64Bytes(a) if err != nil { t.Fatal(err) } if want != got { t.Errorf("value #%d: want %v; got %v", i, want, got) } } } func BenchmarkAppendFloat(b *testing.B) { rng := rand.New(rand.NewSource(0)) const n = 1 << 16 src := make([]float64, n) for i := range src { // ~50% full float64, 50% converted from float32. if rng.Uint32()&1 == 1 { src[i] = rng.NormFloat64() } else { src[i] = float64(math.MaxFloat32 * (0.5 - rng.Float32())) } } buf := make([]byte, 0, 9) b.SetBytes(8) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { AppendFloat(buf, src[i&(n-1)]) } } func TestAppendFloat64(t *testing.T) { f := float64(3.14159) var buf bytes.Buffer en := NewWriter(&buf) var bts []byte en.WriteFloat64(f) en.Flush() bts = AppendFloat64(bts[0:0], f) if !bytes.Equal(buf.Bytes(), bts) { t.Errorf("for float %f, encoder wrote %q; append wrote %q", f, buf.Bytes(), bts) } } func BenchmarkAppendFloat64(b *testing.B) { f := float64(3.14159) buf := make([]byte, 0, 9) b.SetBytes(9) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { AppendFloat64(buf[0:0], f) } } func TestAppendFloat32(t *testing.T) { f := float32(3.14159) var buf bytes.Buffer en := NewWriter(&buf) var bts []byte en.WriteFloat32(f) en.Flush() bts = AppendFloat32(bts[0:0], f) if !bytes.Equal(buf.Bytes(), bts) { t.Errorf("for float %f, encoder wrote %q; append wrote %q", f, buf.Bytes(), bts) } } func BenchmarkAppendFloat32(b *testing.B) { f := float32(3.14159) buf := make([]byte, 0, 5) b.SetBytes(5) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { AppendFloat32(buf[0:0], f) } } func TestAppendInt64(t *testing.T) { is := []int64{0, 1, -5, -50, int64(tint16), int64(tint32), tint64} var buf bytes.Buffer en := NewWriter(&buf) var bts []byte for _, i := range is { buf.Reset() en.WriteInt64(i) en.Flush() bts = AppendInt64(bts[0:0], i) if !bytes.Equal(buf.Bytes(), bts) { t.Errorf("for int64 %d, encoder wrote %q; append wrote %q", i, buf.Bytes(), bts) } } } func BenchmarkAppendInt64(b *testing.B) { is := []int64{0, 1, -5, -50, int64(tint16), int64(tint32), tint64} l := len(is) buf := make([]byte, 0, 9) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { AppendInt64(buf[0:0], is[i%l]) } } func TestAppendUint64(t *testing.T) { us := []uint64{0, 1, uint64(tuint16), uint64(tuint32), tuint64} var buf bytes.Buffer en := NewWriter(&buf) var bts []byte for _, u := range us { buf.Reset() en.WriteUint64(u) en.Flush() bts = AppendUint64(bts[0:0], u) if !bytes.Equal(buf.Bytes(), bts) { t.Errorf("for uint64 %d, encoder wrote %q; append wrote %q", u, buf.Bytes(), bts) } } } func BenchmarkAppendUint64(b *testing.B) { us := []uint64{0, 1, 15, uint64(tuint16), uint64(tuint32), tuint64} buf := make([]byte, 0, 9) b.ReportAllocs() b.ResetTimer() l := len(us) for i := 0; i < b.N; i++ { AppendUint64(buf[0:0], us[i%l]) } } func TestAppendBytes(t *testing.T) { sizes := []int{0, 1, 225, int(tuint32)} var buf bytes.Buffer en := NewWriter(&buf) var bts []byte for _, sz := range sizes { buf.Reset() b := RandBytes(sz) en.WriteBytes(b) en.Flush() bts = AppendBytes(b[0:0], b) if !bytes.Equal(buf.Bytes(), bts) { t.Errorf("for bytes of length %d, encoder wrote %d bytes and append wrote %d bytes", sz, buf.Len(), len(bts)) } } } func benchappendBytes(size uint32, b *testing.B) { bts := RandBytes(int(size)) buf := make([]byte, 0, len(bts)+5) b.SetBytes(int64(len(bts) + 5)) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { AppendBytes(buf[0:0], bts) } } func BenchmarkAppend16Bytes(b *testing.B) { benchappendBytes(16, b) } func BenchmarkAppend256Bytes(b *testing.B) { benchappendBytes(256, b) } func BenchmarkAppend2048Bytes(b *testing.B) { benchappendBytes(2048, b) } func TestAppendString(t *testing.T) { sizes := []int{0, 1, 225, int(tuint32)} var buf bytes.Buffer en := NewWriter(&buf) var bts []byte for _, sz := range sizes { buf.Reset() s := string(RandBytes(sz)) en.WriteString(s) en.Flush() bts = AppendString(bts[0:0], s) if !bytes.Equal(buf.Bytes(), bts) { t.Errorf("for string of length %d, encoder wrote %d bytes and append wrote %d bytes", sz, buf.Len(), len(bts)) t.Errorf("WriteString prefix: %x", buf.Bytes()[0:5]) t.Errorf("Appendstring prefix: %x", bts[0:5]) } } } func benchappendString(size uint32, b *testing.B) { str := string(RandBytes(int(size))) buf := make([]byte, 0, len(str)+5) b.SetBytes(int64(len(str) + 5)) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { AppendString(buf[0:0], str) } } func BenchmarkAppend16String(b *testing.B) { benchappendString(16, b) } func BenchmarkAppend256String(b *testing.B) { benchappendString(256, b) } func BenchmarkAppend2048String(b *testing.B) { benchappendString(2048, b) } func TestAppendBool(t *testing.T) { vs := []bool{true, false} var buf bytes.Buffer en := NewWriter(&buf) var bts []byte for _, v := range vs { buf.Reset() en.WriteBool(v) en.Flush() bts = AppendBool(bts[0:0], v) if !bytes.Equal(buf.Bytes(), bts) { t.Errorf("for %t, encoder wrote %q and append wrote %q", v, buf.Bytes(), bts) } } } func BenchmarkAppendBool(b *testing.B) { vs := []bool{true, false} buf := make([]byte, 0, 1) b.SetBytes(1) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { AppendBool(buf[0:0], vs[i%2]) } } func BenchmarkAppendTime(b *testing.B) { t := time.Now() b.SetBytes(15) buf := make([]byte, 0, 15) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { AppendTime(buf[0:0], t) } } func BenchmarkAppendTimeExt(b *testing.B) { t := time.Now() buf := make([]byte, 0, 15) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { AppendTimeExt(buf[0:0], t) } } // TestEncodeDecode does a back-and-forth test of encoding and decoding and compare the value with a given output. func TestEncodeDecode(t *testing.T) { for _, tc := range []struct { name string input any output any encodeError string }{ { name: "nil", input: nil, }, { name: "bool", input: true, }, { name: "int", input: int64(42), }, { name: "float", input: 3.14159, }, { name: "string", input: "hello", }, { name: "bytes", input: []byte("hello"), }, { name: "array-empty", input: []any{}, }, { name: "array", input: []any{int64(1), int64(2), int64(3)}, }, { name: "map-empty", input: map[string]any{}, }, { name: "map", input: map[string]any{"a": int64(1), "b": int64(2)}, }, { name: "map-interface", input: map[string]any{"a": int64(1), "b": "2"}, }, { name: "map-string", input: map[string]string{"a": "1", "b": "2"}, output: map[string]any{"a": "1", "b": "2"}, }, { name: "map-array", input: map[string][]int64{"a": {1, 2}, "b": {3}}, output: map[string]any{"a": []any{int64(1), int64(2)}, "b": []any{int64(3)}}, }, { name: "map-map", input: map[string]map[string]int64{"a": {"a": 1, "b": 2}, "b": {"c": 3}}, output: map[string]any{"a": map[string]any{"a": int64(1), "b": int64(2)}, "b": map[string]any{"c": int64(3)}}, }, { name: "array-map", input: []any{map[string]any{"a": int64(1), "b": "2"}, map[string]int64{"c": 3}}, output: []any{map[string]any{"a": int64(1), "b": "2"}, map[string]any{"c": int64(3)}}, }, { name: "array-array", input: []any{[]int64{1, 2}, []any{int64(3)}}, output: []any{[]any{int64(1), int64(2)}, []any{int64(3)}}, }, { name: "array-array-map", input: []any{[]any{int64(1), int64(2)}, map[string]any{"c": int64(3)}}, }, { name: "map-array-map", input: map[string]any{"a": []any{int64(1), int64(2)}, "b": map[string]any{"c": int64(3)}}, }, { name: "map-invalid-keys", input: map[any]any{int64(1): int64(2)}, encodeError: "msgp: map keys must be strings", }, { name: "map-nested-invalid-keys", input: map[string]any{"a": map[int64]string{1: "2"}}, encodeError: "msgp: map keys must be strings", }, { name: "invalid-type", input: struct{}{}, encodeError: "msgp: type \"struct {}\" not supported", }, } { t.Run(tc.name, func(t *testing.T) { // If no output is given, use the input as output if tc.output == nil { tc.output = tc.input } buf, err := AppendIntf(nil, tc.input) if tc.encodeError != "" { if err == nil || !strings.Contains(err.Error(), tc.encodeError) { t.Fatalf("expected encode error '%s' but got '%s'", tc.encodeError, err) } return } if tc.encodeError == "" && err != nil { t.Fatalf("expected no encode error but got '%s'", err.Error()) } out, _, _ := ReadIntfBytes(buf) if err != nil { t.Fatalf("expected no decode error but got '%s'", err.Error()) } if !reflect.DeepEqual(tc.output, out) { t.Fatalf("expected '%v' but got '%v'", tc.input, out) } }) } } msgp-1.6.1/msgp/write_test.go000066400000000000000000000204141511433505400161550ustar00rootroot00000000000000package msgp import ( "bytes" "math" "math/rand" "testing" "time" ) var ( tint8 int8 = 126 // cannot be most fix* types tint16 int16 = 150 // cannot be int8 tint32 int32 = math.MaxInt16 + 100 // cannot be int16 tint64 int64 = math.MaxInt32 + 100 // cannot be int32 tuint16 uint32 = 300 // cannot be uint8 tuint32 uint32 = math.MaxUint16 + 100 // cannot be uint16 tuint64 uint64 = math.MaxUint32 + 100 // cannot be uint32 ) func RandBytes(sz int) []byte { out := make([]byte, sz) rng := rand.New(rand.NewSource(time.Now().UnixNano())) for i := range out { out[i] = byte(rng.Uint32()) } return out } func TestWriteMapHeader(t *testing.T) { tests := []struct { Sz uint32 Outbytes []byte }{ {0, []byte{mfixmap}}, {1, []byte{mfixmap | byte(1)}}, {100, []byte{mmap16, byte(uint16(100) >> 8), byte(uint16(100))}}, { tuint32, []byte{ mmap32, byte(tuint32 >> 24), byte(tuint32 >> 16), byte(tuint32 >> 8), byte(tuint32), }, }, } var buf bytes.Buffer var err error wr := NewWriter(&buf) for _, test := range tests { buf.Reset() err = wr.WriteMapHeader(test.Sz) if err != nil { t.Error(err) } err = wr.Flush() if err != nil { t.Fatal(err) } if !bytes.Equal(buf.Bytes(), test.Outbytes) { t.Errorf("Expected bytes %x; got %x", test.Outbytes, buf.Bytes()) } } } func BenchmarkWriteMapHeader(b *testing.B) { wr := NewWriter(Nowhere) N := b.N / 4 b.ReportAllocs() b.ResetTimer() for range N { wr.WriteMapHeader(0) wr.WriteMapHeader(8) wr.WriteMapHeader(tuint16) wr.WriteMapHeader(tuint32) } } func TestWriteArrayHeader(t *testing.T) { tests := []struct { Sz uint32 Outbytes []byte }{ {0, []byte{mfixarray}}, {1, []byte{mfixarray | byte(1)}}, {tuint16, []byte{marray16, byte(tuint16 >> 8), byte(tuint16)}}, {tuint32, []byte{marray32, byte(tuint32 >> 24), byte(tuint32 >> 16), byte(tuint32 >> 8), byte(tuint32)}}, } var buf bytes.Buffer var err error wr := NewWriter(&buf) for _, test := range tests { buf.Reset() err = wr.WriteArrayHeader(test.Sz) if err != nil { t.Error(err) } err = wr.Flush() if err != nil { t.Fatal(err) } if !bytes.Equal(buf.Bytes(), test.Outbytes) { t.Errorf("Expected bytes %x; got %x", test.Outbytes, buf.Bytes()) } } } func TestReadWriteStringHeader(t *testing.T) { sizes := []uint32{0, 5, 8, 19, 150, tuint16, tuint32} var buf bytes.Buffer var err error wr := NewWriter(&buf) for _, sz := range sizes { buf.Reset() err = wr.WriteStringHeader(sz) if err != nil { t.Fatal(err) } err = wr.Flush() if err != nil { t.Fatal(err) } var nsz uint32 nsz, err = NewReader(&buf).ReadStringHeader() if err != nil { t.Fatal(err) } if nsz != sz { t.Errorf("put in size %d but got out size %d", sz, nsz) } } } func TestReadWriteBytesHeader(t *testing.T) { sizes := []uint32{0, 5, 8, 19, 150, tuint16, tuint32} var buf bytes.Buffer var err error wr := NewWriter(&buf) for _, sz := range sizes { buf.Reset() err = wr.WriteBytesHeader(sz) if err != nil { t.Fatal(err) } err = wr.Flush() if err != nil { t.Fatal(err) } var nsz uint32 nsz, err = NewReader(&buf).ReadBytesHeader() if err != nil { t.Fatal(err) } if nsz != sz { t.Errorf("put in size %d but got out size %d", sz, nsz) } } } func BenchmarkWriteArrayHeader(b *testing.B) { wr := NewWriter(Nowhere) N := b.N / 4 b.ReportAllocs() b.ResetTimer() for range N { wr.WriteArrayHeader(0) wr.WriteArrayHeader(16) wr.WriteArrayHeader(tuint16) wr.WriteArrayHeader(tuint32) } } func TestWriteNil(t *testing.T) { var buf bytes.Buffer wr := NewWriter(&buf) err := wr.WriteNil() if err != nil { t.Fatal(err) } err = wr.Flush() if err != nil { t.Fatal(err) } bts := buf.Bytes() if bts[0] != mnil { t.Errorf("Expected %x; wrote %x", mnil, bts[0]) } } func TestWriteFloat64(t *testing.T) { var buf bytes.Buffer wr := NewWriter(&buf) for range 10000 { buf.Reset() flt := (rand.Float64() - 0.5) * math.MaxFloat64 err := wr.WriteFloat64(flt) if err != nil { t.Errorf("Error with %f: %s", flt, err) } err = wr.Flush() if err != nil { t.Fatal(err) } bts := buf.Bytes() if bts[0] != mfloat64 { t.Errorf("Leading byte was %x and not %x", bts[0], mfloat64) } } } func TestReadWriterDuration(t *testing.T) { var buf bytes.Buffer wr := NewWriter(&buf) for range 10000 { buf.Reset() dur := time.Duration(rand.Int63()) err := wr.WriteDuration(dur) if err != nil { t.Errorf("Error with %v: %s", dur, err) } err = wr.Flush() if err != nil { t.Fatal(err) } bts := buf.Bytes() if bts[0] != mint64 { t.Errorf("Leading byte was %x and not %x", bts[0], mint64) } wr := NewReader(&buf) d, err := wr.ReadDuration() if err != nil { t.Errorf("Error reading duration: %v", err) } if d != dur { t.Errorf("Got duration %v, want %v", d, dur) } } } func BenchmarkWriteFloat64(b *testing.B) { f := rand.Float64() wr := NewWriter(Nowhere) b.SetBytes(9) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { wr.WriteFloat64(f) } } func TestWriteFloat32(t *testing.T) { var buf bytes.Buffer wr := NewWriter(&buf) for range 10000 { buf.Reset() flt := (rand.Float32() - 0.5) * math.MaxFloat32 err := wr.WriteFloat32(flt) if err != nil { t.Errorf("Error with %f: %s", flt, err) } err = wr.Flush() if err != nil { t.Fatal(err) } bts := buf.Bytes() if bts[0] != mfloat32 { t.Errorf("Leading byte was %x and not %x", bts[0], mfloat64) } } } func BenchmarkWriteFloat32(b *testing.B) { f := rand.Float32() wr := NewWriter(Nowhere) b.SetBytes(5) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { wr.WriteFloat32(f) } } func TestWriteInt64(t *testing.T) { var buf bytes.Buffer wr := NewWriter(&buf) for range 10000 { buf.Reset() num := (rand.Int63n(math.MaxInt64)) - (math.MaxInt64 / 2) err := wr.WriteInt64(num) if err != nil { t.Fatal(err) } err = wr.Flush() if err != nil { t.Fatal(err) } if buf.Len() > 9 { t.Errorf("buffer length should be <= 9; it's %d", buf.Len()) } } } func BenchmarkWriteInt64(b *testing.B) { wr := NewWriter(Nowhere) b.SetBytes(9) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { wr.WriteInt64(tint64) } } func TestWriteUint64(t *testing.T) { var buf bytes.Buffer wr := NewWriter(&buf) for range 10000 { buf.Reset() num := uint64(rand.Int63n(math.MaxInt64)) err := wr.WriteUint64(num) if err != nil { t.Fatal(err) } err = wr.Flush() if err != nil { t.Fatal(err) } if buf.Len() > 9 { t.Errorf("buffer length should be <= 9; it's %d", buf.Len()) } } } func BenchmarkWriteUint64(b *testing.B) { wr := NewWriter(Nowhere) b.SetBytes(9) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { wr.WriteUint64(tuint64) } } func TestWriteBytes(t *testing.T) { var buf bytes.Buffer wr := NewWriter(&buf) sizes := []int{0, 1, 225, int(tuint32)} for _, size := range sizes { buf.Reset() bts := RandBytes(size) err := wr.WriteBytes(bts) if err != nil { t.Fatal(err) } err = wr.Flush() if err != nil { t.Fatal(err) } if buf.Len() < len(bts) { t.Errorf("somehow, %d bytes were encoded in %d bytes", len(bts), buf.Len()) } } } func benchwrBytes(size uint32, b *testing.B) { bts := RandBytes(int(size)) wr := NewWriter(Nowhere) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { wr.WriteBytes(bts) } } func BenchmarkWrite16Bytes(b *testing.B) { benchwrBytes(16, b) } func BenchmarkWrite256Bytes(b *testing.B) { benchwrBytes(256, b) } func BenchmarkWrite2048Bytes(b *testing.B) { benchwrBytes(2048, b) } func TestWriteTime(t *testing.T) { var buf bytes.Buffer wr := NewWriter(&buf) tm := time.Now() err := wr.WriteTime(tm) if err != nil { t.Fatal(err) } err = wr.Flush() if err != nil { t.Fatal(err) } if buf.Len() != 15 { t.Errorf("expected time.Time to be %d bytes; got %d", 15, buf.Len()) } newt, err := NewReader(&buf).ReadTime() if err != nil { t.Fatal(err) } if !newt.Equal(tm) { t.Errorf("in/out not equal; %s in and %s out", tm, newt) } } func BenchmarkWriteTime(b *testing.B) { t := time.Now() wr := NewWriter(Nowhere) b.SetBytes(15) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { wr.WriteTime(t) } } msgp-1.6.1/parse/000077500000000000000000000000001511433505400136005ustar00rootroot00000000000000msgp-1.6.1/parse/directives.go000066400000000000000000000322561511433505400163000ustar00rootroot00000000000000package parse import ( "fmt" "go/ast" "go/parser" "regexp" "strconv" "strings" "github.com/tinylib/msgp/gen" ) const linePrefix = "//msgp:" // func(args, fileset) type directive func([]string, *FileSet) error // func(passName, args, printer) type passDirective func(gen.Method, []string, *gen.Printer) error // map of all recognized directives // // to add a directive, define a func([]string, *FileSet) error // and then add it to this list. var directives = map[string]directive{ "shim": applyShim, "replace": replace, "ignore": ignore, "tuple": astuple, "vartuple": asvartuple, "compactfloats": compactfloats, "clearomitted": clearomitted, "newtime": newtime, "timezone": newtimezone, "limit": limit, "binmarshal": binmarshal, "binappend": binappend, "textmarshal": textmarshal, "textappend": textappend, } // map of all recognized directives which will be applied // before process() is called // // to add an early directive, define a func([]string, *FileSet) error // and then add it to this list. var earlyDirectives = map[string]directive{ "tag": tag, "pointer": pointer, "maps": maps, } var passDirectives = map[string]passDirective{ "ignore": passignore, } func passignore(m gen.Method, text []string, p *gen.Printer) error { pushstate(m.String()) for _, a := range text { p.ApplyDirective(m, gen.IgnoreTypename(a)) infof("ignoring %s\n", a) } popstate() return nil } // find all comment lines that begin with //msgp: func yieldComments(c []*ast.CommentGroup) []string { var out []string for _, cg := range c { for _, line := range cg.List { if after, ok := strings.CutPrefix(line.Text, linePrefix); ok { out = append(out, after) } } } return out } //msgp:shim {Type} as:{NewType} using:{toFunc/fromFunc} mode:{Mode} func applyShim(text []string, f *FileSet) error { if len(text) < 4 { return fmt.Errorf("shim directive should have at least 3 arguments; found %d", len(text)-1) } name := text[1] be := gen.Ident(strings.TrimPrefix(strings.TrimSpace(text[2]), "as:")) // parse as::{base} if name[0] == '*' { name = name[1:] be.Needsref(true) } be.Alias(name) usestr := strings.TrimPrefix(strings.TrimSpace(text[3]), "using:") // parse using::{method/method} methods := strings.Split(usestr, "/") if len(methods) != 2 { return fmt.Errorf("expected 2 using::{} methods; found %d (%q)", len(methods), text[3]) } be.ShimToBase = methods[0] be.ShimFromBase = methods[1] text = text[4:] for len(text) > 0 { arg := strings.TrimSpace(text[0]) switch { case strings.HasPrefix(arg, "mode:"): modestr := strings.TrimPrefix(arg, "mode:") // parse mode::{mode} switch modestr { case "cast": be.ShimMode = gen.Cast case "convert": be.ShimMode = gen.Convert default: return fmt.Errorf("invalid shim mode; found %s, expected 'cast' or 'convert", modestr) } case strings.HasPrefix(arg, "witherr:"): haserr, err := strconv.ParseBool(strings.TrimPrefix(arg, "witherr:")) if err != nil { return fmt.Errorf("invalid witherr directive; found %s, expected 'true' or 'false'", arg) } be.ShimErrs = haserr default: return fmt.Errorf("invalid shim directive; found %s", arg) } text = text[1:] } infof("%s -> %s\n", name, be.Value.String()) f.findShim(name, be, true) return nil } //msgp:replace {Type} with:{NewType} func replace(text []string, f *FileSet) error { if len(text) != 3 { return fmt.Errorf("replace directive should have only 2 arguments; found %d", len(text)-1) } name := text[1] replacement := strings.TrimPrefix(strings.TrimSpace(text[2]), "with:") expr, err := parser.ParseExpr(replacement) if err != nil { return err } e := f.parseExpr(expr) e.AlwaysPtr(&f.pointerRcv) if be, ok := e.(*gen.BaseElem); ok { be.Convert = true be.Alias(name) if be.Value == gen.IDENT { be.ShimToBase = "(*" + replacement + ")" be.Needsref(true) } } infof("%s -> %s\n", name, replacement) f.findShim(name, e, false) return nil } //msgp:ignore {TypeA} {TypeB}... func ignore(text []string, f *FileSet) error { if len(text) < 2 { return nil } for _, item := range text[1:] { name := strings.TrimSpace(item) if name, ok := strings.CutPrefix(name, "regex:"); ok { name = strings.TrimPrefix(name, "regex:") rx, err := regexp.Compile(name) if err != nil { panic(fmt.Sprintf("Error compiling ignore regex %q: %v", name, err)) } for name := range f.Identities { if !rx.MatchString(name) { continue } delete(f.Identities, name) infof("ignoring %s\n", name) } continue } if _, ok := f.Identities[name]; ok { delete(f.Identities, name) infof("ignoring %s\n", name) } } return nil } //msgp:tuple {TypeA} {TypeB}... func astuple(text []string, f *FileSet) error { if len(text) < 2 { return nil } for _, item := range text[1:] { name := strings.TrimSpace(item) if el, ok := f.Identities[name]; ok { if st, ok := el.(*gen.Struct); ok { st.AsTuple = true infof(name) } else { warnf("%s: only structs can be tuples\n", name) } } } return nil } //msgp:vartuple {TypeA} {TypeB}... func asvartuple(text []string, f *FileSet) error { if len(text) < 2 { return nil } for _, item := range text[1:] { name := strings.TrimSpace(item) if el, ok := f.Identities[name]; ok { if st, ok := el.(*gen.Struct); ok { st.AsTuple = true st.AsVarTuple = true infof(name) } else { warnf("%s: only structs can be tuples\n", name) } } } return nil } //msgp:tag {tagname} func tag(text []string, f *FileSet) error { if len(text) != 2 { return nil } f.tagName = strings.TrimSpace(text[1]) infof("using field tag %q\n", f.tagName) return nil } //msgp:pointer func pointer(text []string, f *FileSet) error { infof("using pointer receiver\n") f.pointerRcv = true return nil } //msgp:compactfloats func compactfloats(text []string, f *FileSet) error { infof("using compact floats\n") f.CompactFloats = true return nil } //msgp:clearomitted func clearomitted(text []string, f *FileSet) error { infof("clearing omitted fields\n") f.ClearOmitted = true return nil } //msgp:newtime func newtime(text []string, f *FileSet) error { infof("using new time encoding\n") f.NewTime = true return nil } func maps(text []string, f *FileSet) (err error) { for _, arg := range text[1:] { arg = strings.ToLower(strings.TrimSpace(arg)) switch { case strings.HasPrefix(arg, "shim"): arg = strings.TrimPrefix(arg, "shim") if len(arg) == 0 { f.AllowMapShims = true continue } f.AllowMapShims, err = strconv.ParseBool(strings.TrimPrefix(arg, ":")) if err != nil { return fmt.Errorf("invalid shim directive; found %s, expected 'true' or 'false'", arg) } case strings.HasPrefix(arg, "binkeys"): arg = strings.TrimPrefix(arg, "binkeys") if len(arg) == 0 { f.AllowBinMaps = true continue } f.AllowBinMaps, err = strconv.ParseBool(strings.TrimPrefix(arg, ":")) if err != nil { return fmt.Errorf("invalid binkeys directive; found %s, expected 'true' or 'false'", arg) } case strings.HasPrefix(arg, "autoshim"): arg = strings.TrimPrefix(arg, "autoshim") if len(arg) == 0 { f.AutoMapShims = true continue } f.AutoMapShims, err = strconv.ParseBool(strings.TrimPrefix(arg, ":")) if err != nil { return fmt.Errorf("invalid autoshim directive; found %s, expected 'true' or 'false'", arg) } default: if err != nil { return fmt.Errorf("invalid autoshim directive; found %s, expected 'true' or 'false'", arg) } } } if f.AllowBinMaps && f.AutoMapShims { warnf("both binkeys and autoshim are enabled; ignoring autoshim\n") f.AutoMapShims = false } infof("shim:%t binkeys:%t autoshim:%t\n", f.AllowMapShims, f.AllowBinMaps, f.AutoMapShims) return nil } //msgp:timezone func newtimezone(text []string, f *FileSet) error { if len(text) != 2 { return fmt.Errorf("timezone directive should have only 1 argument; found %d", len(text)-1) } switch strings.ToLower(strings.TrimSpace(text[1])) { case "local": f.AsUTC = false case "utc": f.AsUTC = true default: return fmt.Errorf("timezone directive should be either 'local' or 'utc'; found %q", text[1]) } infof("using timezone %q\n", text[1]) return nil } //msgp:limit arrays:n maps:n marshal:true/false func limit(text []string, f *FileSet) (err error) { for _, arg := range text[1:] { arg = strings.ToLower(strings.TrimSpace(arg)) switch { case strings.HasPrefix(arg, "arrays:"): limitStr := strings.TrimPrefix(arg, "arrays:") limit, err := strconv.ParseUint(limitStr, 10, 32) if err != nil { return fmt.Errorf("invalid arrays limit; found %s, expected positive integer", limitStr) } f.ArrayLimit = uint32(limit) case strings.HasPrefix(arg, "maps:"): limitStr := strings.TrimPrefix(arg, "maps:") limit, err := strconv.ParseUint(limitStr, 10, 32) if err != nil { return fmt.Errorf("invalid maps limit; found %s, expected positive integer", limitStr) } f.MapLimit = uint32(limit) case strings.HasPrefix(arg, "marshal:"): marshalStr := strings.TrimPrefix(arg, "marshal:") marshal, err := strconv.ParseBool(marshalStr) if err != nil { return fmt.Errorf("invalid marshal option; found %s, expected 'true' or 'false'", marshalStr) } f.MarshalLimits = marshal default: return fmt.Errorf("invalid limit directive; found %s, expected 'arrays:n', 'maps:n', or 'marshal:true/false'", arg) } } infof("limits - arrays:%d maps:%d marshal:%t\n", f.ArrayLimit, f.MapLimit, f.MarshalLimits) return nil } //msgp:binmarshal pkg.Type pkg.Type2 func binmarshal(text []string, f *FileSet) error { if len(text) < 2 { return fmt.Errorf("binmarshal directive should have at least 1 argument; found %d", len(text)-1) } alwaysPtr := true for _, item := range text[1:] { name := strings.TrimSpace(item) be := gen.Ident(name) be.Value = gen.BinaryMarshaler be.Alias(name) be.Convert = false // Don't use conversion for marshaler types be.AlwaysPtr(&alwaysPtr) infof("%s -> BinaryMarshaler\n", name) f.findShim(name, be, true) } return nil } //msgp:binappend pkg.Type pkg.Type2 func binappend(text []string, f *FileSet) error { if len(text) < 2 { return fmt.Errorf("binappend directive should have at least 1 argument; found %d", len(text)-1) } alwaysPtr := true for _, item := range text[1:] { name := strings.TrimSpace(item) be := gen.Ident(name) be.Value = gen.BinaryAppender be.Alias(name) be.Convert = false // Don't use conversion for marshaler types be.AlwaysPtr(&alwaysPtr) infof("%s -> BinaryAppender\n", name) f.findShim(name, be, true) } return nil } //msgp:textmarshal [as:string] pkg.Type pkg.Type2 func textmarshal(text []string, f *FileSet) error { if len(text) < 2 { return fmt.Errorf("textmarshal directive should have at least 1 argument; found %d", len(text)-1) } // Check for as:string option anywhere in the arguments var asString bool var typeArgs []string alwaysPtr := true for _, item := range text[1:] { trimmed := strings.TrimSpace(item) if strings.HasPrefix(trimmed, "as:") { option := strings.TrimPrefix(trimmed, "as:") switch option { case "string": asString = true case "bin": asString = false default: return fmt.Errorf("invalid as: option %q, expected 'string' or 'bin'", option) } } else { typeArgs = append(typeArgs, trimmed) } } if len(typeArgs) == 0 { return fmt.Errorf("textmarshal directive should have at least 1 type argument") } for _, item := range typeArgs { name := strings.TrimSpace(item) be := gen.Ident(name) be.AlwaysPtr(&alwaysPtr) if asString { be.Value = gen.TextMarshalerString } else { be.Value = gen.TextMarshalerBin } be.Alias(name) be.Convert = false // Don't use conversion for marshaler types if asString { infof("%s -> TextMarshaler (as string)\n", name) } else { infof("%s -> TextMarshaler (as bin)\n", name) } f.findShim(name, be, true) } return nil } //msgp:textappend [as:string] pkg.Type pkg.Type2 func textappend(text []string, f *FileSet) error { if len(text) < 2 { return fmt.Errorf("textappend directive should have at least 1 argument; found %d", len(text)-1) } // Check for as:string option anywhere in the arguments var asString bool var typeArgs []string alwaysPtr := true for _, item := range text[1:] { trimmed := strings.TrimSpace(item) if strings.HasPrefix(trimmed, "as:") { option := strings.TrimPrefix(trimmed, "as:") switch option { case "string": asString = true case "bin": asString = false default: return fmt.Errorf("invalid as: option %q, expected 'string' or 'bin'", option) } } else { typeArgs = append(typeArgs, trimmed) } } if len(typeArgs) == 0 { return fmt.Errorf("textappend directive should have at least 1 type argument") } for _, item := range typeArgs { name := strings.TrimSpace(item) be := gen.Ident(name) if asString { be.Value = gen.TextAppenderString } else { be.Value = gen.TextAppenderBin } be.Alias(name) be.Convert = false // Don't use conversion for marshaler types be.AlwaysPtr(&alwaysPtr) if asString { infof("%s -> TextAppender (as string)\n", name) } else { infof("%s -> TextAppender (as bin)\n", name) } f.findShim(name, be, true) } return nil } msgp-1.6.1/parse/getast.go000066400000000000000000000550001511433505400154160ustar00rootroot00000000000000package parse import ( "fmt" "go/ast" "go/parser" "go/token" "math" "os" "reflect" "sort" "strconv" "strings" "github.com/tinylib/msgp/gen" ) // TypeInfo holds both the type expression and its generic type parameters type TypeInfo struct { Type ast.Expr // The actual type expression TypeParams *ast.FieldList // Generic type parameters } // A FileSet is the in-memory representation of a // parsed file. type FileSet struct { Package string // package name Specs map[string]ast.Expr // type specs in file TypeInfos map[string]*TypeInfo // type specs with generic info Identities map[string]gen.Elem // processed from specs Aliased map[string]string // Aliased types. Directives []string // raw preprocessor directives Imports []*ast.ImportSpec // imports CompactFloats bool // Use smaller floats when feasible ClearOmitted bool // Set omitted fields to zero value NewTime bool // Set to use -1 extension for time.Time AsUTC bool // Set timezone to UTC instead of local AllowMapShims bool // Allow map keys to be shimmed (default true) AllowBinMaps bool // Allow maps with binary keys to be used (default false) AutoMapShims bool // Automatically shim map keys of builtin types(default false) ArrayLimit uint32 // Maximum array/slice size allowed during deserialization MapLimit uint32 // Maximum map size allowed during deserialization MarshalLimits bool // Whether to enforce limits during marshaling LimitPrefix string // Unique prefix for limit constants to avoid collisions tagName string // tag to read field names from pointerRcv bool // generate with pointer receivers. } // File parses a file at the relative path // provided and produces a new *FileSet. // If you pass in a path to a directory, the entire // directory will be parsed. // If unexport is false, only exported identifiers are included in the FileSet. // If the resulting FileSet would be empty, an error is returned. func File(name string, unexported bool, directives []string) (*FileSet, error) { pushstate(name) defer popstate() fs := &FileSet{ Specs: make(map[string]ast.Expr), TypeInfos: make(map[string]*TypeInfo), Identities: make(map[string]gen.Elem), Directives: append([]string{}, directives...), ArrayLimit: math.MaxUint32, MapLimit: math.MaxUint32, } fset := token.NewFileSet() finfo, err := os.Stat(name) if err != nil { return nil, err } if finfo.IsDir() { pkgs, err := parser.ParseDir(fset, name, nil, parser.ParseComments) if err != nil { return nil, err } if len(pkgs) != 1 { return nil, fmt.Errorf("multiple packages in directory: %s", name) } var one *ast.Package for _, nm := range pkgs { one = nm break } fs.Package = one.Name for _, fl := range one.Files { pushstate(fl.Name.Name) fs.Directives = append(fs.Directives, yieldComments(fl.Comments)...) if !unexported { ast.FileExports(fl) } fs.getTypeSpecs(fl) popstate() } } else { f, err := parser.ParseFile(fset, name, nil, parser.ParseComments) if err != nil { return nil, err } fs.Package = f.Name.Name fs.Directives = append(fs.Directives, yieldComments(f.Comments)...) if !unexported { ast.FileExports(f) } fs.getTypeSpecs(f) } if len(fs.Specs) == 0 { return nil, fmt.Errorf("no definitions in %s", name) } fs.applyEarlyDirectives() fs.process() fs.applyDirectives() fs.propInline() return fs, nil } // applyDirectives applies all of the directives that // are known to the parser. additional method-specific // directives remain in f.Directives func (fs *FileSet) applyDirectives() { newdirs := make([]string, 0, len(fs.Directives)) for _, d := range fs.Directives { chunks := strings.Split(d, " ") if len(chunks) > 0 { if fn, ok := directives[chunks[0]]; ok { pushstate(chunks[0]) err := fn(chunks, fs) if err != nil { warnf("directive error: %s", err) } popstate() } else { newdirs = append(newdirs, d) } } } // Apply aliases last, so we don't overrule any manually specified replace directives. for _, d := range fs.Aliased { chunks := strings.Split(d, " ") if len(chunks) > 0 { if fn, ok := directives[chunks[0]]; ok { pushstate(chunks[0]) err := fn(chunks, fs) if err != nil { warnf("directive error: %s", err) } popstate() } else { newdirs = append(newdirs, d) } } } fs.Directives = newdirs } // applyEarlyDirectives applies all early directives needed before process() is called. // additional directives remain in f.Directives for future processing func (fs *FileSet) applyEarlyDirectives() { newdirs := make([]string, 0, len(fs.Directives)) for _, d := range fs.Directives { parts := strings.Split(d, " ") if len(parts) == 0 { continue } if fn, ok := earlyDirectives[parts[0]]; ok { pushstate(parts[0]) err := fn(parts, fs) if err != nil { warnf("early directive error: %s", err) } popstate() } else { newdirs = append(newdirs, d) } } fs.Directives = newdirs } // A linkset is a graph of unresolved // identities. // // Since gen.Ident can only represent // one level of type indirection (e.g. Foo -> uint8), // type declarations like `type Foo Bar` // aren't resolve-able until we've processed // everything else. // // The goal of this dependency resolution // is to distill the type declaration // into just one level of indirection. // In other words, if we have: // // type A uint64 // type B A // type C B // type D C // // ... then we want to end up // figuring out that D is just a uint64. type linkset map[string]*gen.BaseElem func (fs *FileSet) resolve(ls linkset) { progress := true for progress && len(ls) > 0 { progress = false for name, elem := range ls { real, ok := fs.Identities[elem.TypeName()] if ok { // copy the old type descriptor, // alias it to the new value, // and insert it into the resolved // identities list progress = true nt := real.Copy() nt.Alias(name) fs.Identities[name] = nt delete(ls, name) } } } // what's left can't be resolved for name, elem := range ls { warnf("couldn't resolve type %s (%s)\n", name, elem.TypeName()) } } // formatTypeParams converts an AST FieldList to a string representation func formatTypeParams(params *ast.FieldList) string { if params == nil || params.NumFields() == 0 { return "" } var paramStrs []string for _, field := range params.List { // Convert underscores to _RTn where n is the number of the parameter convert := isrtfor(field.Type) // Each field can have multiple names (e.g., T, U constraint) for _, name := range field.Names { if convert && name.Name == "_" { name.Name = fmt.Sprintf("_RT%d", len(paramStrs)+1) } // For method receivers, we only include the type parameter name // The constraints are defined in the type declaration, not the method receiver paramStrs = append(paramStrs, name.Name) } } return "[" + strings.Join(paramStrs, ", ") + "]" } // isrtfor returns whether the provided expression is a msgp.RTFor[T] pattern. func isrtfor(t ast.Expr) bool { return strings.HasPrefix(stringify(t), "msgp.RTFor[") } // findRTForInInterface recursively searches for msgp.RTFor[T] patterns within interface types func findRTForInInterface(iface *ast.InterfaceType) []string { var rtfors []string if iface.Methods == nil { return rtfors } for _, method := range iface.Methods.List { // Check if this is an embedded interface/type if len(method.Names) == 0 { if isrtfor(method.Type) { rtfors = append(rtfors, stringify(method.Type)) } // Recursively check nested interfaces if nestedIface, ok := method.Type.(*ast.InterfaceType); ok { rtfors = append(rtfors, findRTForInInterface(nestedIface)...) } } } return rtfors } // formatTypeParams converts an AST FieldList to a string representation. // For 'Foo[T any, P msgp.RTFor[T]]' will return {"T": "P"}. func getMspTypeParams(params *ast.FieldList) map[string]string { if params == nil || params.NumFields() == 0 { return nil } paramStrs := make(map[string]string) for _, field := range params.List { // Handle simple msgp.RTFor[T] constraints if isrtfor(field.Type) { t := strings.TrimSuffix(strings.TrimPrefix(stringify(field.Type), "msgp.RTFor["), "]") for _, name := range field.Names { paramStrs[t] = name.Name + "(&%s)" paramStrs["*"+t] = name.Name + "(%s)" paramStrs[name.Name] = "%s" infof("found generic type %s, with roundtrippper %s\n", t, name.Name) } continue } // Handle complex interface constraints that embed msgp.RTFor[T] if iface, ok := field.Type.(*ast.InterfaceType); ok { rtfors := findRTForInInterface(iface) for _, rtfor := range rtfors { t := strings.TrimSuffix(strings.TrimPrefix(rtfor, "msgp.RTFor["), "]") for _, name := range field.Names { paramStrs[t] = name.Name + "(&%s)" paramStrs["*"+t] = name.Name + "(%s)" paramStrs[name.Name] = "%s" infof("found generic type %s, with roundtrippper %s (in complex interface)\n", t, name.Name) } } } } return paramStrs } // process takes the contents of f.Specs and // uses them to populate f.Identities func (fs *FileSet) process() { deferred := make(linkset) parse: for name, def := range fs.Specs { pushstate(name) el := fs.parseExpr(def) if el == nil { warnf("failed to parse") popstate() continue parse } el.AlwaysPtr(&fs.pointerRcv) // Apply type parameters if available if typeInfo, ok := fs.TypeInfos[name]; ok && typeInfo.TypeParams != nil { typeParamsStr := formatTypeParams(typeInfo.TypeParams) ptrMap := getMspTypeParams(typeInfo.TypeParams) if typeParamsStr != "" && ptrMap != nil { el.SetTypeParams(gen.GenericTypeParams{ TypeParams: typeParamsStr, ToPointerMap: ptrMap, }) } } // push unresolved identities into // the graph of links and resolve after // we've handled every possible named type. if be, ok := el.(*gen.BaseElem); ok && be.Value == gen.IDENT { deferred[name] = be popstate() continue parse } el.Alias(name) fs.Identities[name] = el popstate() } if len(deferred) > 0 { fs.resolve(deferred) } } func strToMethod(s string) gen.Method { switch s { case "encode": return gen.Encode case "decode": return gen.Decode case "test": return gen.Test case "size": return gen.Size case "marshal": return gen.Marshal case "unmarshal": return gen.Unmarshal default: return 0 } } func (fs *FileSet) applyDirs(p *gen.Printer) { // apply directives of the form // // //msgp:encode ignore {{TypeName}} // loop: for _, d := range fs.Directives { chunks := strings.Split(d, " ") if len(chunks) > 1 { for i := range chunks { chunks[i] = strings.TrimSpace(chunks[i]) } m := strToMethod(chunks[0]) if m == 0 { warnf("unknown pass name: %q\n", chunks[0]) continue loop } if fn, ok := passDirectives[chunks[1]]; ok { pushstate(chunks[1]) err := fn(m, chunks[2:], p) if err != nil { warnf("error applying directive: %s\n", err) } popstate() } else { warnf("unrecognized directive %q\n", chunks[1]) } } else { warnf("empty directive: %q\n", d) } } p.CompactFloats = fs.CompactFloats p.ClearOmitted = fs.ClearOmitted p.NewTime = fs.NewTime p.AsUTC = fs.AsUTC p.ArrayLimit = fs.ArrayLimit p.MapLimit = fs.MapLimit p.MarshalLimits = fs.MarshalLimits p.LimitPrefix = fs.LimitPrefix } func (fs *FileSet) PrintTo(p *gen.Printer) error { fs.applyDirs(p) names := make([]string, 0, len(fs.Identities)) for name := range fs.Identities { names = append(names, name) } sort.Strings(names) for _, name := range names { el := fs.Identities[name] el.SetVarname("z") pushstate(el.TypeName()) err := p.Print(el) popstate() if err != nil { return err } } return nil } // getTypeSpecs extracts all of the *ast.TypeSpecs in the file // into fs.Identities, but does not set the actual element func (fs *FileSet) getTypeSpecs(f *ast.File) { // collect all imports... fs.Imports = append(fs.Imports, f.Imports...) // check all declarations... for i := range f.Decls { // for GenDecls... if g, ok := f.Decls[i].(*ast.GenDecl); ok { // and check the specs... for _, s := range g.Specs { // for ast.TypeSpecs.... if ts, ok := s.(*ast.TypeSpec); ok { // Handle type aliases, by adding a "replace" directive. if ts.Assign != 0 { if fs.Aliased == nil { fs.Aliased = make(map[string]string) } fs.Aliased[ts.Name.Name] = fmt.Sprintf("replace %s with:%s", ts.Name.Name, stringify(ts.Type)) continue } switch ts.Type.(type) { // this is the list of parse-able // type specs case *ast.ArrayType, *ast.StarExpr, *ast.Ident, *ast.StructType, *ast.MapType: fs.Specs[ts.Name.Name] = ts.Type // Store type info (no type params for non-struct types yet) fs.TypeInfos[ts.Name.Name] = &TypeInfo{ Type: ts.Type, TypeParams: ts.TypeParams, } } } } } } } func fieldName(f *ast.Field) string { switch len(f.Names) { case 0: return stringify(f.Type) case 1: return f.Names[0].Name default: return f.Names[0].Name + " (and others)" } } func (fs *FileSet) parseFieldList(fl *ast.FieldList) []gen.StructField { if fl == nil || fl.NumFields() == 0 { return nil } out := make([]gen.StructField, 0, fl.NumFields()) for _, field := range fl.List { pushstate(fieldName(field)) fds := fs.getField(field) if len(fds) > 0 { out = append(out, fds...) } else { warnf("ignored") } popstate() } return out } // translate *ast.Field into []gen.StructField func (fs *FileSet) getField(f *ast.Field) []gen.StructField { sf := make([]gen.StructField, 1) var extension, flatten bool // parse tag; otherwise field name is field tag if f.Tag != nil { var body string if fs.tagName != "" { body = reflect.StructTag(strings.Trim(f.Tag.Value, "`")).Get(fs.tagName) } if body == "" { body = reflect.StructTag(strings.Trim(f.Tag.Value, "`")).Get("msg") } if body == "" { body = reflect.StructTag(strings.Trim(f.Tag.Value, "`")).Get("msgpack") } tags := strings.Split(body, ",") if len(tags) >= 2 { for _, tag := range tags[1:] { switch tag { case "extension": extension = true case "flatten": flatten = true default: // Check for limit=N format if strings.HasPrefix(tag, "limit=") { limitStr := strings.TrimPrefix(tag, "limit=") if limit, err := strconv.ParseUint(limitStr, 10, 32); err == nil { sf[0].FieldLimit = uint32(limit) } else { warnf("invalid limit value in field tag: %s", limitStr) } } } } } // ignore "-" fields if tags[0] == "-" { return nil } sf[0].FieldTag = tags[0] sf[0].FieldTagParts = tags sf[0].RawTag = f.Tag.Value } ex := fs.parseExpr(f.Type) if ex == nil { return nil } // parse field name switch len(f.Names) { case 0: if flatten { return fs.getFieldsFromEmbeddedStruct(f.Type) } else { sf[0].FieldName = embedded(f.Type) } case 1: sf[0].FieldName = f.Names[0].Name default: // this is for a multiple in-line declaration, // e.g. type A struct { One, Two int } sf = sf[0:0] for _, nm := range f.Names { sf = append(sf, gen.StructField{ FieldTag: nm.Name, FieldName: nm.Name, FieldElem: ex.Copy(), }) } return sf } sf[0].FieldElem = ex if sf[0].FieldTag == "" { sf[0].FieldTag = sf[0].FieldName if len(sf[0].FieldTagParts) <= 1 { sf[0].FieldTagParts = []string{sf[0].FieldTag} } else { sf[0].FieldTagParts = append([]string{sf[0].FieldName}, sf[0].FieldTagParts[1:]...) } } // validate extension if extension { switch ex := ex.(type) { case *gen.Ptr: if b, ok := ex.Value.(*gen.BaseElem); ok { b.Value = gen.Ext } else { warnf("couldn't cast to extension.") return nil } case *gen.BaseElem: ex.Value = gen.Ext default: warnf("couldn't cast to extension.") return nil } } return sf } func (fs *FileSet) getFieldsFromEmbeddedStruct(f ast.Expr) []gen.StructField { switch f := f.(type) { case *ast.Ident: s := fs.Specs[f.Name] switch s := s.(type) { case *ast.StructType: return fs.parseFieldList(s.Fields) default: return nil } default: // other possibilities are disallowed return nil } } // extract embedded field name // // so, for a struct like // // type A struct { // io.Writer // } // // we want "Writer" func embedded(f ast.Expr) string { switch f := f.(type) { case *ast.Ident: return f.Name case *ast.StarExpr: return embedded(f.X) case *ast.SelectorExpr: return f.Sel.Name default: // other possibilities are disallowed return "" } } // stringify a field type name func stringify(e ast.Expr) string { switch e := e.(type) { case *ast.Ident: return e.Name case *ast.StarExpr: return "*" + stringify(e.X) case *ast.SelectorExpr: return stringify(e.X) + "." + e.Sel.Name case *ast.ArrayType: if e.Len == nil { return "[]" + stringify(e.Elt) } return fmt.Sprintf("[%s]%s", stringify(e.Len), stringify(e.Elt)) case *ast.InterfaceType: if e.Methods == nil || e.Methods.NumFields() == 0 { return "interface{}" } case *ast.BasicLit: return e.Value case *ast.IndexExpr: // Single type argument: Generic[T] return fmt.Sprintf("%s[%s]", stringify(e.X), stringify(e.Index)) case *ast.IndexListExpr: // Multiple type arguments: Generic[A,B,...] args := make([]string, 0, len(e.Indices)) for _, ix := range e.Indices { args = append(args, stringify(ix)) } return fmt.Sprintf("%s[%s]", stringify(e.X), strings.Join(args, ",")) } return "" } // recursively translate ast.Expr to gen.Elem; nil means type not supported // expected input types: // - *ast.MapType (map[T]J) // - *ast.Ident (name) // - *ast.ArrayType ([(sz)]T) // - *ast.StarExpr (*T) // - *ast.StructType (struct {}) // - *ast.SelectorExpr (a.B) // - *ast.InterfaceType (interface {}) func (fs *FileSet) parseExpr(e ast.Expr) gen.Elem { switch e := e.(type) { case *ast.MapType: switch k := e.Key.(type) { case *ast.Ident: switch k.Name { case "string": if in := fs.parseExpr(e.Value); in != nil { return &gen.Map{Value: in, AllowBinMaps: fs.AllowBinMaps, AllowMapShims: fs.AllowMapShims, AutoMapShims: fs.AutoMapShims} } warnf("%s: map keys of type are not supported\n", stringify(e.Key)) default: if !fs.AllowMapShims && !fs.AllowBinMaps && !fs.AutoMapShims { warnf("map keys of type %s are not supported without binary keys or shimming\n", stringify(e.Key)) return nil } // Allow for other types, assuming they will be shimmed later. key := fs.parseExpr(k) // Types that aren't idents are native types and cannot currently be used as map keys. switch k := key.(type) { case *gen.BaseElem: switch k.Value { case gen.IDENT: if in := fs.parseExpr(e.Value); in != nil { return &gen.Map{Value: in, Key: key, AllowBinMaps: fs.AllowBinMaps, AllowMapShims: fs.AllowMapShims, AutoMapShims: fs.AutoMapShims} } warnf("map keys of type %s are not supported\n", k.TypeName()) // Exclude types that cannot be used as native map keys. case gen.Bytes: warnf("map keys of type %s are not supported\n", k.TypeName()) default: if in := fs.parseExpr(e.Value); (fs.AllowBinMaps || (fs.AutoMapShims && gen.CanAutoShim[k.Value])) && in != nil { return &gen.Map{Value: in, Key: key, AllowBinMaps: fs.AllowBinMaps, AllowMapShims: fs.AllowMapShims, AutoMapShims: fs.AutoMapShims} } warnf("map keys of type %s are not supported without binary keys or shimming\n", k.TypeName()) } default: warnf("map keys of type %s are not supported\n", k.TypeName()) } return nil } case *ast.ArrayType: if fs.AllowBinMaps { key := fs.parseExpr(k) if in := fs.parseExpr(e.Value); fs.AllowBinMaps && in != nil { return &gen.Map{Value: in, Key: key, AllowBinMaps: fs.AllowBinMaps, AllowMapShims: fs.AllowMapShims, AutoMapShims: fs.AutoMapShims} } } warnf("array map keys (type %s) are not supported without binary keys or shimming\n", stringify(e.Key)) default: warnf("array map key type not supported\n") } return nil case *ast.Ident: b := gen.Ident(e.Name) // work to resolve this expression // can be done later, once we've resolved // everything else. if b.Value == gen.IDENT { if _, ok := fs.Specs[e.Name]; !ok && fs.Aliased[e.Name] == "" { // This can be a generic type. warnf("possible non-local identifier: %s\n", e.Name) } } return b case *ast.ArrayType: // special case for []byte if e.Len == nil { if i, ok := e.Elt.(*ast.Ident); ok && i.Name == "byte" { return &gen.BaseElem{Value: gen.Bytes} } } // return early if we don't know // what the slice element type is els := fs.parseExpr(e.Elt) if els == nil { return nil } // array and not a slice if e.Len != nil { switch s := e.Len.(type) { case *ast.BasicLit: return &gen.Array{ Size: s.Value, Els: els, } case *ast.Ident: return &gen.Array{ Size: s.String(), Els: els, } case *ast.SelectorExpr: return &gen.Array{ Size: stringify(s), Els: els, } default: return nil } } return &gen.Slice{Els: els} case *ast.StarExpr: if v := fs.parseExpr(e.X); v != nil { return &gen.Ptr{Value: v} } return nil case *ast.StructType: return &gen.Struct{Fields: fs.parseFieldList(e.Fields)} case *ast.SelectorExpr: return gen.Ident(stringify(e)) case *ast.InterfaceType: // support `interface{}` if len(e.Methods.List) == 0 { return &gen.BaseElem{Value: gen.Intf} } return nil case *ast.IndexExpr: // Treat a generic instantiation like an identifier of the instantiated name. // Example: GenericTest2[T] -> "GenericTest2[T]" return gen.Ident(stringify(e)) case *ast.IndexListExpr: // Treat a generic instantiation with multiple args similarly. return gen.Ident(stringify(e)) default: // other types not supported return nil } } var Logf func(s string, v ...any) func infof(s string, v ...any) { if Logf != nil { pushstate(s) Logf("info: "+strings.Join(logctx, ": "), v...) popstate() } } func warnf(s string, v ...any) { if Logf != nil { pushstate(s) Logf("warn: "+strings.Join(logctx, ": "), v...) popstate() } } var logctx []string // push logging state func pushstate(s string) { logctx = append(logctx, s) } // pop logging state func popstate() { logctx = logctx[:len(logctx)-1] } msgp-1.6.1/parse/inline.go000066400000000000000000000105671511433505400154160ustar00rootroot00000000000000package parse import ( "sort" "strings" "github.com/tinylib/msgp/gen" ) // This file defines when and how we // propagate type information from // one type declaration to another. // After the processing pass, every // non-primitive type is marshalled/unmarshalled/etc. // through a function call. Here, we propagate // the type information into the caller's type // tree *if* the child type is simple enough. // // For example, types like // // type A [4]int // // will get pushed into parent methods, // whereas types like // // type B [3]map[string]struct{A, B [4]string} // // will not. // this is an approximate measure // of the number of children in a node const maxComplex = 5 // begin recursive search for identities with the // given name and replace them with e func (fs *FileSet) findShim(id string, e gen.Elem, addID bool) { for name, el := range fs.Identities { pushstate(name) switch el := el.(type) { case *gen.Struct: for i := range el.Fields { fs.nextShim(&el.Fields[i].FieldElem, id, e) } case *gen.Array: fs.nextShim(&el.Els, id, e) case *gen.Slice: fs.nextShim(&el.Els, id, e) case *gen.Map: fs.nextShim(&el.Value, id, e) if el.Key != nil { fs.nextShim(&el.Key, id, e) } case *gen.Ptr: fs.nextShim(&el.Value, id, e) } popstate() } if addID { fs.Identities[id] = e } } func (fs *FileSet) nextShim(ref *gen.Elem, id string, e gen.Elem) { if (*ref).TypeName() == id { vn := (*ref).Varname() *ref = e.Copy() (*ref).SetVarname(vn) } else { switch el := (*ref).(type) { case *gen.Struct: for i := range el.Fields { fs.nextShim(&el.Fields[i].FieldElem, id, e) } case *gen.Array: fs.nextShim(&el.Els, id, e) case *gen.Slice: fs.nextShim(&el.Els, id, e) case *gen.Map: fs.nextShim(&el.Value, id, e) if el.Key != nil { fs.nextShim(&el.Key, id, e) } case *gen.Ptr: fs.nextShim(&el.Value, id, e) } } } // propInline identifies and inlines candidates func (fs *FileSet) propInline() { type gelem struct { name string el gen.Elem } all := make([]gelem, 0, len(fs.Identities)) for name, el := range fs.Identities { all = append(all, gelem{name: name, el: el}) } // make sure we process inlining determinstically: // start with the least-complex elems; // use identifier names as a tie-breaker sort.Slice(all, func(i, j int) bool { ig, jg := &all[i], &all[j] ic, jc := ig.el.Complexity(), jg.el.Complexity() return ic < jc || (ic == jc && ig.name < jg.name) }) for i := range all { name := all[i].name pushstate(name) switch el := all[i].el.(type) { case *gen.Struct: for i := range el.Fields { fs.nextInline(&el.Fields[i].FieldElem, name, el.TypeParams()) } case *gen.Array: fs.nextInline(&el.Els, name, el.TypeParams()) case *gen.Slice: fs.nextInline(&el.Els, name, el.TypeParams()) case *gen.Map: fs.nextInline(&el.Value, name, el.TypeParams()) case *gen.Ptr: fs.nextInline(&el.Value, name, el.TypeParams()) } popstate() } } const fatalloop = `detected infinite recursion in inlining loop! Please file a bug at github.com/tinylib/msgp/issues! Thanks! ` func (fs *FileSet) nextInline(ref *gen.Elem, root string, params gen.GenericTypeParams) { switch el := (*ref).(type) { case *gen.BaseElem: // ensure that we're not inlining // a type into itself typ := el.TypeName() if el.Value == gen.IDENT && typ != root { if node, ok := fs.Identities[typ]; ok && node.Complexity() < maxComplex { infof("inlining %s\n", typ) // This should never happen; it will cause // infinite recursion. if node == *ref { panic(fatalloop) } *ref = node.Copy() fs.nextInline(ref, node.TypeName(), params) } else if !ok && !el.Resolved() { if params.ToPointerMap[typ] == "" && (!strings.Contains(typ, "[") || !strings.Contains(typ, "]")) { // this is the point at which we're sure that // we've got a type that isn't a primitive, // a library builtin, or a processed type warnf("unresolved identifier: %s\n", typ) } } } case *gen.Struct: for i := range el.Fields { fs.nextInline(&el.Fields[i].FieldElem, root, el.TypeParams()) } case *gen.Array: fs.nextInline(&el.Els, root, params) case *gen.Slice: fs.nextInline(&el.Els, root, params) case *gen.Map: fs.nextInline(&el.Value, root, params) case *gen.Ptr: fs.nextInline(&el.Value, root, params) default: panic("bad elem type") } } msgp-1.6.1/printer/000077500000000000000000000000001511433505400141515ustar00rootroot00000000000000msgp-1.6.1/printer/print.go000066400000000000000000000104331511433505400156350ustar00rootroot00000000000000package printer import ( "bytes" "fmt" "hash/crc32" "io" "math" "os" "path/filepath" "strings" "github.com/tinylib/msgp/gen" "github.com/tinylib/msgp/parse" "golang.org/x/tools/imports" ) var Logf func(s string, v ...any) // PrintFile prints the methods for the provided list // of elements to the given file name and canonical // package path. func PrintFile(file string, f *parse.FileSet, mode gen.Method) error { out, tests, err := generate(file, f, mode) if err != nil { return err } // we'll run goimports on the main file // in another goroutine, and run it here // for the test file. empirically, this // takes about the same amount of time as // doing them in serial when GOMAXPROCS=1, // and faster otherwise. res := goformat(file, out.Bytes()) if tests != nil { testfile := strings.TrimSuffix(file, ".go") + "_test.go" err = format(testfile, tests.Bytes()) if err != nil { return err } if Logf != nil { Logf("Wrote and formatted \"%s\"\n", testfile) } } err = <-res if err != nil { os.WriteFile(file+".broken", out.Bytes(), os.ModePerm) if Logf != nil { Logf("Error: %s. Wrote broken output to %s\n", err, file+".broken") } return err } return nil } func format(file string, data []byte) error { out, err := imports.Process(file, data, nil) if err != nil { return err } return os.WriteFile(file, out, 0o600) } func goformat(file string, data []byte) <-chan error { out := make(chan error, 1) go func(file string, data []byte, end chan error) { end <- format(file, data) if Logf != nil { Logf("Wrote and formatted \"%s\"\n", file) } }(file, data, out) return out } func dedupImports(imp []string) []string { m := make(map[string]struct{}) for i := range imp { m[imp[i]] = struct{}{} } r := []string{} for k := range m { r = append(r, k) } return r } func generate(file string, f *parse.FileSet, mode gen.Method) (*bytes.Buffer, *bytes.Buffer, error) { outbuf := bytes.NewBuffer(make([]byte, 0, 4096)) writePkgHeader(outbuf, f.Package) myImports := []string{"github.com/tinylib/msgp/msgp"} for _, imp := range f.Imports { if imp.Name != nil { // have an alias, include it. myImports = append(myImports, imp.Name.Name+` `+imp.Path.Value) } else { myImports = append(myImports, imp.Path.Value) } } dedup := dedupImports(myImports) writeImportHeader(outbuf, dedup...) writeLimitConstants(outbuf, file, f) var testbuf *bytes.Buffer var testwr io.Writer if mode&gen.Test == gen.Test { testbuf = bytes.NewBuffer(make([]byte, 0, 4096)) writePkgHeader(testbuf, f.Package) if mode&(gen.Encode|gen.Decode) != 0 { writeImportHeader(testbuf, "bytes", "github.com/tinylib/msgp/msgp", "testing") } else { writeImportHeader(testbuf, "github.com/tinylib/msgp/msgp", "testing") } testwr = testbuf } return outbuf, testbuf, f.PrintTo(gen.NewPrinter(mode, outbuf, testwr)) } func writePkgHeader(b *bytes.Buffer, name string) { // write generated code marker // https://github.com/tinylib/msgp/issues/229 // https://golang.org/s/generatedcode b.WriteString("// Code generated by github.com/tinylib/msgp DO NOT EDIT.\n\n") b.WriteString("package ") b.WriteString(name) b.WriteString("\n\n") } func writeImportHeader(b *bytes.Buffer, imports ...string) { b.WriteString("import (\n") for _, im := range imports { if im[len(im)-1] == '"' { // support aliased imports fmt.Fprintf(b, "\t%s\n", im) } else { fmt.Fprintf(b, "\t%q\n", im) } } b.WriteString(")\n\n") } // generateFilePrefix creates a deterministic, unique prefix for constants based on the file name func generateFilePrefix(filename string) string { base := filepath.Base(filename) hash := crc32.ChecksumIEEE([]byte(base)) return fmt.Sprintf("z%08x", hash) } func writeLimitConstants(b *bytes.Buffer, file string, f *parse.FileSet) { if f.ArrayLimit != math.MaxUint32 || f.MapLimit != math.MaxUint32 { prefix := generateFilePrefix(file) b.WriteString("// Size limits for msgp deserialization\n") b.WriteString("const (\n") if f.ArrayLimit != math.MaxUint32 { fmt.Fprintf(b, "\t%slimitArrays = %d\n", prefix, f.ArrayLimit) } if f.MapLimit != math.MaxUint32 { fmt.Fprintf(b, "\t%slimitMaps = %d\n", prefix, f.MapLimit) } b.WriteString(")\n\n") // Store the prefix in FileSet so generators can use it f.LimitPrefix = prefix } } msgp-1.6.1/tinygotest/000077500000000000000000000000001511433505400146775ustar00rootroot00000000000000msgp-1.6.1/tinygotest/.gitignore000066400000000000000000000001071511433505400166650ustar00rootroot00000000000000*_gen.go *_gen_test.go *.out *.bin *.hex *.wasm *.wasi nativebin tmp* msgp-1.6.1/tinygotest/testdata/000077500000000000000000000000001511433505400165105ustar00rootroot00000000000000msgp-1.6.1/tinygotest/testdata/empty/000077500000000000000000000000001511433505400176465ustar00rootroot00000000000000msgp-1.6.1/tinygotest/testdata/empty/main.go000066400000000000000000000001651511433505400211230ustar00rootroot00000000000000package main // baseline file just so we can compare the size func main() { println("successfully did nothing") } msgp-1.6.1/tinygotest/testdata/roundtrip/000077500000000000000000000000001511433505400205365ustar00rootroot00000000000000msgp-1.6.1/tinygotest/testdata/roundtrip/main.go000066400000000000000000000073611511433505400220200ustar00rootroot00000000000000package main import ( "bytes" "github.com/tinylib/msgp/msgp" ) //go:generate msgp type SomeStruct struct { A string `msg:"a"` } type EmbeddedStruct struct { A string `msg:"a"` } // Example provides a decent variety of types and features and // lets us test for basic functionality in TinyGo. type Example struct { Interface interface{} `msg:"interface"` Any any `msg:"any"` Int64 int64 `msg:"int64"` Uint64 uint64 `msg:"uint64"` Int32 int32 `msg:"int32"` Uint32 uint32 `msg:"uint32"` Int16 int32 `msg:"int16"` Uint16 uint32 `msg:"uint16"` Int8 int32 `msg:"int8"` Byte byte `msg:"byte"` Float64 float64 `msg:"float64"` Float32 float32 `msg:"float32"` String string `msg:"string"` ByteSlice []byte `msg:"byte_slice"` StringSlice []string `msg:"string_slice"` IntArray [2]int `msg:"int_array"` SomeStruct SomeStruct `msg:"some_struct"` EmbeddedStruct Omitted string `msg:"-"` OmitEmptyString string `msg:"omit_empty_string,omitempty"` } // Setup populuates the struct with test data func (e *Example) Setup() { e.Interface = 10 e.Any = "any" e.Int64 = 10 e.Uint64 = 11 e.Int32 = 12 e.Uint32 = 13 e.Int16 = 14 e.Uint16 = 15 e.Int8 = 16 e.Byte = 17 e.Float64 = 18.1 e.Float32 = 19.2 e.String = "astr" e.ByteSlice = []byte("bstr") e.StringSlice = []string{"a", "b"} e.IntArray = [...]int{20, 21} e.SomeStruct = SomeStruct{A: "x"} e.EmbeddedStruct = EmbeddedStruct{A: "y"} e.Omitted = "nope" e.OmitEmptyString = "here" } func (e *Example) Eq(e2 *Example) bool { if int64(e.Interface.(int)) != e2.Interface.(int64) { return false } if e.Any.(string) != e2.Any.(string) { return false } if e.Int64 != e2.Int64 { return false } if e.Uint64 != e2.Uint64 { return false } if e.Int32 != e2.Int32 { return false } if e.Uint32 != e2.Uint32 { return false } if e.Int16 != e2.Int16 { return false } if e.Uint16 != e2.Uint16 { return false } if e.Int8 != e2.Int8 { return false } if e.Byte != e2.Byte { return false } if e.Float64 != e2.Float64 { return false } if e.Float32 != e2.Float32 { return false } if e.String != e2.String { return false } if bytes.Compare(e.ByteSlice, e2.ByteSlice) != 0 { return false } if len(e.StringSlice) != len(e2.StringSlice) { return false } for i := 0; i < len(e.StringSlice); i++ { if e.StringSlice[i] != e2.StringSlice[i] { return false } } if len(e.IntArray) != len(e2.IntArray) { return false } for i := 0; i < len(e.IntArray); i++ { if e.IntArray[i] != e2.IntArray[i] { return false } } if e.SomeStruct.A != e2.SomeStruct.A { return false } if e.EmbeddedStruct.A != e2.EmbeddedStruct.A { return false } if e.Omitted != e2.Omitted { return false } if e.OmitEmptyString != e2.OmitEmptyString { return false } return true } var buf [256]byte func main() { var e Example e.Setup() b, err := e.MarshalMsg(buf[:0]) if err != nil { panic(err) } b1 := b var e2 Example _, err = e2.UnmarshalMsg(b) if err != nil { panic(err) } println("marshal/unmarshal done: ", &e2) e.Omitted = "" if !e.Eq(&e2) { panic("comparison after marshal/unmarhsal failed") } var wbuf bytes.Buffer mw := msgp.NewWriterSize(&wbuf, 64) e.Omitted = "other" err = e.EncodeMsg(mw) if err != nil { panic(err) } mw.Flush() e2 = Example{} mr := msgp.NewReaderSize(bytes.NewReader(wbuf.Bytes()), 64) err = e2.DecodeMsg(mr) if err != nil { panic(err) } println("writer/reader done: ", &e2) e.Omitted = "" if !e.Eq(&e2) { panic("comparison after writer/reader failed") } if bytes.Compare(wbuf.Bytes(), b1) != 0 { panic("writer and marshal produced different results") } } msgp-1.6.1/tinygotest/testdata/simple_bytes_append/000077500000000000000000000000001511433505400225365ustar00rootroot00000000000000msgp-1.6.1/tinygotest/testdata/simple_bytes_append/main.go000066400000000000000000000006601511433505400240130ustar00rootroot00000000000000package main import "github.com/tinylib/msgp/msgp" type Example struct { I int S string } var buf [64]byte func main() { e := Example{ I: 1, S: "2", } b := buf[:0] b = msgp.AppendMapHeader(b, 2) b = msgp.AppendString(b, "i") b = msgp.AppendInt(b, e.I) b = msgp.AppendString(b, "s") b = msgp.AppendString(b, e.S) println("done, len(b):", len(b)) for i := 0; i < len(b); i++ { print(b[i], " ") } println() } msgp-1.6.1/tinygotest/testdata/simple_bytes_read/000077500000000000000000000000001511433505400222025ustar00rootroot00000000000000msgp-1.6.1/tinygotest/testdata/simple_bytes_read/main.go000066400000000000000000000014741511433505400234630ustar00rootroot00000000000000package main import "github.com/tinylib/msgp/msgp" type Example struct { I int S string } func main() { b := []byte{130, 161, 105, 1, 161, 115, 161, 50} e := Example{} sz, b, err := msgp.ReadMapHeaderBytes(b) if err != nil { panic(err) } if sz != 2 { panic("bad sz") } for i := 0; i < int(sz); i++ { var sb []byte var i32 int32 var err error sb, b, err = msgp.ReadStringZC(b) switch string(sb) { case "i": i32, b, err = msgp.ReadInt32Bytes(b) if err != nil { panic(err) } e.I = int(i32) case "s": sb, b, err = msgp.ReadStringZC(b) if err != nil { panic(err) } e.S = string(sb) default: panic("unexpected field:" + string(sb)) } } if len(b) != 0 { panic("unexpected extra") } if e.I != 1 || e.S != "2" { panic("not equal") } println("done") } msgp-1.6.1/tinygotest/testdata/simple_marshal/000077500000000000000000000000001511433505400215105ustar00rootroot00000000000000msgp-1.6.1/tinygotest/testdata/simple_marshal/main.go000066400000000000000000000004701511433505400227640ustar00rootroot00000000000000package main //go:generate msgp type Example struct { I int `msg:"i"` S string `msg:"s"` } func main() { e := Example{ I: 1, S: "2", } b, err := e.MarshalMsg(nil) if err != nil { panic(err) } println("done, len(b):", len(b)) for i := 0; i < len(b); i++ { print(b[i], " ") } println() } msgp-1.6.1/tinygotest/testdata/simple_roundtrip/000077500000000000000000000000001511433505400221075ustar00rootroot00000000000000msgp-1.6.1/tinygotest/testdata/simple_roundtrip/main.go000066400000000000000000000011361511433505400233630ustar00rootroot00000000000000package main //go:generate msgp type Example struct { I int `msg:"i"` S string `msg:"s"` // NOTE: floats omitted intentionally, many MCUs don't have // native support for it so the binary size bloats just due to // the software float implementation } func main() { e := Example{ I: 1, S: "2", } b, err := e.MarshalMsg(nil) if err != nil { panic(err) } var e2 Example extra, err := e2.UnmarshalMsg(b) if err != nil { panic(err) } if len(extra) != 0 { panic("unexpected extra") } if e.I != e2.I || e.S != e2.S { panic("not equal") } println("done, len(b):", len(b)) } msgp-1.6.1/tinygotest/testdata/simple_unmarshal/000077500000000000000000000000001511433505400220535ustar00rootroot00000000000000msgp-1.6.1/tinygotest/testdata/simple_unmarshal/main.go000066400000000000000000000006111511433505400233240ustar00rootroot00000000000000package main //go:generate msgp type Example struct { I int `msg:"i"` S string `msg:"s"` } func main() { b := []byte{130, 161, 105, 1, 161, 115, 161, 50} var e2 Example extra, err := e2.UnmarshalMsg(b) if err != nil { panic(err) } if len(extra) != 0 { panic("unexpected extra") } if e2.I != 1 || e2.S != "2" { panic("not equal") } println("done, len(b):", len(b)) } msgp-1.6.1/tinygotest/tinygo_test.go000066400000000000000000000155251511433505400176060ustar00rootroot00000000000000//go:build amd64 || darwin package tinygotest // NOTE: this is intended to be run with `go test` not `tinygo test`, // as it then in turn performs various `tinygo build` commands and // verifies the output. import ( "bytes" "os" "os/exec" "path/filepath" "runtime" "strings" "testing" ) // empty gives us a baseline to compare sizes (and to prove that tinygo itself isn't broken) func TestEmptyRun(t *testing.T) { // build and run native executable tinygoBuild(t, "empty") run(t, "empty", "nativebin") } func TestEmptyBuild(t *testing.T) { // build for various environments tinygoBuild(t, "empty", buildOnlyTargets...) reportSizes(t, "empty") } // roundtrip provides reasonable coverage for various cases, but is // fairly bloated in terms of size compared to simpler examples func TestRoundtripRun(t *testing.T) { // build and run native executable goGenerate(t, "roundtrip") tinygoBuild(t, "roundtrip") run(t, "roundtrip", "nativebin") } func TestRoundtripBuild(t *testing.T) { // build for various environments goGenerate(t, "roundtrip") tinygoBuild(t, "roundtrip", buildOnlyTargets...) reportSizes(t, "roundtrip") } // simple_roundtrip is a minimal marshal+unmarshal example and should show // the baseline size when only using minimal functionality and marshal+unmarshal func TestSimpleRoundtripRun(t *testing.T) { // build and run native executable goGenerate(t, "simple_roundtrip") tinygoBuild(t, "simple_roundtrip") run(t, "simple_roundtrip", "nativebin") } func TestSimpleRoundtripBuild(t *testing.T) { // build for various environments goGenerate(t, "simple_roundtrip") tinygoBuild(t, "simple_roundtrip", buildOnlyTargets...) sizes := reportSizes(t, "simple_roundtrip") // this was ~13k at the time this test was written, // if it bloats up to over 20k, we assume something is wrong // (e.g. "fmt" or other large package being using) sz := sizes["arduino-nano33.bin"] if sz > 20000 { t.Errorf("arduino-nano33.bin is larger than expected: %d", sz) } } // simple_marshal is just the MarshalMsg part func TestSimpleMarshalRun(t *testing.T) { // build and run native executable goGenerate(t, "simple_marshal") tinygoBuild(t, "simple_marshal") run(t, "simple_marshal", "nativebin") } func TestSimpleMarshalBuild(t *testing.T) { // build for various environments goGenerate(t, "simple_marshal") tinygoBuild(t, "simple_marshal", buildOnlyTargets...) reportSizes(t, "simple_marshal") } // simple_unmarshal is just the UnmarshalMsg part func TestSimpleUnmarshalRun(t *testing.T) { // build and run native executable goGenerate(t, "simple_unmarshal") tinygoBuild(t, "simple_unmarshal") run(t, "simple_unmarshal", "nativebin") } func TestSimpleUnmarshalBuild(t *testing.T) { // build for various environments goGenerate(t, "simple_unmarshal") tinygoBuild(t, "simple_unmarshal", buildOnlyTargets...) reportSizes(t, "simple_unmarshal") } // simple_bytes_append is AppendX() methods without code generation func TestSimpleBytesAppendRun(t *testing.T) { // build and run native executable goGenerate(t, "simple_bytes_append") tinygoBuild(t, "simple_bytes_append") run(t, "simple_bytes_append", "nativebin") } func TestSimpleBytesAppendBuild(t *testing.T) { // build for various environments goGenerate(t, "simple_bytes_append") tinygoBuild(t, "simple_bytes_append", buildOnlyTargets...) reportSizes(t, "simple_bytes_append") } // simple_bytes_append is ReadX() methods without code generation func TestSimpleBytesReadRun(t *testing.T) { // build and run native executable goGenerate(t, "simple_bytes_read") tinygoBuild(t, "simple_bytes_read") run(t, "simple_bytes_read", "nativebin") } func TestSimpleBytesReadBuild(t *testing.T) { // build for various environments goGenerate(t, "simple_bytes_read") tinygoBuild(t, "simple_bytes_read", buildOnlyTargets...) reportSizes(t, "simple_bytes_read") } // do builds for these tinygo boards/environments to make sure // it at least compiles var buildOnlyTargets = []string{ "arduino-nano33", // ARM Cortex-M0, SAMD21 "feather-m4", // ARM Cortex-M4, SAMD51 "wasm", // WebAssembly // "arduino-nano", // AVR - roundtrip build currently fails with: could not store type code number inside interface type code // "esp32-coreboard-v2", // ESP - xtensa seems to require additional setup, currently errors with: No available targets are compatible with triple "xtensa" } func run(t *testing.T, dir, exe string, args ...string) { t.Helper() if runtime.GOOS == "windows" { exe += ".exe" } cmd := exec.Command("./" + exe) wd, err := os.Getwd() if err != nil { t.Fatal(err) } cmd.Dir = filepath.Join(wd, "testdata", dir) cmd.Args = args b, err := cmd.CombinedOutput() if len(bytes.TrimSpace(b)) > 0 { t.Logf("%s: %s %v; output: %s", dir, exe, args, b) } if err != nil { t.Fatal(err) } } func goGenerate(t *testing.T, dir string) { t.Helper() t.Logf("%s: go generate", dir) cmd := exec.Command("go", "generate") wd, err := os.Getwd() if err != nil { t.Fatal(err) } cmd.Dir = filepath.Join(wd, "testdata", dir) b, err := cmd.CombinedOutput() if len(bytes.TrimSpace(b)) > 0 { t.Logf("%s: go generate output: %s", dir, b) } if err != nil { t.Fatal(err) } } func tinygoBuild(t *testing.T, dir string, targets ...string) { t.Helper() wd, err := os.Getwd() if err != nil { t.Fatal(err) } dirabs := filepath.Join(wd, "testdata", dir) // no targets specified implies just build the native executable if len(targets) == 0 { targets = []string{""} } for _, tgt := range targets { ext := ".bin" if tgt == "wasm" { ext = ".wasm" } dst := tgt + ext if tgt == "" { dst = "nativebin" if runtime.GOOS == "windows" { dst += ".exe" } } var args []string if tgt == "" { // empty target means the native platform args = []string{"build", "-o=" + dst, "."} } else { args = []string{"build", "-target=" + tgt, "-o=" + dst, "."} } t.Logf("%s: tinygo %v", dir, args) cmd := exec.Command("tinygo", args...) cmd.Dir = dirabs b, err := cmd.CombinedOutput() if len(bytes.TrimSpace(b)) > 0 { t.Logf("%s: tinygo build %v; output: %s", dir, args, b) } if err != nil { // See https://github.com/tinygo-org/tinygo/issues/3977 if strings.Contains(string(b), "could not find wasm-opt") { t.Skipf("skipping wasm test because wasm-opt is not installed") } t.Fatal(err) } } } var spacePad = strings.Repeat(" ", 64) func reportSizes(t *testing.T, dir string) (ret map[string]int64) { ret = make(map[string]int64) var fnl []string for _, gl := range []string{"*.bin", "*.wasm"} { fnl2, err := filepath.Glob(filepath.Join("testdata", dir, gl)) if err != nil { t.Fatal(err) } fnl = append(fnl, fnl2...) } for _, fn := range fnl { st, err := os.Stat(fn) if err != nil { t.Fatal(err) } _, jfn := filepath.Split(fn) t.Logf("size report - %s %6d bytes", (jfn + spacePad)[:24], st.Size()) ret[jfn] = st.Size() } return ret }