Showing preview only (682K chars total). Download the full file or copy to clipboard to get everything.
Repository: shamaton/msgpack
Branch: main
Commit: 014715d0f53e
Files: 245
Total size: 619.5 KB
Directory structure:
gitextract_aynht_4q/
├── .github/
│ ├── release.yml
│ └── workflows/
│ ├── stale.yml
│ ├── tagpr.yml
│ └── test.yml
├── .gitignore
├── .tagpr
├── CHANGELOG.md
├── LICENSE
├── README.md
├── codecov.yml
├── crash_test.go
├── decode.go
├── def/
│ ├── def.go
│ └── error.go
├── encode.go
├── errors.go
├── ext/
│ ├── decode.go
│ ├── decoder_stream.go
│ ├── encode.go
│ └── encode_stream.go
├── go.mod
├── internal/
│ ├── common/
│ │ ├── buffer.go
│ │ ├── common.go
│ │ ├── common_test.go
│ │ └── testutil/
│ │ ├── reader.go
│ │ ├── struct.go
│ │ └── testutil.go
│ ├── decoding/
│ │ ├── bin.go
│ │ ├── bin_test.go
│ │ ├── bool.go
│ │ ├── bool_test.go
│ │ ├── complex.go
│ │ ├── complex_test.go
│ │ ├── decoding.go
│ │ ├── decoding_test.go
│ │ ├── ext.go
│ │ ├── ext_test.go
│ │ ├── float.go
│ │ ├── float_test.go
│ │ ├── int.go
│ │ ├── int_test.go
│ │ ├── interface.go
│ │ ├── interface_test.go
│ │ ├── map.go
│ │ ├── map_test.go
│ │ ├── nil.go
│ │ ├── read.go
│ │ ├── slice.go
│ │ ├── slice_test.go
│ │ ├── string.go
│ │ ├── string_test.go
│ │ ├── struct.go
│ │ ├── struct_test.go
│ │ ├── uint.go
│ │ └── uint_test.go
│ ├── encoding/
│ │ ├── bool.go
│ │ ├── byte.go
│ │ ├── byte_test.go
│ │ ├── complex.go
│ │ ├── encoding.go
│ │ ├── encoding_test.go
│ │ ├── ext.go
│ │ ├── ext_test.go
│ │ ├── float.go
│ │ ├── int.go
│ │ ├── map.go
│ │ ├── nil.go
│ │ ├── set.go
│ │ ├── slice.go
│ │ ├── slice_test.go
│ │ ├── string.go
│ │ ├── struct.go
│ │ ├── struct_test.go
│ │ └── uint.go
│ └── stream/
│ ├── decoding/
│ │ ├── bin.go
│ │ ├── bin_test.go
│ │ ├── bool.go
│ │ ├── bool_test.go
│ │ ├── complex.go
│ │ ├── complex_test.go
│ │ ├── decoding.go
│ │ ├── decoding_test.go
│ │ ├── ext.go
│ │ ├── ext_test.go
│ │ ├── float.go
│ │ ├── float_test.go
│ │ ├── int.go
│ │ ├── int_test.go
│ │ ├── interface.go
│ │ ├── interface_test.go
│ │ ├── map.go
│ │ ├── map_test.go
│ │ ├── nil.go
│ │ ├── read.go
│ │ ├── slice.go
│ │ ├── slice_test.go
│ │ ├── string.go
│ │ ├── string_test.go
│ │ ├── struct.go
│ │ ├── struct_test.go
│ │ ├── uint.go
│ │ └── uint_test.go
│ └── encoding/
│ ├── bool.go
│ ├── bool_test.go
│ ├── byte.go
│ ├── byte_test.go
│ ├── complex.go
│ ├── complex_test.go
│ ├── encoding.go
│ ├── encoding_test.go
│ ├── ext.go
│ ├── ext_test.go
│ ├── float.go
│ ├── float_test.go
│ ├── int.go
│ ├── int_test.go
│ ├── map.go
│ ├── map_test.go
│ ├── nil.go
│ ├── set.go
│ ├── slice.go
│ ├── slice_test.go
│ ├── string.go
│ ├── string_test.go
│ ├── struct.go
│ ├── struct_test.go
│ ├── uint.go
│ └── uint_test.go
├── msgpack.go
├── msgpack_example_test.go
├── msgpack_test.go
├── testdata/
│ └── crashers/
│ ├── 007424b0caabdaf653d7efeb3ce6c1c127f628c6
│ ├── 01d1844ec3cdec0e8d60d81fcded73f920270e9c
│ ├── 049b2af75fc4ee7160c7ea9bad41a5167b501d32
│ ├── 051d081de15ae4680b4156046787aae72ae0adcc
│ ├── 063fea9d12105a80ee56a482aac428543fcf8d49
│ ├── 080c57e02ab7e704e2a2e93aad7674a574dc9d69
│ ├── 0d45579ce9ef9c1ca6e945d3f21ad31097f0c3c0
│ ├── 0f7994b18fb75394c81005c925dd1ae153ad57ad
│ ├── 121a9af889bd4ca2266be5a4f680d3bead8d02d6
│ ├── 19eb9972c2a406f15bbae850ac33b42ebd88f7a7
│ ├── 1a3492dbf0b80d08f12ce49c620239e48b74c08c
│ ├── 1ae8bba51072f9ff2bdf587596cfb0edf8a5cd12
│ ├── 1b274070ce90f8ccdf0fc33a4afd4e1455766f8b
│ ├── 1d49f1635e901393bf65a263810508bea7ec9d51
│ ├── 1e2c5c5ac7754f3e3fd858ce644b6621da2f4d03
│ ├── 236cfc19fdc31facdfe306e479a52bb3c08cb540
│ ├── 2478b7ed4fe72f5030a22146ecf365adba0dc780
│ ├── 24b5d7868ba6df6da0e26365e10fc15bcf72cca6
│ ├── 255b827f8c0a593c5ee7610cdbd31c656f166a37
│ ├── 2a8cbfc34aa4aefa008e9e18276e32fa5e8f56d8
│ ├── 2ba0c664eff181eeb2b101f60c5ca66397f4c386
│ ├── 2c34cfd27e783430e24c2af05361af3540b4d6ad
│ ├── 2c4dd5af849b5cda2b7769dc52706e5fa746de73
│ ├── 2cdb9f5adf53f1054ce8e6ceba007396ce6b734b
│ ├── 30140397fe38ee61f01eff44b5cfa48285e47889
│ ├── 321500ed9a1796dca3d559d8f129ed31a8790035
│ ├── 3219e4d65ac8671a452900514bc3c7aea2e71be3
│ ├── 36a5cc93968072de9d120643033589df4f316997
│ ├── 3abe9a29f2b95f34da65d88b969e58f4b46b6309
│ ├── 3e5a9e8b50fcdcbe08f8138de6b95b5cd5b69bf2
│ ├── 3f0062c38d031b015f1a8bb82bd370b65d5ca35a
│ ├── 4670a8e0d21a624c0d42fd6dc76ef408d2b4e195
│ ├── 47393c214b8f5a3d3c098e3985d24bd1e8d82a85
│ ├── 48947b6f943721ce84ef81e887a16bde2759f7ab
│ ├── 49989f6a8875777519c822a92c821cbb95bfc360
│ ├── 4aaffe149efbd0ab6f122a4dc6e9e9aa0a602799
│ ├── 4b65bf83d9b292f65bb5d1b056d68a4811732ef3
│ ├── 4c156cb396c967d81bf3615cbd5ba74221a9c622
│ ├── 4fb8cfeaaac80a1c829b22a43089ef470bcfe5b8
│ ├── 502804b3665c5eb935d6f66e7677f75242f516bb
│ ├── 56ff31c3b76d37929e45071a36ca5aa0bc386e09
│ ├── 5bc56c0f00870625b5016a8d242ebe5c2a58802b
│ ├── 5e8c489081abe671d760e1840b526f43bc7e6aa3
│ ├── 5ec02b6349403b523d33576c7e2de27fb345edf0
│ ├── 6351ed5a9ac9cbb709ad15b4193edb52b8d37e84
│ ├── 673480b070ea0508c3510627c81a4b519fb7d2f5
│ ├── 683f06bff1a62b73193352f06a7194f0bf60ffb8
│ ├── 68a5e75e9b42928454b320fe8f64ea107e61f60f
│ ├── 68be1e92e40e77926e1d9a5c2d800da023f6a4e9
│ ├── 6b7395dabfc4d5a76e276f222c64c4bf7771ffb7
│ ├── 707235f5352edef615d64d00d83fcf92c9dffa57
│ ├── 71819c849b41ee2f4a5b08321b9fc8bf21326ddf
│ ├── 730377e1be92f426661e434d4f1cf20a10e16991
│ ├── 73728d128f628772a64990a72340d9fd7987e29b
│ ├── 73cc8fe38acd489c2b1fed0a66222aac4e04cc98
│ ├── 74fe2a4034b08b5ecb014b2596e7f21ab55ea729
│ ├── 79aed363731b28a60abf16190df3d60fd1d88e54
│ ├── 7a1d04a0253fbb956c8119c40dc917cb460dabb0
│ ├── 7a96d469f87b8c0fa00a944669469db9c8246714
│ ├── 7b21df3bb234142e7b2dfc81f84eb621f9c7a617
│ ├── 7cd196c0e83037dd1c7aa060e3919f530d5eaa13
│ ├── 8611c05469f8e623e1e035e578d1d50ff2a54e11
│ ├── 861648845b817281bffa42d8ca1c46443cef5cd8
│ ├── 86f9eb6ebcae33f4d3663f90adf430f6d7b5e57c
│ ├── 8a90278d26f66fd78e4e38da237c201707bf7ab3
│ ├── 8de4d4284d8227a753986639b1d6e698bc683d8a
│ ├── 8e4cb24fea75d067b0d9a5598fdeb66490777000
│ ├── 900843bfb3730b31165e6d480bb212854380de72
│ ├── 964ac50bf26ecb3d0253e5e288484776bbf0abdf
│ ├── 98d2aa10f9c5e6d9b1a6fb3dcc6583aa5631882a
│ ├── 9ae8dabd9621f44592757414f83d26df04e55bca
│ ├── 9b982d96821f364683a7a9cc2495cccc7d5bb705
│ ├── 9ded617601151e2a3dde370fe42f206f6dd38f42
│ ├── 9e2487eee9a3b9f415c36aed893ed2da3d3bace6
│ ├── 9f733d3115030339e63922d6e35920f9dba1207e
│ ├── a0bb3eef10ad343fdf00adc2c7a2fab0e4dd679f
│ ├── a611449daf97af318de6495f22c907ecb1f83076
│ ├── a8c1d81ff50e57abc043f8bbcc87ce0e123285a7
│ ├── aa1a1bd5b7953186af6c9f2e8f757247fdffa9ce
│ ├── b7471e724dfba20b71265eb8f8315ff5add6ccad
│ ├── b9df95e660f5bc5d66f2ad7c49339cb3d62d2a99
│ ├── bc22b685617fec260cb94cb1ab9822e393924a35
│ ├── c1a1ed4a1a749c9e38da920c66a4c425e169566b
│ ├── c41c1a47577c69284cae60d785ddb240dc3739db
│ ├── c4ee5a4632d4f9a51ba57a70cfa2cae832460857
│ ├── c9388db618e924f41e419ccddc068b443657ffa4
│ ├── ce7c29332788aa93186591aceaad307ffbdf9735
│ ├── da39a3ee5e6b4b0d3255bfef95601890afd80709
│ ├── df0c1e8999119939ea4f07c2daeb57b868bb0719
│ ├── e2d6b6d4d9b8346067d2252bfbcefff99a24ed21
│ ├── e62ebb1ab82b8cf630f2b393d89c367dd0b25924
│ ├── e906f0d49a1b91f0b93d64c36bf5a764924ce45f
│ ├── ead2a4908cb1750ae6f619656ebf74b153edab25
│ ├── eae5f62c3fc844275194f17d530d26ceafcf941b
│ ├── eb9a0e5a353364b221b1e1e3115d34d7948e9ae9
│ ├── edb2dfda8124a5c5935dd1d449f493e868d9f9c0
│ ├── f023f3307ef4fe6b9d8ea2c0ea4fb3bc954f2888
│ ├── f1ec5f959e75412b01270a861f1f1ecdfda1cb9c
│ ├── f4aaa2a22e1038e4abda4636592d330fc9fc693b
│ ├── f7cb64ffc60ab1f9e0aecbd9c560af1d743fe314
│ ├── f86f8b65ecd59bddb8df4850b538b863021ea14a
│ ├── f87f13e299cb66c824237b662a5623647d3af86e
│ ├── fa85f6319c6d39864527629c9b25c4b086f398b7
│ └── fc7077d7ef5f47af404835e9ea6401f258b27f83
├── time/
│ ├── decode.go
│ ├── decode_stream.go
│ ├── decode_stream_test.go
│ ├── decode_test.go
│ ├── encode.go
│ ├── encode_stream.go
│ ├── encode_stream_test.go
│ ├── encode_test.go
│ └── time.go
└── unmarshal_ext_test.go
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/release.yml
================================================
changelog:
exclude:
labels:
- tagpr
================================================
FILE: .github/workflows/stale.yml
================================================
name: Mark stale issues and pull requests
# on:
# schedule:
# - cron: '30 11 * * *'
jobs:
stale:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v3
with:
days-before-issue-stale: 30
days-before-issue-close: 14
stale-issue-label: "stale"
stale-issue-message: "This issue is stale because it has been open for 30 days with no activity."
close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale."
days-before-pr-stale: -1
days-before-pr-close: -1
repo-token: ${{ secrets.GITHUB_TOKEN }}
================================================
FILE: .github/workflows/tagpr.yml
================================================
name: tagpr
on:
push:
branches: ["main"]
jobs:
tagpr:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
issues: read
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- uses: Songmu/tagpr@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
================================================
FILE: .github/workflows/test.yml
================================================
name: test
on: [push, pull_request]
env:
GOPATH: ${{ github.workspace }}
WORKSPACE: ${{ github.workspace }}/src/github.com/${{ github.repository }}
jobs:
test:
defaults:
run:
working-directory: ${{ env.WORKSPACE }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
go: ["1.23", "1.24", "1.25", "1.26"]
name: ${{ matrix.os }} @ Go ${{ matrix.go }}
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
path: ${{ env.WORKSPACE }}
- name: Set up Go ${{ matrix.go }}
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go }}
- name: Cache
uses: actions/cache@v4
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Build
run: go build -v ./...
- name: Test
run: go test -v --coverpkg=github.com/shamaton/msgpack/... --coverprofile=coverage.coverprofile.tmp --covermode=atomic ./...
- name: Remove testutil from coverage
shell: bash
run: |
cat coverage.coverprofile.tmp | grep -v testutil > coverage.coverprofile
rm coverage.coverprofile.tmp
- name: Upload coverage to Codecov
if: success() && matrix.go == '1.25' && matrix.os == 'ubuntu-latest'
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: false
working-directory: ${{ env.WORKSPACE }}
lint:
needs: test
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
path: ${{ env.WORKSPACE }}
- name: golangci-lint
uses: reviewdog/action-golangci-lint@v2
with:
workdir: ${{ env.WORKSPACE }}
level: warning
reporter: github-pr-review
================================================
FILE: .gitignore
================================================
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# coverage
*.coverprofile
.DS_Store
.idea
.vscode
================================================
FILE: .tagpr
================================================
[tagpr]
releaseBranch = main
versionFile = -
vPrefix = true
changelog = true
release = true
fixedMajorVersion = 3
================================================
FILE: CHANGELOG.md
================================================
# Changelog
## [v3.1.1](https://github.com/shamaton/msgpack/compare/v3.1.0...v3.1.1) - 2026-05-12
- chore: isolate formatting cleanup from #60 by @shamaton in https://github.com/shamaton/msgpack/pull/61
- Add tagpr configuration by @shamaton in https://github.com/shamaton/msgpack/pull/63
- fix: validate ext frame bounds before byte-slice decode by @hyp3rd in https://github.com/shamaton/msgpack/pull/60
## [v3.1.0](https://github.com/shamaton/msgpack/commits/v3.1.0) - 2026-02-06
- Add embedded struct support with optimized fast path by @shamaton in https://github.com/shamaton/msgpack/pull/58
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2025 Masayuki Shamoto
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.
================================================
FILE: README.md
================================================
# MessagePack for Golang
[](https://pkg.go.dev/github.com/shamaton/msgpack)

[](https://goreportcard.com/report/github.com/shamaton/msgpack)
[](https://codecov.io/gh/shamaton/msgpack)
[](https://app.fossa.com/projects/git%2Bgithub.com%2Fshamaton%2Fmsgpack?ref=badge_shield)
## 📣 Announcement: `time.Time` decoding defaults to **UTC** in v3
Starting with **v3.0.0**, when decoding MessagePack **Timestamp** into Go’s `time.Time`,
the default `Location` will be **UTC** (previously `Local`). The instant is unchanged.
To keep the old behavior, use `SetDecodedTimeAsLocal()`.
## Features
* Supported types : primitive / array / slice / struct / map / interface{} and time.Time
* Renaming fields via `msgpack:"field_name"`
* Omitting fields via `msgpack:"-"`
* Omitting empty fields via `msgpack:"field_name,omitempty"`
* Supports extend encoder / decoder [(example)](./msgpack_example_test.go)
* Can also Encoding / Decoding struct as array
## Installation
Current version is **msgpack/v3**.
```sh
go get -u github.com/shamaton/msgpack/v3
```
### Upgrading from v2
If you are upgrading from v2, please note the `time.Time` decoding change mentioned in the announcement above.
To keep the v2 behavior, use `msgpack.SetDecodedTimeAsLocal()` after upgrading.
## Quick Start
```go
package main
import (
"github.com/shamaton/msgpack/v3"
"net/http"
)
type Struct struct {
String string
}
// simple
func main() {
v := Struct{String: "msgpack"}
d, err := msgpack.Marshal(v)
if err != nil {
panic(err)
}
r := Struct{}
if err = msgpack.Unmarshal(d, &r); err != nil {
panic(err)
}
}
// streaming
func handle(w http.ResponseWriter, r *http.Request) {
var body Struct
if err := msgpack.UnmarshalRead(r, &body); err != nil {
panic(err)
}
if err := msgpack.MarshalWrite(w, body); err != nil {
panic(err)
}
}
```
## v3: `time.Time` decoding defaults to **UTC**
**TL;DR:** Starting with **v3.0.0**, when decoding MessagePack **Timestamp** into Go’s `time.Time`, the default `Location` will be **UTC** (previously `Local`). The **instant** is unchanged—only the display/location changes. This avoids host-dependent differences and aligns with common distributed systems practice.
### What is changing?
* **Before (v2.x):** Decoded `time.Time` defaults to `Local`.
* **After (v3.0.0):** Decoded `time.Time` defaults to **UTC**.
MessagePack’s Timestamp encodes an **instant** (epoch seconds + nanoseconds) and does **not** carry timezone info. Your data’s point in time is the same; only `time.Time.Location()` differs.
### Why?
* Eliminate environment-dependent behavior, such as different hosts showing different local zones.
* Make “UTC by default” the safe, predictable baseline for logs, APIs, and distributed apps.
### Who is affected?
* Apps that **display local time** without explicitly converting from UTC.
* If your code already normalizes to UTC or explicitly sets a location, you’re likely unaffected.
### Keep the old behavior (Local)
If you want the v2 behavior on v3:
```go
msgpack.SetDecodedTimeAsLocal()
```
Or convert after the fact:
```go
var t time.Time
_ = msgpack.Unmarshal(data, &t)
t = t.In(time.Local)
```
### Preview the new behavior on v2 (optional)
You can opt into UTC today on v2.x:
```go
msgpack.SetDecodedTimeAsUTC()
```
## Benchmark
This result made from [shamaton/msgpack_bench](https://github.com/shamaton/msgpack_bench)

## License
This library is under the MIT License.
================================================
FILE: codecov.yml
================================================
coverage:
status:
project: off
patch: off
================================================
FILE: crash_test.go
================================================
package msgpack_test
import (
"io"
"os"
"path/filepath"
"runtime"
"sync"
"testing"
"github.com/shamaton/msgpack/v3"
)
var crashDir = filepath.Join("testdata", "crashers")
func TestCrashBinary(t *testing.T) {
entries, err := os.ReadDir(crashDir)
if err != nil {
t.Fatalf("os.ReadDir error. err: %+v", err)
}
ch := make(chan string, len(entries))
// worker
wg := sync.WaitGroup{}
for i := 0; i < runtime.NumCPU(); i++ {
wg.Add(1)
go check(t, &wg, ch)
}
for _, entry := range entries {
ch <- filepath.Join(crashDir, entry.Name())
}
close(ch)
wg.Wait()
}
func check(t *testing.T, wg *sync.WaitGroup, ch <-chan string) {
var (
path string
ok bool
data []byte
)
t.Helper()
defer wg.Done()
defer func() {
if e := recover(); e != nil {
t.Logf("panic occurred.\nfile: %s\nlen: %d\nbin: % x\nerr: %+v",
path, len(data), data, e,
)
}
}()
for {
path, ok = <-ch // closeされると ok が false になる
if !ok {
return
}
file, err := os.Open(path)
if err != nil {
t.Logf("%s file open error. err: %+v", path, err)
t.Fail()
return
}
data, err = io.ReadAll(file)
if err != nil {
t.Logf("%s io.ReadAll error. err: %+v", path, err)
t.Fail()
return
}
var r interface{}
err = msgpack.Unmarshal(data, &r)
if err == nil {
t.Logf("err should be occurred.\nname: %s\nlen: %d\nbin: % x",
file.Name(), len(data), data,
)
t.Fail()
return
}
path = ""
data = nil
}
}
================================================
FILE: decode.go
================================================
package msgpack
import (
"io"
"github.com/shamaton/msgpack/v3/internal/decoding"
streamdecoding "github.com/shamaton/msgpack/v3/internal/stream/decoding"
)
// UnmarshalAsMap decodes data that is encoded as map format.
// This is the same thing that StructAsArray sets false.
func UnmarshalAsMap(data []byte, v interface{}) error {
return decoding.Decode(data, v, false)
}
// UnmarshalAsArray decodes data that is encoded as array format.
// This is the same thing that StructAsArray sets true.
func UnmarshalAsArray(data []byte, v interface{}) error {
return decoding.Decode(data, v, true)
}
// UnmarshalReadAsMap decodes from stream. stream data expects map format.
// This is the same thing that StructAsArray sets false.
func UnmarshalReadAsMap(r io.Reader, v interface{}) error {
return streamdecoding.Decode(r, v, false)
}
// UnmarshalReadAsArray decodes from stream. stream data expects array format.
// This is the same thing that StructAsArray sets true.
func UnmarshalReadAsArray(r io.Reader, v interface{}) error {
return streamdecoding.Decode(r, v, true)
}
================================================
FILE: def/def.go
================================================
package def
// IntSize : 32 or 64
const IntSize = 32 << (^uint(0) >> 63)
var IsIntSize32 = IntSize == 32
// message pack format
const (
PositiveFixIntMin = 0x00
PositiveFixIntMax = 0x7f
FixMap = 0x80
FixArray = 0x90
FixStr = 0xa0
Nil = 0xc0
False = 0xc2
True = 0xc3
Bin8 = 0xc4
Bin16 = 0xc5
Bin32 = 0xc6
Ext8 = 0xc7
Ext16 = 0xc8
Ext32 = 0xc9
Float32 = 0xca
Float64 = 0xcb
Uint8 = 0xcc
Uint16 = 0xcd
Uint32 = 0xce
Uint64 = 0xcf
Int8 = 0xd0
Int16 = 0xd1
Int32 = 0xd2
Int64 = 0xd3
Fixext1 = 0xd4
Fixext2 = 0xd5
Fixext4 = 0xd6
Fixext8 = 0xd7
Fixext16 = 0xd8
Str8 = 0xd9
Str16 = 0xda
Str32 = 0xdb
Array16 = 0xdc
Array32 = 0xdd
Map16 = 0xde
Map32 = 0xdf
NegativeFixintMin = -32 // 0xe0
NegativeFixintMax = -1 // 0xff
)
// byte
const (
Byte1 = 1 << iota
Byte2
Byte4
Byte8
Byte16
Byte32
)
// ext type
const (
TimeStamp = -1
)
// ext type complex
var complexTypeCode = int8(-128)
// ComplexTypeCode gets complexTypeCode
func ComplexTypeCode() int8 { return complexTypeCode }
// SetComplexTypeCode sets complexTypeCode
func SetComplexTypeCode(code int8) {
complexTypeCode = code
}
================================================
FILE: def/error.go
================================================
package def
import (
"errors"
"fmt"
)
var (
// base errors
ErrMsgpack = errors.New("")
// decoding errors
ErrNoData = fmt.Errorf("%wno data", ErrMsgpack)
ErrHasLeftOver = fmt.Errorf("%wdata has left over", ErrMsgpack)
ErrReceiverNotPointer = fmt.Errorf("%wreceiver not pointer", ErrMsgpack)
ErrNotMatchArrayElement = fmt.Errorf("%wnot match array element", ErrMsgpack)
ErrCanNotDecode = fmt.Errorf("%winvalid code", ErrMsgpack)
ErrCanNotSetSliceAsMapKey = fmt.Errorf("%wcan not set slice as map key", ErrMsgpack)
ErrCanNotSetMapAsMapKey = fmt.Errorf("%wcan not set map as map key", ErrMsgpack)
// encoding errors
ErrTooShortBytes = fmt.Errorf("%wtoo short bytes", ErrMsgpack)
ErrLackDataLengthToSlice = fmt.Errorf("%wdata length lacks to create slice", ErrMsgpack)
ErrLackDataLengthToMap = fmt.Errorf("%wdata length lacks to create map", ErrMsgpack)
ErrUnsupportedType = fmt.Errorf("%wunsupported type", ErrMsgpack)
ErrUnsupportedLength = fmt.Errorf("%wunsupported length", ErrMsgpack)
ErrNotMatchLastIndex = fmt.Errorf("%wnot match last index", ErrMsgpack)
)
================================================
FILE: encode.go
================================================
package msgpack
import (
"io"
"github.com/shamaton/msgpack/v3/internal/encoding"
streamencoding "github.com/shamaton/msgpack/v3/internal/stream/encoding"
)
// MarshalAsMap encodes data as map format.
// This is the same thing that StructAsArray sets false.
func MarshalAsMap(v interface{}) ([]byte, error) {
return encoding.Encode(v, false)
}
// MarshalAsArray encodes data as array format.
// This is the same thing that StructAsArray sets true.
func MarshalAsArray(v interface{}) ([]byte, error) {
return encoding.Encode(v, true)
}
// MarshalWriteAsMap writes map format encoded data to writer.
// This is the same thing that StructAsArray sets false.
func MarshalWriteAsMap(w io.Writer, v interface{}) error {
return streamencoding.Encode(w, v, false)
}
// MarshalWriteAsArray writes array format encoded data to writer.
// This is the same thing that StructAsArray sets true.
func MarshalWriteAsArray(w io.Writer, v interface{}) error {
return streamencoding.Encode(w, v, true)
}
================================================
FILE: errors.go
================================================
package msgpack
import (
"github.com/shamaton/msgpack/v3/def"
)
// Error is used in all msgpack error as the based error.
var Error = def.ErrMsgpack
================================================
FILE: ext/decode.go
================================================
package ext
import (
"reflect"
"github.com/shamaton/msgpack/v3/def"
)
// Decoder defines an interface for decoding values from bytes.
// It provides methods to get the decoder type, check if the data matches the type,
// and convert the data into a Go value.
type Decoder interface {
// Code returns the unique code representing the decoder type.
Code() int8
// IsType checks if the data at the given offset matches the expected type.
// Returns true if the type matches, false otherwise.
IsType(offset int, d *[]byte) bool
// AsValue decodes the data at the given offset into a Go value of the specified kind.
// Returns the decoded value, the new offset, and an error if decoding fails.
AsValue(offset int, k reflect.Kind, d *[]byte) (interface{}, int, error)
}
// DecoderCommon provides common utility methods for decoding data from bytes.
type DecoderCommon struct{}
// ReadSize1 reads a single byte from the given index in the byte slice.
// Returns the byte and the new index after reading.
func (cd *DecoderCommon) ReadSize1(index int, d *[]byte) (byte, int) {
rb := def.Byte1
return (*d)[index], index + rb
}
// ReadSize2 reads two bytes from the given index in the byte slice.
// Returns the bytes as a slice and the new index after reading.
func (cd *DecoderCommon) ReadSize2(index int, d *[]byte) ([]byte, int) {
rb := def.Byte2
return (*d)[index : index+rb], index + rb
}
// ReadSize4 reads four bytes from the given index in the byte slice.
// Returns the bytes as a slice and the new index after reading.
func (cd *DecoderCommon) ReadSize4(index int, d *[]byte) ([]byte, int) {
rb := def.Byte4
return (*d)[index : index+rb], index + rb
}
// ReadSize8 reads eight bytes from the given index in the byte slice.
// Returns the bytes as a slice and the new index after reading.
func (cd *DecoderCommon) ReadSize8(index int, d *[]byte) ([]byte, int) {
rb := def.Byte8
return (*d)[index : index+rb], index + rb
}
// ReadSizeN reads a specified number of bytes (n) from the given index in the byte slice.
// Returns the bytes as a slice and the new index after reading.
func (cd *DecoderCommon) ReadSizeN(index, n int, d *[]byte) ([]byte, int) {
return (*d)[index : index+n], index + n
}
================================================
FILE: ext/decoder_stream.go
================================================
package ext
import (
"reflect"
)
// StreamDecoder defines an interface for decoding streams of data.
// It provides methods to retrieve the decoder's code, check type compatibility,
// and convert raw data into a Go value of a specified kind.
type StreamDecoder interface {
// Code returns the unique identifier for the decoder.
Code() int8
// IsType checks if the provided code, inner type, and data length match the expected type.
// Returns true if the type matches, otherwise false.
IsType(code byte, innerType int8, dataLength int) bool
// ToValue converts the raw data into a Go value of the specified kind.
// Takes the code, raw data, and the target kind as input.
// Returns the decoded value or an error if the conversion fails.
ToValue(code byte, data []byte, k reflect.Kind) (any, error)
}
================================================
FILE: ext/encode.go
================================================
package ext
import (
"reflect"
)
// Encoder defines an interface for encoding values into bytes.
// It provides methods to get the encoding type, calculate the byte size of a value,
// and write the encoded value into a byte slice.
type Encoder interface {
// Code returns the unique code representing the encoder type.
Code() int8
// Type returns the reflect.Type of the value that the encoder handles.
Type() reflect.Type
// CalcByteSize calculates the number of bytes required to encode the given value.
// Returns the size and an error if the calculation fails.
CalcByteSize(value reflect.Value) (int, error)
// WriteToBytes encodes the given value into a byte slice starting at the specified offset.
// Returns the new offset after writing the bytes.
WriteToBytes(value reflect.Value, offset int, bytes *[]byte) int
}
// EncoderCommon provides utility methods for encoding various types of values into bytes.
// It includes methods to encode integers and unsigned integers of different sizes,
// as well as methods to write raw byte slices into a target byte slice.
type EncoderCommon struct{}
// SetByte1Int64 encodes a single byte from the given int64 value into the byte slice at the specified offset.
// Returns the new offset after writing the byte.
func (c *EncoderCommon) SetByte1Int64(value int64, offset int, d *[]byte) int {
(*d)[offset] = byte(value)
return offset + 1
}
// SetByte2Int64 encodes the lower two bytes of the given int64 value into the byte slice at the specified offset.
// Returns the new offset after writing the bytes.
func (c *EncoderCommon) SetByte2Int64(value int64, offset int, d *[]byte) int {
(*d)[offset+0] = byte(value >> 8)
(*d)[offset+1] = byte(value)
return offset + 2
}
// SetByte4Int64 encodes the lower four bytes of the given int64 value into the byte slice at the specified offset.
// Returns the new offset after writing the bytes.
func (c *EncoderCommon) SetByte4Int64(value int64, offset int, d *[]byte) int {
(*d)[offset+0] = byte(value >> 24)
(*d)[offset+1] = byte(value >> 16)
(*d)[offset+2] = byte(value >> 8)
(*d)[offset+3] = byte(value)
return offset + 4
}
// SetByte8Int64 encodes all eight bytes of the given int64 value into the byte slice at the specified offset.
// Returns the new offset after writing the bytes.
func (c *EncoderCommon) SetByte8Int64(value int64, offset int, d *[]byte) int {
(*d)[offset] = byte(value >> 56)
(*d)[offset+1] = byte(value >> 48)
(*d)[offset+2] = byte(value >> 40)
(*d)[offset+3] = byte(value >> 32)
(*d)[offset+4] = byte(value >> 24)
(*d)[offset+5] = byte(value >> 16)
(*d)[offset+6] = byte(value >> 8)
(*d)[offset+7] = byte(value)
return offset + 8
}
// SetByte1Uint64 encodes a single byte from the given uint64 value into the byte slice at the specified offset.
// Returns the new offset after writing the byte.
func (c *EncoderCommon) SetByte1Uint64(value uint64, offset int, d *[]byte) int {
(*d)[offset] = byte(value)
return offset + 1
}
// SetByte2Uint64 encodes the lower two bytes of the given uint64 value into the byte slice at the specified offset.
// Returns the new offset after writing the bytes.
func (c *EncoderCommon) SetByte2Uint64(value uint64, offset int, d *[]byte) int {
(*d)[offset] = byte(value >> 8)
(*d)[offset+1] = byte(value)
return offset + 2
}
// SetByte4Uint64 encodes the lower four bytes of the given uint64 value into the byte slice at the specified offset.
// Returns the new offset after writing the bytes.
func (c *EncoderCommon) SetByte4Uint64(value uint64, offset int, d *[]byte) int {
(*d)[offset] = byte(value >> 24)
(*d)[offset+1] = byte(value >> 16)
(*d)[offset+2] = byte(value >> 8)
(*d)[offset+3] = byte(value)
return offset + 4
}
// SetByte8Uint64 encodes all eight bytes of the given uint64 value into the byte slice at the specified offset.
// Returns the new offset after writing the bytes.
func (c *EncoderCommon) SetByte8Uint64(value uint64, offset int, d *[]byte) int {
(*d)[offset] = byte(value >> 56)
(*d)[offset+1] = byte(value >> 48)
(*d)[offset+2] = byte(value >> 40)
(*d)[offset+3] = byte(value >> 32)
(*d)[offset+4] = byte(value >> 24)
(*d)[offset+5] = byte(value >> 16)
(*d)[offset+6] = byte(value >> 8)
(*d)[offset+7] = byte(value)
return offset + 8
}
// SetByte1Int encodes a single byte from the given int value into the byte slice at the specified offset.
// Returns the new offset after writing the byte.
func (c *EncoderCommon) SetByte1Int(code, offset int, d *[]byte) int {
(*d)[offset] = byte(code)
return offset + 1
}
// SetByte2Int encodes the lower two bytes of the given int value into the byte slice at the specified offset.
// Returns the new offset after writing the bytes.
func (c *EncoderCommon) SetByte2Int(value int, offset int, d *[]byte) int {
(*d)[offset] = byte(value >> 8)
(*d)[offset+1] = byte(value)
return offset + 2
}
// SetByte4Int encodes the lower four bytes of the given int value into the byte slice at the specified offset.
// Returns the new offset after writing the bytes.
func (c *EncoderCommon) SetByte4Int(value int, offset int, d *[]byte) int {
(*d)[offset] = byte(value >> 24)
(*d)[offset+1] = byte(value >> 16)
(*d)[offset+2] = byte(value >> 8)
(*d)[offset+3] = byte(value)
return offset + 4
}
// SetByte4Uint32 encodes the lower four bytes of the given uint32 value into the byte slice at the specified offset.
// Returns the new offset after writing the bytes.
func (c *EncoderCommon) SetByte4Uint32(value uint32, offset int, d *[]byte) int {
(*d)[offset] = byte(value >> 24)
(*d)[offset+1] = byte(value >> 16)
(*d)[offset+2] = byte(value >> 8)
(*d)[offset+3] = byte(value)
return offset + 4
}
// SetBytes writes the given byte slice `bs` into the target byte slice at the specified offset.
// Returns the new offset after writing the bytes.
func (c *EncoderCommon) SetBytes(bs []byte, offset int, d *[]byte) int {
for i := range bs {
(*d)[offset+i] = bs[i]
}
return offset + len(bs)
}
================================================
FILE: ext/encode_stream.go
================================================
package ext
import (
"io"
"reflect"
"github.com/shamaton/msgpack/v3/internal/common"
)
// StreamEncoder is an interface that extended encoders should implement.
// It defines methods for encoding data into a stream.
type StreamEncoder interface {
// Code returns the unique code for the encoder.
Code() int8
// Type returns the reflect.Type of the value being encoded.
Type() reflect.Type
// Write encodes the given value and writes it to the provided StreamWriter.
Write(w StreamWriter, value reflect.Value) error
}
// StreamWriter provides methods for writing data in extended formats.
// It wraps an io.Writer and a buffer for efficient writing.
type StreamWriter struct {
w io.Writer // The underlying writer to write data to.
buf *common.Buffer // A buffer used for temporary storage during writing.
}
// CreateStreamWriter creates and returns a new StreamWriter instance.
func CreateStreamWriter(w io.Writer, buf *common.Buffer) StreamWriter {
return StreamWriter{w, buf}
}
// WriteByte1Int64 writes a single byte representation of an int64 value.
func (w *StreamWriter) WriteByte1Int64(value int64) error {
return w.buf.Write(w.w,
byte(value),
)
}
// WriteByte2Int64 writes a two-byte representation of an int64 value.
func (w *StreamWriter) WriteByte2Int64(value int64) error {
return w.buf.Write(w.w,
byte(value>>8),
byte(value),
)
}
// WriteByte4Int64 writes a four-byte representation of an int64 value.
func (w *StreamWriter) WriteByte4Int64(value int64) error {
return w.buf.Write(w.w,
byte(value>>24),
byte(value>>16),
byte(value>>8),
byte(value),
)
}
// WriteByte8Int64 writes an eight-byte representation of an int64 value.
func (w *StreamWriter) WriteByte8Int64(value int64) error {
return w.buf.Write(w.w,
byte(value>>56),
byte(value>>48),
byte(value>>40),
byte(value>>32),
byte(value>>24),
byte(value>>16),
byte(value>>8),
byte(value),
)
}
// WriteByte1Uint64 writes a single byte representation of a uint64 value.
func (w *StreamWriter) WriteByte1Uint64(value uint64) error {
return w.buf.Write(w.w,
byte(value),
)
}
// WriteByte2Uint64 writes a two-byte representation of a uint64 value.
func (w *StreamWriter) WriteByte2Uint64(value uint64) error {
return w.buf.Write(w.w,
byte(value>>8),
byte(value),
)
}
// WriteByte4Uint64 writes a four-byte representation of a uint64 value.
func (w *StreamWriter) WriteByte4Uint64(value uint64) error {
return w.buf.Write(w.w,
byte(value>>24),
byte(value>>16),
byte(value>>8),
byte(value),
)
}
// WriteByte8Uint64 writes an eight-byte representation of a uint64 value.
func (w *StreamWriter) WriteByte8Uint64(value uint64) error {
return w.buf.Write(w.w,
byte(value>>56),
byte(value>>48),
byte(value>>40),
byte(value>>32),
byte(value>>24),
byte(value>>16),
byte(value>>8),
byte(value),
)
}
// WriteByte1Int writes a single byte representation of an int value.
func (w *StreamWriter) WriteByte1Int(value int) error {
return w.buf.Write(w.w,
byte(value),
)
}
// WriteByte2Int writes a two-byte representation of an int value.
func (w *StreamWriter) WriteByte2Int(value int) error {
return w.buf.Write(w.w,
byte(value>>8),
byte(value),
)
}
// WriteByte4Int writes a four-byte representation of an int value.
func (w *StreamWriter) WriteByte4Int(value int) error {
return w.buf.Write(w.w,
byte(value>>24),
byte(value>>16),
byte(value>>8),
byte(value),
)
}
// WriteByte4Uint32 writes a four-byte representation of a uint32 value.
func (w *StreamWriter) WriteByte4Uint32(value uint32) error {
return w.buf.Write(w.w,
byte(value>>24),
byte(value>>16),
byte(value>>8),
byte(value),
)
}
// WriteBytes writes a slice of bytes to the underlying writer.
func (w *StreamWriter) WriteBytes(bs []byte) error {
return w.buf.Write(w.w, bs...)
}
================================================
FILE: go.mod
================================================
module github.com/shamaton/msgpack/v3
go 1.23
================================================
FILE: internal/common/buffer.go
================================================
package common
import (
"io"
"sync"
)
type Buffer struct {
Data []byte
B1 []byte
B2 []byte
B4 []byte
B8 []byte
B16 []byte
offset int
}
func (b *Buffer) Write(w io.Writer, vs ...byte) error {
if len(b.Data) < b.offset+len(vs) {
_, err := w.Write(b.Data[:b.offset])
b.offset = 0
if err != nil {
return err
}
if len(b.Data) < len(vs) {
b.Data = append(b.Data, make([]byte, len(vs)-len(b.Data))...)
}
}
for i := range vs {
b.Data[b.offset+i] = vs[i]
}
b.offset += len(vs)
return nil
}
func (b *Buffer) Flush(w io.Writer) error {
_, err := w.Write(b.Data[:b.offset])
return err
}
var bufPool = sync.Pool{
New: func() interface{} {
data := make([]byte, 64)
return &Buffer{
Data: data,
B1: data[:1],
B2: data[:2],
B4: data[:4],
B8: data[:8],
B16: data[:16],
}
},
}
func GetBuffer() *Buffer {
buf := bufPool.Get().(*Buffer)
buf.offset = 0
return buf
}
func PutBuffer(buf *Buffer) {
bufPool.Put(buf)
}
================================================
FILE: internal/common/common.go
================================================
package common
import (
"reflect"
"strings"
)
// Common is used encoding/decoding
type Common struct{}
// FieldInfo holds information about a struct field including its path for embedded structs
type FieldInfo struct {
Path []int // path to reach this field (indices for embedded structs)
Name string // field name or tag
Omit bool // omitempty flag
Tagged bool // tag name explicitly set
OmitPaths [][]int // paths to embedded fields with omitempty
}
// CollectFields collects all fields from a struct, expanding embedded structs
// following the same rules as encoding/json
func (c *Common) CollectFields(t reflect.Type, path []int) []FieldInfo {
return c.collectFields(t, path, nil)
}
func (c *Common) collectFields(t reflect.Type, path []int, omitPaths [][]int) []FieldInfo {
var fields []FieldInfo
var embedded []FieldInfo // embedded fields to process later (lower priority)
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
// Check field visibility and get omitempty flag
public, omit, name := c.CheckField(field)
if !public {
continue
}
// Get tag to check if embedded
tag := field.Tag.Get("msgpack")
// Extract just the name part (before comma if any)
tagName := tag
for j, ch := range tag {
if ch == ',' {
tagName = tag[:j]
break
}
}
// Check if this is an embedded struct
isEmbedded := field.Anonymous && (tag == "" || tagName == "")
tagged := tagName != ""
if isEmbedded {
// Get the actual type (dereference pointer if needed)
fieldType := field.Type
if fieldType.Kind() == reflect.Ptr {
fieldType = fieldType.Elem()
}
// If it's a struct, expand its fields
if fieldType.Kind() == reflect.Struct {
newPath := append(append([]int{}, path...), i)
nextOmitPaths := omitPaths
if omit {
nextOmitPaths = appendOmitPath(omitPaths, newPath)
}
embeddedFields := c.collectFields(fieldType, newPath, nextOmitPaths)
embedded = append(embedded, embeddedFields...)
continue
}
}
// Regular field or embedded non-struct
newPath := append(append([]int{}, path...), i)
fields = append(fields, FieldInfo{
Path: newPath,
Name: name,
Omit: omit,
Tagged: tagged,
OmitPaths: omitPaths,
})
}
// Add embedded fields after regular fields (they have lower priority)
fields = append(fields, embedded...)
// Remove duplicates and handle ambiguous fields
return c.deduplicateFields(fields)
}
func appendOmitPath(paths [][]int, path []int) [][]int {
if len(paths) == 0 {
return [][]int{path}
}
newPaths := make([][]int, len(paths)+1)
copy(newPaths, paths)
newPaths[len(paths)] = path
return newPaths
}
// deduplicateFields removes duplicate fields and handles ambiguous fields
// following encoding/json behavior
func (c *Common) deduplicateFields(fields []FieldInfo) []FieldInfo {
// Group fields by name and depth, preserving order
type fieldAtDepth struct {
field FieldInfo
depth int
}
fieldsByName := make(map[string][]fieldAtDepth)
var seenNames []string // To preserve order
for _, f := range fields {
if _, seen := fieldsByName[f.Name]; !seen {
seenNames = append(seenNames, f.Name)
}
fieldsByName[f.Name] = append(fieldsByName[f.Name], fieldAtDepth{
field: f,
depth: len(f.Path),
})
}
var result []FieldInfo
for _, name := range seenNames {
fieldsWithDepth := fieldsByName[name]
// Find minimum depth
minDepth := fieldsWithDepth[0].depth
for _, fd := range fieldsWithDepth {
if fd.depth < minDepth {
minDepth = fd.depth
}
}
// Count fields at minimum depth
var fieldsAtMinDepth []FieldInfo
for _, fd := range fieldsWithDepth {
if fd.depth == minDepth {
fieldsAtMinDepth = append(fieldsAtMinDepth, fd.field)
}
}
// If there's exactly one field at minimum depth, use it
if len(fieldsAtMinDepth) == 1 {
result = append(result, fieldsAtMinDepth[0])
continue
}
// Prefer the tagged field if exactly one is tagged at minimum depth
var taggedFields []FieldInfo
for _, f := range fieldsAtMinDepth {
if f.Tagged {
taggedFields = append(taggedFields, f)
}
}
if len(taggedFields) == 1 {
result = append(result, taggedFields[0])
}
// else: ambiguous field, skip it (following encoding/json behavior)
}
return result
}
// CheckField returns flag whether should encode/decode or not and field name
func (c *Common) CheckField(field reflect.StructField) (public, omit bool, name string) {
// A to Z
if !c.isPublic(field.Name) {
return false, false, ""
}
tag := field.Tag.Get("msgpack")
if tag == "" {
return true, false, field.Name
}
parts := strings.Split(tag, ",")
// check ignore
if parts[0] == "-" {
return false, false, ""
}
// check omitempty
for _, part := range parts[1:] {
if part == "omitempty" {
omit = true
}
}
// check name
name = field.Name
if parts[0] != "" {
name = parts[0]
}
return true, omit, name
}
func (c *Common) isPublic(name string) bool {
return 0x41 <= name[0] && name[0] <= 0x5a
}
================================================
FILE: internal/common/common_test.go
================================================
package common
import (
"reflect"
"testing"
tu "github.com/shamaton/msgpack/v3/internal/common/testutil"
)
func TestCommon_CheckField(t *testing.T) {
common := Common{}
t.Run("tag:-", func(t *testing.T) {
field := reflect.StructField{
Name: "A",
Tag: `msgpack:"-"`,
}
public, omit, v := common.CheckField(field)
tu.Equal(t, public, false)
tu.Equal(t, omit, false)
tu.Equal(t, v, "")
})
t.Run("tag:,omitempty", func(t *testing.T) {
field := reflect.StructField{
Name: "A",
Tag: `msgpack:",omitempty"`,
}
public, omit, v := common.CheckField(field)
tu.Equal(t, public, true)
tu.Equal(t, omit, true)
tu.Equal(t, v, "A")
})
t.Run("tag:-,omitempty", func(t *testing.T) {
field := reflect.StructField{
Name: "A",
Tag: `msgpack:"-,omitempty"`,
}
public, omit, v := common.CheckField(field)
tu.Equal(t, public, false)
tu.Equal(t, omit, false)
tu.Equal(t, v, "")
})
t.Run("tag:B", func(t *testing.T) {
field := reflect.StructField{
Name: "A",
Tag: `msgpack:"B"`,
}
public, omit, v := common.CheckField(field)
tu.Equal(t, public, true)
tu.Equal(t, omit, false)
tu.Equal(t, v, "B")
})
t.Run("tag:B,omitempty", func(t *testing.T) {
field := reflect.StructField{
Name: "A",
Tag: `msgpack:"B,omitempty"`,
}
public, omit, v := common.CheckField(field)
tu.Equal(t, public, true)
tu.Equal(t, omit, true)
tu.Equal(t, v, "B")
})
t.Run("name:A", func(t *testing.T) {
field := reflect.StructField{
Name: "A",
Tag: `msgpack:""`,
}
public, omit, v := common.CheckField(field)
tu.Equal(t, public, true)
tu.Equal(t, omit, false)
tu.Equal(t, v, "A")
})
t.Run("private", func(t *testing.T) {
field := reflect.StructField{
Name: "a",
}
public, omit, v := common.CheckField(field)
tu.Equal(t, public, false)
tu.Equal(t, omit, false)
tu.Equal(t, v, "")
})
}
================================================
FILE: internal/common/testutil/reader.go
================================================
package testutil
import (
"errors"
"io"
)
var ErrReaderErr = errors.New("reader error")
type ErrReader struct{}
func NewErrReader() *ErrReader {
return &ErrReader{}
}
func (ErrReader) Read(_ []byte) (int, error) {
return 0, ErrReaderErr
}
type TestReader struct {
s []byte
i int64 // current reading index
count int
}
func NewTestReader(b []byte) *TestReader {
return &TestReader{s: b, i: 0, count: 0}
}
func (r *TestReader) Read(b []byte) (n int, err error) {
if r.i >= int64(len(r.s)) {
return 0, io.EOF
}
n = copy(b, r.s[r.i:])
r.i += int64(n)
r.count++
return
}
func (r *TestReader) Count() int {
return r.count
}
================================================
FILE: internal/common/testutil/struct.go
================================================
package testutil
import (
"math"
"reflect"
"strconv"
"github.com/shamaton/msgpack/v3/def"
)
// CreateStruct returns a struct that is made dynamically and encoded bytes.
func CreateStruct(fieldNum int) (v any, asMapBytes []byte, asArrayBytes []byte) {
if fieldNum < 0 {
panic("negative field number")
}
fields := make([]reflect.StructField, 0, fieldNum)
asMapBytes = make([]byte, 0, fieldNum*2)
asArrayBytes = make([]byte, 0, fieldNum)
for i := 0; i < fieldNum; i++ {
// create struct field
name := "A" + strconv.Itoa(i)
typ := reflect.TypeOf(1)
field := reflect.StructField{
Name: name,
Type: typ,
Tag: `json:"B"`,
}
fields = append(fields, field)
// set encoded bytes
if len(name) < 32 {
asMapBytes = append(asMapBytes, def.FixStr+byte(len(name)))
} else if len(name) < math.MaxUint8 {
asMapBytes = append(asMapBytes, def.Str8)
asMapBytes = append(asMapBytes, byte(len(name)))
}
for _, c := range name {
asMapBytes = append(asMapBytes, byte(c))
}
value := byte(i % 0x7f)
asMapBytes = append(asMapBytes, value)
asArrayBytes = append(asArrayBytes, value)
}
t := reflect.StructOf(fields)
// set field values
v = reflect.New(t).Interface()
rv := reflect.ValueOf(v)
for i := 0; i < rv.Elem().NumField(); i++ {
field := rv.Elem().Field(i)
field.SetInt(int64(i % 0x7f))
}
return v, asMapBytes, asArrayBytes
}
================================================
FILE: internal/common/testutil/testutil.go
================================================
package testutil
import (
"errors"
"reflect"
"strings"
"testing"
)
func NoError(t *testing.T, err error) {
t.Helper()
if err != nil {
t.Fatalf("error is not nil: %v", err)
}
}
func Error(t *testing.T, err error) {
t.Helper()
if err == nil {
t.Fatal(err)
}
}
func IsError(t *testing.T, actual, expected error) {
t.Helper()
if !errors.Is(actual, expected) {
t.Fatalf("not equal. actual: %v, expected: %v", actual, expected)
}
}
func ErrorContains(t *testing.T, err error, errStr string) {
t.Helper()
if err == nil {
t.Fatal("error should occur")
}
if !strings.Contains(err.Error(), errStr) {
t.Fatalf("error does not contain '%s'. err: %v", errStr, err)
}
}
func Equal[T any](t *testing.T, actual, expected T) {
t.Helper()
if !reflect.DeepEqual(actual, expected) {
t.Fatalf("not equal. actual: %v, expected: %v", actual, expected)
}
}
func EqualSlice[T comparable](t *testing.T, actual, expected []T) {
t.Helper()
if len(actual) != len(expected) {
switch a := any(actual).(type) {
case []byte:
e := any(expected).([]byte)
t.Fatalf("diffrent length. actual: [% 02x], expected: [% 02x]", a, e)
default:
t.Fatalf("diffrent length. actual: %v, expected: %v", actual, expected)
}
}
for i := range actual {
if !reflect.DeepEqual(actual[i], expected[i]) {
switch a := any(actual).(type) {
case []byte:
e := any(expected).([]byte)
t.Fatalf("not equal. actual: [% 02x], expected: [% 02x]", a, e)
default:
t.Fatalf("not equal. actual: %v, expected: %v", actual, expected)
}
}
}
}
func EqualMap[K comparable, V comparable](t *testing.T, actual, expected map[K]V) {
t.Helper()
if len(actual) != len(expected) {
t.Fatalf("diffrent length. actual: %v, expected: %v", actual, expected)
}
for k, v1 := range actual {
if v2, ok := expected[k]; !ok || v1 != v2 {
t.Fatalf("not equal. actual: %v, expected: %v", actual, expected)
}
}
}
type Equaler[T any] interface {
Equal(other T) bool
}
func EqualEqualer[T Equaler[T]](t *testing.T, actual, expected T) {
t.Helper()
if !actual.Equal(expected) {
t.Fatalf("not equal. actual: %v, expected: %v", actual, expected)
}
}
================================================
FILE: internal/decoding/bin.go
================================================
package decoding
import (
"encoding/binary"
"reflect"
"unsafe"
"github.com/shamaton/msgpack/v3/def"
)
func (d *decoder) isCodeBin(v byte) bool {
switch v {
case def.Bin8, def.Bin16, def.Bin32:
return true
}
return false
}
func (d *decoder) asBin(offset int, k reflect.Kind) ([]byte, int, error) {
code, offset, err := d.readSize1(offset)
if err != nil {
return emptyBytes, 0, err
}
switch code {
case def.Bin8:
l, offset, err := d.readSize1(offset)
if err != nil {
return emptyBytes, 0, err
}
v, offset, err := d.readSizeN(offset, int(uint8(l)))
if err != nil {
return emptyBytes, 0, err
}
return v, offset, nil
case def.Bin16:
bs, offset, err := d.readSize2(offset)
if err != nil {
return emptyBytes, 0, err
}
v, offset, err := d.readSizeN(offset, int(binary.BigEndian.Uint16(bs)))
if err != nil {
return emptyBytes, 0, err
}
return v, offset, nil
case def.Bin32:
bs, offset, err := d.readSize4(offset)
if err != nil {
return emptyBytes, 0, err
}
v, offset, err := d.readSizeN(offset, int(binary.BigEndian.Uint32(bs)))
if err != nil {
return emptyBytes, 0, err
}
return v, offset, nil
}
return emptyBytes, 0, d.errorTemplate(code, k)
}
func (d *decoder) asBinString(offset int, k reflect.Kind) (string, int, error) {
bs, offset, err := d.asBin(offset, k)
return *(*string)(unsafe.Pointer(&bs)), offset, err
}
================================================
FILE: internal/decoding/bin_test.go
================================================
package decoding
import (
"reflect"
"testing"
"github.com/shamaton/msgpack/v3/def"
tu "github.com/shamaton/msgpack/v3/internal/common/testutil"
)
func Test_isCodeBin(t *testing.T) {
d := decoder{}
for i := 0x00; i <= 0xff; i++ {
v := byte(i)
isBin := v == def.Bin8 || v == def.Bin16 || v == def.Bin32
tu.Equal(t, d.isCodeBin(v), isBin)
}
}
func Test_asBin(t *testing.T) {
method := func(d *decoder) func(int, reflect.Kind) ([]byte, int, error) {
return d.asBin
}
testcases := AsXXXTestCases[[]byte]{
{
Name: "error.code",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Bin8.error.size",
Data: []byte{def.Bin8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Bin8.error.data",
Data: []byte{def.Bin8, 1},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Bin8.ok",
Data: []byte{def.Bin8, 1, 'a'},
Expected: []byte{'a'},
MethodAs: method,
},
{
Name: "Bin16.error.size",
Data: []byte{def.Bin16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Bin16.error.data",
Data: []byte{def.Bin16, 0, 1},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Bin16.ok",
Data: []byte{def.Bin16, 0, 1, 'b'},
Expected: []byte{'b'},
MethodAs: method,
},
{
Name: "Bin32.error.size",
Data: []byte{def.Bin32},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Bin32.error.data",
Data: []byte{def.Bin32, 0, 0, 0, 1},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Bin32.ok",
Data: []byte{def.Bin32, 0, 0, 0, 1, 'c'},
Expected: []byte{'c'},
MethodAs: method,
},
{
Name: "Unexpected",
Data: []byte{def.Nil},
Error: def.ErrCanNotDecode,
MethodAs: method,
},
}
testcases.Run(t)
}
================================================
FILE: internal/decoding/bool.go
================================================
package decoding
import (
"reflect"
"github.com/shamaton/msgpack/v3/def"
)
func (d *decoder) asBool(offset int, k reflect.Kind) (bool, int, error) {
code, offset, err := d.readSize1(offset)
if err != nil {
return false, 0, err
}
switch code {
case def.True:
return true, offset, nil
case def.False:
return false, offset, nil
}
return false, 0, d.errorTemplate(code, k)
}
================================================
FILE: internal/decoding/bool_test.go
================================================
package decoding
import (
"reflect"
"testing"
"github.com/shamaton/msgpack/v3/def"
)
func Test_asBool(t *testing.T) {
method := func(d *decoder) func(int, reflect.Kind) (bool, int, error) {
return d.asBool
}
testcases := AsXXXTestCases[bool]{
{
Name: "error.code",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Bool.false",
Data: []byte{def.False},
Expected: false,
MethodAs: method,
},
{
Name: "Bool.true",
Data: []byte{def.True},
Expected: true,
MethodAs: method,
},
{
Name: "Unexpected",
Data: []byte{def.Nil},
Error: def.ErrCanNotDecode,
MethodAs: method,
},
}
testcases.Run(t)
}
================================================
FILE: internal/decoding/complex.go
================================================
package decoding
import (
"encoding/binary"
"fmt"
"math"
"reflect"
"github.com/shamaton/msgpack/v3/def"
)
func (d *decoder) asComplex64(offset int, k reflect.Kind) (complex64, int, error) {
code, offset, err := d.readSize1(offset)
if err != nil {
return complex(0, 0), 0, err
}
switch code {
case def.Fixext8:
t, offset, err := d.readSize1(offset)
if err != nil {
return complex(0, 0), 0, err
}
if int8(t) != def.ComplexTypeCode() {
return complex(0, 0), 0, fmt.Errorf("fixext8. complex type is diffrent %d, %d", t, def.ComplexTypeCode())
}
rb, offset, err := d.readSize4(offset)
if err != nil {
return complex(0, 0), 0, err
}
ib, offset, err := d.readSize4(offset)
if err != nil {
return complex(0, 0), 0, err
}
r := math.Float32frombits(binary.BigEndian.Uint32(rb))
i := math.Float32frombits(binary.BigEndian.Uint32(ib))
return complex(r, i), offset, nil
case def.Fixext16:
t, offset, err := d.readSize1(offset)
if err != nil {
return complex(0, 0), 0, err
}
if int8(t) != def.ComplexTypeCode() {
return complex(0, 0), 0, fmt.Errorf("fixext16. complex type is diffrent %d, %d", t, def.ComplexTypeCode())
}
rb, offset, err := d.readSize8(offset)
if err != nil {
return complex(0, 0), 0, err
}
ib, offset, err := d.readSize8(offset)
if err != nil {
return complex(0, 0), 0, err
}
r := math.Float64frombits(binary.BigEndian.Uint64(rb))
i := math.Float64frombits(binary.BigEndian.Uint64(ib))
return complex64(complex(r, i)), offset, nil
}
return complex(0, 0), 0, d.errorTemplate(code, k)
}
func (d *decoder) asComplex128(offset int, k reflect.Kind) (complex128, int, error) {
code, offset, err := d.readSize1(offset)
if err != nil {
return complex(0, 0), 0, err
}
switch code {
case def.Fixext8:
t, offset, err := d.readSize1(offset)
if err != nil {
return complex(0, 0), 0, err
}
if int8(t) != def.ComplexTypeCode() {
return complex(0, 0), 0, fmt.Errorf("fixext8. complex type is diffrent %d, %d", t, def.ComplexTypeCode())
}
rb, offset, err := d.readSize4(offset)
if err != nil {
return complex(0, 0), 0, err
}
ib, offset, err := d.readSize4(offset)
if err != nil {
return complex(0, 0), 0, err
}
r := math.Float32frombits(binary.BigEndian.Uint32(rb))
i := math.Float32frombits(binary.BigEndian.Uint32(ib))
return complex128(complex(r, i)), offset, nil
case def.Fixext16:
t, offset, err := d.readSize1(offset)
if err != nil {
return complex(0, 0), 0, err
}
if int8(t) != def.ComplexTypeCode() {
return complex(0, 0), 0, fmt.Errorf("fixext16. complex type is diffrent %d, %d", t, def.ComplexTypeCode())
}
rb, offset, err := d.readSize8(offset)
if err != nil {
return complex(0, 0), 0, err
}
ib, offset, err := d.readSize8(offset)
if err != nil {
return complex(0, 0), 0, err
}
r := math.Float64frombits(binary.BigEndian.Uint64(rb))
i := math.Float64frombits(binary.BigEndian.Uint64(ib))
return complex(r, i), offset, nil
}
return complex(0, 0), 0, d.errorTemplate(code, k)
}
================================================
FILE: internal/decoding/complex_test.go
================================================
package decoding
import (
"reflect"
"testing"
"github.com/shamaton/msgpack/v3/def"
)
func Test_asComplex64(t *testing.T) {
method := func(d *decoder) func(int, reflect.Kind) (complex64, int, error) {
return d.asComplex64
}
testcases := AsXXXTestCases[complex64]{
{
Name: "error.code",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Fixext8.error.type",
Data: []byte{def.Fixext8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Fixext8.error.r",
Data: []byte{def.Fixext8, byte(def.ComplexTypeCode())},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Fixext8.error.i",
Data: []byte{def.Fixext8, byte(def.ComplexTypeCode()), 0, 0, 0, 1},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Fixext8.ok",
Data: []byte{def.Fixext8, byte(def.ComplexTypeCode()), 63, 128, 0, 0, 63, 128, 0, 0},
Expected: complex(1, 1),
MethodAs: method,
},
{
Name: "Fixext16.error.type",
Data: []byte{def.Fixext16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Fixext16.error.r",
Data: []byte{def.Fixext16, byte(def.ComplexTypeCode())},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Fixext16.error.i",
Data: []byte{def.Fixext16, byte(def.ComplexTypeCode()), 0, 0, 0, 0, 0, 0, 0, 1},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Fixext16.ok",
Data: []byte{
def.Fixext16, byte(def.ComplexTypeCode()),
63, 240, 0, 0, 0, 0, 0, 0, 63, 240, 0, 0, 0, 0, 0, 0,
},
Expected: complex(1, 1),
MethodAs: method,
},
{
Name: "Unexpected",
Data: []byte{def.Nil},
Error: def.ErrCanNotDecode,
MethodAs: method,
},
}
testcases.Run(t)
}
func Test_asComplex128(t *testing.T) {
method := func(d *decoder) func(int, reflect.Kind) (complex128, int, error) {
return d.asComplex128
}
testcases := AsXXXTestCases[complex128]{
{
Name: "error.code",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Fixext8.error.type",
Data: []byte{def.Fixext8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Fixext8.error.r",
Data: []byte{def.Fixext8, byte(def.ComplexTypeCode())},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Fixext8.error.i",
Data: []byte{def.Fixext8, byte(def.ComplexTypeCode()), 0, 0, 0, 1},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Fixext8.ok",
Data: []byte{def.Fixext8, byte(def.ComplexTypeCode()), 63, 128, 0, 0, 63, 128, 0, 0},
Expected: complex(1, 1),
MethodAs: method,
},
{
Name: "Fixext16.error.type",
Data: []byte{def.Fixext16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Fixext16.error.r",
Data: []byte{def.Fixext16, byte(def.ComplexTypeCode())},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Fixext16.error.i",
Data: []byte{def.Fixext16, byte(def.ComplexTypeCode()), 0, 0, 0, 0, 0, 0, 0, 1},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Fixext16.ok",
Data: []byte{
def.Fixext16, byte(def.ComplexTypeCode()),
63, 240, 0, 0, 0, 0, 0, 0, 63, 240, 0, 0, 0, 0, 0, 0,
},
Expected: complex(1, 1),
MethodAs: method,
},
{
Name: "Unexpected",
Data: []byte{def.Nil},
Error: def.ErrCanNotDecode,
MethodAs: method,
},
}
testcases.Run(t)
}
================================================
FILE: internal/decoding/decoding.go
================================================
package decoding
import (
"fmt"
"reflect"
"github.com/shamaton/msgpack/v3/def"
"github.com/shamaton/msgpack/v3/internal/common"
)
type decoder struct {
data []byte
asArray bool
common.Common
}
// Decode analyzes the MessagePack-encoded data and stores
// the result into the pointer of v.
func Decode(data []byte, v interface{}, asArray bool) error {
d := decoder{data: data, asArray: asArray}
if len(d.data) < 1 {
return def.ErrNoData
}
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr {
return fmt.Errorf("%w. v.(type): %T", def.ErrReceiverNotPointer, v)
}
rv = rv.Elem()
last, err := d.decode(rv, 0)
if err != nil {
return err
}
if len(data) != last {
return fmt.Errorf("%w size=%d, last=%d", def.ErrHasLeftOver, len(data), last)
}
return err
}
func (d *decoder) decode(rv reflect.Value, offset int) (int, error) {
k := rv.Kind()
switch k {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
v, o, err := d.asInt(offset, k)
if err != nil {
return 0, err
}
rv.SetInt(v)
offset = o
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
v, o, err := d.asUint(offset, k)
if err != nil {
return 0, err
}
rv.SetUint(v)
offset = o
case reflect.Float32:
v, o, err := d.asFloat32(offset, k)
if err != nil {
return 0, err
}
rv.SetFloat(float64(v))
offset = o
case reflect.Float64:
v, o, err := d.asFloat64(offset, k)
if err != nil {
return 0, err
}
rv.SetFloat(v)
offset = o
case reflect.String:
// byte slice
if d.isCodeBin(d.data[offset]) {
v, offset, err := d.asBinString(offset, k)
if err != nil {
return 0, err
}
rv.SetString(v)
return offset, nil
}
v, o, err := d.asString(offset, k)
if err != nil {
return 0, err
}
rv.SetString(v)
offset = o
case reflect.Bool:
v, o, err := d.asBool(offset, k)
if err != nil {
return 0, err
}
rv.SetBool(v)
offset = o
case reflect.Slice:
// nil
if d.isCodeNil(d.data[offset]) {
offset++
return offset, nil
}
// byte slice
if d.isCodeBin(d.data[offset]) {
bs, offset, err := d.asBin(offset, k)
if err != nil {
return 0, err
}
rv.SetBytes(bs)
return offset, nil
}
// string to bytes
if d.isCodeString(d.data[offset]) {
l, offset, err := d.stringByteLength(offset, k)
if err != nil {
return 0, err
}
bs, offset, err := d.asStringByteByLength(offset, l, k)
if err != nil {
return 0, err
}
rv.SetBytes(bs)
return offset, nil
}
// get slice length
l, o, err := d.sliceLength(offset, k)
if err != nil {
return 0, err
}
if err = d.hasRequiredLeastSliceSize(o, l); err != nil {
return 0, err
}
// check fixed type
fixedOffset, found, err := d.asFixedSlice(rv, o, l)
if err != nil {
return 0, err
}
if found {
return fixedOffset, nil
}
// create slice dynamically
tmpSlice := reflect.MakeSlice(rv.Type(), l, l)
for i := 0; i < l; i++ {
v := tmpSlice.Index(i)
if v.Kind() == reflect.Struct {
o, err = d.setStruct(v, o, k)
} else {
o, err = d.decode(v, o)
}
if err != nil {
return 0, err
}
}
rv.Set(tmpSlice)
offset = o
case reflect.Complex64:
v, o, err := d.asComplex64(offset, k)
if err != nil {
return 0, err
}
rv.SetComplex(complex128(v))
offset = o
case reflect.Complex128:
v, o, err := d.asComplex128(offset, k)
if err != nil {
return 0, err
}
rv.SetComplex(v)
offset = o
case reflect.Array:
// nil
if d.isCodeNil(d.data[offset]) {
offset++
return offset, nil
}
// byte slice
if d.isCodeBin(d.data[offset]) {
bs, offset, err := d.asBin(offset, k)
if err != nil {
return 0, err
}
if len(bs) > rv.Len() {
return 0, fmt.Errorf("%v len is %d, but msgpack has %d elements, %w", rv.Type(), rv.Len(), len(bs), def.ErrNotMatchArrayElement)
}
for i, b := range bs {
rv.Index(i).SetUint(uint64(b))
}
return offset, nil
}
// string to bytes
if d.isCodeString(d.data[offset]) {
l, offset, err := d.stringByteLength(offset, k)
if err != nil {
return 0, err
}
if l > rv.Len() {
return 0, fmt.Errorf("%v len is %d, but msgpack has %d elements, %w", rv.Type(), rv.Len(), l, def.ErrNotMatchArrayElement)
}
bs, offset, err := d.asStringByteByLength(offset, l, k)
if err != nil {
return 0, err
}
for i, b := range bs {
rv.Index(i).SetUint(uint64(b))
}
return offset, nil
}
// get slice length
l, o, err := d.sliceLength(offset, k)
if err != nil {
return 0, err
}
if l > rv.Len() {
return 0, fmt.Errorf("%v len is %d, but msgpack has %d elements, %w", rv.Type(), rv.Len(), l, def.ErrNotMatchArrayElement)
}
if err = d.hasRequiredLeastSliceSize(o, l); err != nil {
return 0, err
}
// create array dynamically
for i := 0; i < l; i++ {
o, err = d.decode(rv.Index(i), o)
if err != nil {
return 0, err
}
}
offset = o
case reflect.Map:
// nil
if d.isCodeNil(d.data[offset]) {
offset++
return offset, nil
}
// get map length
l, o, err := d.mapLength(offset, k)
if err != nil {
return 0, err
}
if err = d.hasRequiredLeastMapSize(o, l); err != nil {
return 0, err
}
// check fixed type
fixedOffset, found, err := d.asFixedMap(rv, o, l)
if err != nil {
return 0, err
}
if found {
return fixedOffset, nil
}
// create dynamically
key := rv.Type().Key()
value := rv.Type().Elem()
if rv.IsNil() {
rv.Set(reflect.MakeMapWithSize(rv.Type(), l))
}
for i := 0; i < l; i++ {
k := reflect.New(key).Elem()
v := reflect.New(value).Elem()
o, err = d.decode(k, o)
if err != nil {
return 0, err
}
o, err = d.decode(v, o)
if err != nil {
return 0, err
}
rv.SetMapIndex(k, v)
}
offset = o
case reflect.Struct:
o, err := d.setStruct(rv, offset, k)
if err != nil {
return 0, err
}
offset = o
case reflect.Ptr:
// nil
if d.isCodeNil(d.data[offset]) {
offset++
return offset, nil
}
if rv.Elem().Kind() == reflect.Invalid {
n := reflect.New(rv.Type().Elem())
rv.Set(n)
}
o, err := d.decode(rv.Elem(), offset)
if err != nil {
return 0, err
}
offset = o
case reflect.Interface:
if rv.Elem().Kind() == reflect.Ptr {
o, err := d.decode(rv.Elem(), offset)
if err != nil {
return 0, err
}
offset = o
} else {
v, o, err := d.asInterface(offset, k)
if err != nil {
return 0, err
}
if v != nil {
rv.Set(reflect.ValueOf(v))
}
offset = o
}
default:
return 0, fmt.Errorf("%v is %w type", rv.Kind(), def.ErrUnsupportedType)
}
return offset, nil
}
func (d *decoder) errorTemplate(code byte, k reflect.Kind) error {
return fmt.Errorf("%w %x decoding as %v", def.ErrCanNotDecode, code, k)
}
================================================
FILE: internal/decoding/decoding_test.go
================================================
package decoding
import (
"reflect"
"testing"
"github.com/shamaton/msgpack/v3/def"
tu "github.com/shamaton/msgpack/v3/internal/common/testutil"
)
type AsXXXTestCase[T any] struct {
Name string
Data []byte
Expected T
Error error
MethodAs func(d *decoder) func(int, reflect.Kind) (T, int, error)
MethodAsCustom func(d *decoder) (int, T, error)
}
type AsXXXTestCases[T any] []AsXXXTestCase[T]
func (tcs AsXXXTestCases[T]) Run(t *testing.T) {
for _, tc := range tcs {
tc.Run(t)
}
}
func (tc *AsXXXTestCase[T]) Run(t *testing.T) {
const kind = reflect.String
t.Helper()
if tc.MethodAs == nil && tc.MethodAsCustom == nil {
t.Fatal("must set either method or MethodAsCustom")
}
methodAs := func(d *decoder) (T, int, error) {
if tc.MethodAs != nil {
return tc.MethodAs(d)(0, kind)
}
if tc.MethodAsCustom != nil {
v, o, err := tc.MethodAsCustom(d)
return o, v, err
}
panic("unreachable")
}
t.Run(tc.Name, func(t *testing.T) {
d := decoder{
data: tc.Data,
}
v, offset, err := methodAs(&d)
if tc.Error != nil {
tu.IsError(t, err, tc.Error)
return
}
tu.NoError(t, err)
tu.Equal(t, v, tc.Expected)
tu.Equal(t, offset, len(tc.Data))
})
}
func TestDecoding(t *testing.T) {
t.Run("empty data", func(t *testing.T) {
v := new(int)
err := Decode(nil, v, false)
tu.IsError(t, err, def.ErrNoData)
})
t.Run("not pointer", func(t *testing.T) {
v := 0
err := Decode([]byte{def.PositiveFixIntMax}, v, false)
tu.IsError(t, err, def.ErrReceiverNotPointer)
})
t.Run("left data", func(t *testing.T) {
v := new(int)
err := Decode([]byte{def.PositiveFixIntMin, 0}, v, false)
tu.IsError(t, err, def.ErrHasLeftOver)
})
}
func Test_decodeWithCode(t *testing.T) {
var target any
method := func(d *decoder) func(offset int, _ reflect.Kind) (bool, int, error) {
return func(offset int, _ reflect.Kind) (bool, int, error) {
rv := reflect.ValueOf(target)
o, err := d.decode(rv.Elem(), offset)
return true, o, err
}
}
t.Run("Int", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{def.Int8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.Int8, 5},
Expected: true,
MethodAs: method,
},
}
v := new(int)
target = v
testcases.Run(t)
tu.Equal(t, *v, 5)
})
t.Run("Uint", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{def.Uint8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.Uint8, 5},
Expected: true,
MethodAs: method,
},
}
v := new(uint)
target = v
testcases.Run(t)
tu.Equal(t, *v, 5)
})
t.Run("Float32", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{def.Float32},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.Float32, 63, 128, 0, 0},
Expected: true,
MethodAs: method,
},
}
v := new(float32)
target = v
testcases.Run(t)
tu.Equal(t, *v, 1)
})
t.Run("Float64", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{def.Float64},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.Float64, 63, 240, 0, 0, 0, 0, 0, 0},
Expected: true,
MethodAs: method,
},
}
v := new(float64)
target = v
testcases.Run(t)
tu.Equal(t, *v, 1)
})
t.Run("BinString", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{def.Bin8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.Bin8, 1, 'a'},
Expected: true,
MethodAs: method,
},
}
v := new(string)
target = v
testcases.Run(t)
tu.Equal(t, *v, "a")
})
t.Run("String", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{def.Str8},
Expected: false,
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.Str8, 1, 'b'},
Expected: true,
MethodAs: method,
},
}
v := new(string)
target = v
testcases.Run(t)
tu.Equal(t, *v, "b")
})
t.Run("Bool", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{def.Int8},
Error: def.ErrCanNotDecode,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.True},
Expected: true,
MethodAs: method,
},
}
v := new(bool)
target = v
testcases.Run(t)
tu.Equal(t, *v, true)
})
t.Run("Slice.nil", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "ok",
Data: []byte{def.Nil},
Expected: true,
MethodAs: method,
},
}
v := new([]int)
target = v
testcases.Run(t)
tu.Equal(t, *v, nil)
})
t.Run("Slice.bin", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{def.Bin8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.Bin8, 1, 2},
Expected: true,
MethodAs: method,
},
}
v := new([]byte)
target = v
testcases.Run(t)
tu.Equal(t, *v, []byte{2})
})
t.Run("Slice.string", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "error.strlen",
Data: []byte{def.Str8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "error.bytelen",
Data: []byte{def.Str8, 1},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.Str8, 1, 'c'},
Expected: true,
MethodAs: method,
},
}
v := new([]byte)
target = v
testcases.Run(t)
tu.Equal(t, *v, []byte{'c'})
})
t.Run("Slice.fixed", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "error.strlen",
Data: []byte{def.Array16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "error.require",
Data: []byte{def.Array16, 0, 1},
Error: def.ErrLackDataLengthToSlice,
MethodAs: method,
},
{
Name: "error.slice",
Data: []byte{def.Array16, 0, 1, def.Int8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.Array16, 0, 1, def.PositiveFixIntMin + 3},
Expected: true,
MethodAs: method,
},
}
v := new([]int)
target = v
testcases.Run(t)
tu.Equal(t, *v, []int{3})
})
t.Run("Slice.struct", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "error.strlen",
Data: []byte{def.Array16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "error.require",
Data: []byte{def.Array16, 0, 1},
Error: def.ErrLackDataLengthToSlice,
MethodAs: method,
},
{
Name: "error.slice",
Data: []byte{def.Array16, 0, 1, def.Map16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "error.struct",
Data: []byte{def.Array16, 0, 1, def.FixMap + 1, def.FixStr + 1, 'v'},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.Array16, 0, 1, def.FixMap + 1, def.FixStr + 1, 'v', def.PositiveFixIntMin + 3},
Expected: true,
MethodAs: method,
},
}
type st struct {
V int `msgpack:"v"`
}
v := new([]st)
target = v
testcases.Run(t)
tu.Equal(t, *v, []st{{V: 3}})
})
t.Run("Slice.map", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "error.strlen",
Data: []byte{def.Array16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "error.require",
Data: []byte{def.Array16, 0, 1},
Error: def.ErrLackDataLengthToSlice,
MethodAs: method,
},
{
Name: "error.slice",
Data: []byte{def.Array16, 0, 1, def.Map16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "error.map",
Data: []byte{def.Array16, 0, 1, def.FixMap + 1, def.FixStr + 1, 'v'},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.Array16, 0, 1, def.FixMap + 1, def.FixStr + 1, 'v', def.PositiveFixIntMin + 3},
Expected: true,
MethodAs: method,
},
}
v := new([]map[string]int)
target = v
testcases.Run(t)
tu.Equal(t, *v, []map[string]int{{"v": 3}})
})
t.Run("Complex64", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{def.Fixext8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.Fixext8, byte(def.ComplexTypeCode()), 63, 128, 0, 0, 63, 128, 0, 0},
Expected: true,
MethodAs: method,
},
}
v := new(complex64)
target = v
testcases.Run(t)
tu.Equal(t, *v, complex(1, 1))
})
t.Run("Complex128", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{def.Fixext8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.Fixext8, byte(def.ComplexTypeCode()), 63, 128, 0, 0, 63, 128, 0, 0},
Expected: true,
MethodAs: method,
},
}
v := new(complex128)
target = v
testcases.Run(t)
tu.Equal(t, *v, complex(1, 1))
})
t.Run("Array.nil", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "ok",
Data: []byte{def.Nil},
Expected: true,
MethodAs: method,
},
}
v := new([1]int)
target = v
testcases.Run(t)
tu.Equal(t, *v, [1]int{})
})
t.Run("Array.bin", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "error.bin",
Data: []byte{def.Bin8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "error.len",
Data: []byte{def.Bin8, 2, 1, 2},
Error: def.ErrNotMatchArrayElement,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.Bin8, 1, 2},
Expected: true,
MethodAs: method,
},
}
v := new([1]byte)
target = v
testcases.Run(t)
tu.Equal(t, *v, [1]byte{2})
})
t.Run("Array.string", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "error.strlen",
Data: []byte{def.Str8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "error.compare",
Data: []byte{def.Str8, 2},
Error: def.ErrNotMatchArrayElement,
MethodAs: method,
},
{
Name: "error.bytelen",
Data: []byte{def.Str8, 1},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.Str8, 1, 'c'},
Expected: true,
MethodAs: method,
},
}
v := new([1]byte)
target = v
testcases.Run(t)
tu.Equal(t, *v, [1]byte{'c'})
})
t.Run("Array.struct", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "error.strlen",
Data: []byte{def.Array16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "error.len.match",
Data: []byte{def.Array16, 0, 2},
Error: def.ErrNotMatchArrayElement,
MethodAs: method,
},
{
Name: "error.slice",
Data: []byte{def.Array16, 0, 1},
Error: def.ErrLackDataLengthToSlice,
MethodAs: method,
},
{
Name: "error.struct",
Data: []byte{def.Array16, 0, 1, def.FixMap + 1, def.FixStr + 1, 'v'},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.Array16, 0, 1, def.FixMap + 1, def.FixStr + 1, 'v', def.PositiveFixIntMin + 3},
Expected: true,
MethodAs: method,
},
}
type st struct {
V int `msgpack:"v"`
}
v := new([1]st)
target = v
testcases.Run(t)
tu.Equal(t, *v, [1]st{{V: 3}})
})
t.Run("Map.nil", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "ok",
Data: []byte{def.Nil},
Expected: true,
MethodAs: method,
},
}
v := new(map[string]int)
target = v
testcases.Run(t)
tu.Equal(t, *v, nil)
})
t.Run("Map.fixed", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "error.strlen",
Data: []byte{def.Map16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "error.require",
Data: []byte{def.Map16, 0, 1},
Error: def.ErrLackDataLengthToMap,
MethodAs: method,
},
{
Name: "error.map",
Data: []byte{def.Map16, 0, 1, def.Str16, 0},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.Map16, 0, 1, def.FixStr + 1, 'a', def.PositiveFixIntMin + 3},
Expected: true,
MethodAs: method,
},
}
v := new(map[string]int)
target = v
testcases.Run(t)
tu.Equal(t, *v, map[string]int{"a": 3})
})
t.Run("Map.struct", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "error.strlen",
Data: []byte{def.Map16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "error.require",
Data: []byte{def.Map16, 0, 1},
Error: def.ErrLackDataLengthToMap,
MethodAs: method,
},
{
Name: "error.key",
Data: []byte{def.Map16, 0, 1, def.Str16, 0},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "error.value",
Data: []byte{def.Map16, 0, 1, def.FixStr + 1, 'a', def.FixMap + 1, def.FixStr + 1, 'v'},
Expected: true,
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.Map16, 0, 1, def.FixStr + 1, 'a', def.FixMap + 1, def.FixStr + 1, 'v', def.PositiveFixIntMin + 3},
Expected: true,
MethodAs: method,
},
}
type st struct {
V int `msgpack:"v"`
}
v := new(map[string]st)
target = v
testcases.Run(t)
tu.Equal(t, *v, map[string]st{"a": {V: 3}})
})
t.Run("Struct", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{def.Map16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.Map16, 0, 1, def.FixStr + 1, 'v', def.PositiveFixIntMin + 3},
Expected: true,
MethodAs: method,
},
}
type st struct {
V int `msgpack:"v"`
}
v := new(st)
target = v
testcases.Run(t)
tu.Equal(t, *v, st{V: 3})
})
t.Run("Ptr.nil", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "ok",
Data: []byte{def.Nil},
Expected: true,
MethodAs: method,
},
}
v := new(int)
target = &v
testcases.Run(t)
tu.Equal(t, *v, 0)
})
t.Run("Ptr", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{def.Int8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.Int8, 3},
Expected: true,
MethodAs: method,
},
}
v := new(int)
target = &v
testcases.Run(t)
tu.Equal(t, *v, 3)
})
t.Run("Interface.ptr", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{def.Int8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.Int8, 3},
Expected: true,
MethodAs: method,
},
}
v := (any)(new(int))
target = &v
testcases.Run(t)
vv := v.(*int)
tu.Equal(t, *vv, 3)
})
t.Run("Interface", func(t *testing.T) {
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{def.Map16, 0, 1, def.FixStr + 1, 'v', def.Int8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.Map16, 0, 1, def.FixStr + 1, 'v', def.Int8, 3},
Expected: true,
MethodAs: method,
},
}
type st struct {
V any `msgpack:"v"`
}
v := new(st)
target = v
testcases.Run(t)
var vv any = int8(3)
tu.Equal(t, v.V, vv)
})
}
================================================
FILE: internal/decoding/ext.go
================================================
package decoding
import (
"encoding/binary"
"github.com/shamaton/msgpack/v3/def"
"github.com/shamaton/msgpack/v3/ext"
"github.com/shamaton/msgpack/v3/time"
)
var (
extCoderMap = map[int8]ext.Decoder{time.Decoder.Code(): time.Decoder}
extCoders = []ext.Decoder{time.Decoder}
)
// AddExtDecoder adds decoders for extension types.
func AddExtDecoder(f ext.Decoder) {
// ignore time
if f.Code() == time.Decoder.Code() {
return
}
_, ok := extCoderMap[f.Code()]
if !ok {
extCoderMap[f.Code()] = f
updateExtCoders()
}
}
// RemoveExtDecoder removes decoders for extension types.
func RemoveExtDecoder(f ext.Decoder) {
// ignore time
if f.Code() == time.Decoder.Code() {
return
}
_, ok := extCoderMap[f.Code()]
if ok {
delete(extCoderMap, f.Code())
updateExtCoders()
}
}
func updateExtCoders() {
extCoders = make([]ext.Decoder, len(extCoderMap))
i := 0
for k := range extCoderMap {
extCoders[i] = extCoderMap[k]
i++
}
}
func (d *decoder) extEndOffset(offset int) (bool, int, error) {
code, offset, err := d.readSize1(offset)
if err != nil {
return false, 0, err
}
return d.extEndOffsetWithCode(code, offset)
}
func (d *decoder) extEndOffsetWithCode(code byte, offset int) (bool, int, error) {
switch code {
case def.Fixext1:
_, offset, err := d.readSizeN(offset, def.Byte1+def.Byte1)
return true, offset, err
case def.Fixext2:
_, offset, err := d.readSizeN(offset, def.Byte1+def.Byte2)
return true, offset, err
case def.Fixext4:
_, offset, err := d.readSizeN(offset, def.Byte1+def.Byte4)
return true, offset, err
case def.Fixext8:
_, offset, err := d.readSizeN(offset, def.Byte1+def.Byte8)
return true, offset, err
case def.Fixext16:
_, offset, err := d.readSizeN(offset, def.Byte1+def.Byte16)
return true, offset, err
case def.Ext8:
size, offset, err := d.readSize1(offset)
if err != nil {
return true, 0, err
}
_, offset, err = d.readSizeN(offset, def.Byte1+int(size))
return true, offset, err
case def.Ext16:
sizeBytes, offset, err := d.readSize2(offset)
if err != nil {
return true, 0, err
}
_, offset, err = d.readSizeN(offset, def.Byte1+int(binary.BigEndian.Uint16(sizeBytes)))
return true, offset, err
case def.Ext32:
sizeBytes, offset, err := d.readSize4(offset)
if err != nil {
return true, 0, err
}
_, offset, err = d.readSizeN(offset, def.Byte1+int(binary.BigEndian.Uint32(sizeBytes)))
return true, offset, err
default:
return false, 0, nil
}
}
/*
var zero = time.Unix(0,0)
func (d *decoder) isDateTime(offset int) bool {
code, offset := d.readSize1(offset)
if code == def.Fixext4 {
t, _ := d.readSize1(offset)
return int8(t) == def.TimeStamp
} else if code == def.Fixext8 {
t, _ := d.readSize1(offset)
return int8(t) == def.TimeStamp
} else if code == def.Ext8 {
l, offset := d.readSize1(offset)
t, _ := d.readSize1(offset)
return l == 12 && int8(t) == def.TimeStamp
}
return false
}
func (d *decoder) asDateTime(offset int, k reflect.Kind) (time.Time, int, error) {
code, offset := d.readSize1(offset)
switch code {
case def.Fixext4:
_, offset = d.readSize1(offset)
bs, offset := d.readSize4(offset)
return time.Unix(int64(binary.BigEndian.Uint32(bs)), 0), offset, nil
case def.Fixext8:
_, offset = d.readSize1(offset)
bs, offset := d.readSize8(offset)
data64 := binary.BigEndian.Uint64(bs)
nano := int64(data64 >> 34)
if nano > 999999999 {
return zero, 0, fmt.Errorf("In timestamp 64 formats, nanoseconds must not be larger than 999999999 : %d", nano)
}
return time.Unix(int64(data64&0x00000003ffffffff), nano), offset, nil
case def.Ext8:
_, offset = d.readSize1(offset)
_, offset = d.readSize1(offset)
nanobs, offset := d.readSize4(offset)
secbs, offset := d.readSize8(offset)
nano := binary.BigEndian.Uint32(nanobs)
if nano > 999999999 {
return zero, 0, fmt.Errorf("In timestamp 96 formats, nanoseconds must not be larger than 999999999 : %d", nano)
}
sec := binary.BigEndian.Uint64(secbs)
return time.Unix(int64(sec), int64(nano)), offset, nil
}
return zero, 0, d.errorTemplate(code, k)
}
*/
================================================
FILE: internal/decoding/ext_test.go
================================================
package decoding
import (
"reflect"
"testing"
"github.com/shamaton/msgpack/v3/def"
tu "github.com/shamaton/msgpack/v3/internal/common/testutil"
"github.com/shamaton/msgpack/v3/time"
)
func Test_AddExtDecoder(t *testing.T) {
t.Run("ignore", func(t *testing.T) {
AddExtDecoder(time.Decoder)
tu.Equal(t, len(extCoders), 1)
})
}
func Test_RemoveExtDecoder(t *testing.T) {
t.Run("ignore", func(t *testing.T) {
RemoveExtDecoder(time.Decoder)
tu.Equal(t, len(extCoders), 1)
})
}
type trackingExtDecoder struct {
isTypeCalls int
asValueCalls int
}
func (td *trackingExtDecoder) Code() int8 {
return 42
}
func (td *trackingExtDecoder) IsType(_ int, _ *[]byte) bool {
td.isTypeCalls++
return false
}
func (td *trackingExtDecoder) AsValue(_ int, _ reflect.Kind, _ *[]byte) (interface{}, int, error) {
td.asValueCalls++
return nil, 0, ErrTestExtDecoder
}
func TestExtValidationRejectsTruncatedBytesBeforeCustomDecoders(t *testing.T) {
dec := &trackingExtDecoder{}
AddExtDecoder(dec)
defer RemoveExtDecoder(dec)
testcases := []struct {
name string
data []byte
}{
{name: "fixext1", data: []byte{def.Fixext1, 42}},
{name: "fixext2", data: []byte{def.Fixext2, 42, 0}},
{name: "fixext4", data: []byte{def.Fixext4, 42, 0, 0, 0}},
{name: "fixext8", data: []byte{def.Fixext8, 42, 0, 0, 0, 0, 0, 0, 0}},
{name: "fixext16", data: []byte{def.Fixext16, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
{name: "ext8", data: []byte{def.Ext8, 1, 42}},
{name: "ext16", data: []byte{def.Ext16, 0, 1, 42}},
{name: "ext32", data: []byte{def.Ext32, 0, 0, 0, 1, 42}},
}
for _, tc := range testcases {
t.Run("interface/"+tc.name, func(t *testing.T) {
dec.isTypeCalls = 0
dec.asValueCalls = 0
d := decoder{data: tc.data}
_, _, err := d.asInterface(0, reflect.Interface)
tu.IsError(t, err, def.ErrTooShortBytes)
tu.Equal(t, dec.isTypeCalls, 0)
tu.Equal(t, dec.asValueCalls, 0)
})
t.Run("struct/"+tc.name, func(t *testing.T) {
dec.isTypeCalls = 0
dec.asValueCalls = 0
d := decoder{data: tc.data}
var v struct{}
_, err := d.setStruct(reflect.ValueOf(&v).Elem(), 0, reflect.Struct)
tu.IsError(t, err, def.ErrTooShortBytes)
tu.Equal(t, dec.isTypeCalls, 0)
tu.Equal(t, dec.asValueCalls, 0)
})
}
}
================================================
FILE: internal/decoding/float.go
================================================
package decoding
import (
"encoding/binary"
"math"
"reflect"
"github.com/shamaton/msgpack/v3/def"
)
func (d *decoder) asFloat32(offset int, k reflect.Kind) (float32, int, error) {
code, _, err := d.readSize1(offset)
if err != nil {
return 0, 0, err
}
switch {
case code == def.Float32:
offset++
bs, offset, err := d.readSize4(offset)
if err != nil {
return 0, 0, err
}
v := math.Float32frombits(binary.BigEndian.Uint32(bs))
return v, offset, nil
case d.isPositiveFixNum(code), code == def.Uint8, code == def.Uint16, code == def.Uint32, code == def.Uint64:
v, offset, err := d.asUint(offset, k)
if err != nil {
return 0, 0, err
}
return float32(v), offset, nil
case d.isNegativeFixNum(code), code == def.Int8, code == def.Int16, code == def.Int32, code == def.Int64:
v, offset, err := d.asInt(offset, k)
if err != nil {
return 0, 0, err
}
return float32(v), offset, nil
case code == def.Nil:
offset++
return 0, offset, nil
}
return 0, 0, d.errorTemplate(code, k)
}
func (d *decoder) asFloat64(offset int, k reflect.Kind) (float64, int, error) {
code, _, err := d.readSize1(offset)
if err != nil {
return 0, 0, err
}
switch {
case code == def.Float64:
offset++
bs, offset, err := d.readSize8(offset)
if err != nil {
return 0, 0, err
}
v := math.Float64frombits(binary.BigEndian.Uint64(bs))
return v, offset, nil
case code == def.Float32:
offset++
bs, offset, err := d.readSize4(offset)
if err != nil {
return 0, 0, err
}
v := math.Float32frombits(binary.BigEndian.Uint32(bs))
return float64(v), offset, nil
case d.isPositiveFixNum(code), code == def.Uint8, code == def.Uint16, code == def.Uint32, code == def.Uint64:
v, offset, err := d.asUint(offset, k)
if err != nil {
return 0, 0, err
}
return float64(v), offset, nil
case d.isNegativeFixNum(code), code == def.Int8, code == def.Int16, code == def.Int32, code == def.Int64:
v, offset, err := d.asInt(offset, k)
if err != nil {
return 0, 0, err
}
return float64(v), offset, nil
case code == def.Nil:
offset++
return 0, offset, nil
}
return 0, 0, d.errorTemplate(code, k)
}
================================================
FILE: internal/decoding/float_test.go
================================================
package decoding
import (
"reflect"
"testing"
"github.com/shamaton/msgpack/v3/def"
)
func Test_asFloat32(t *testing.T) {
method := func(d *decoder) func(int, reflect.Kind) (float32, int, error) {
return d.asFloat32
}
testcases := AsXXXTestCases[float32]{
{
Name: "error.code",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Float32.error",
Data: []byte{def.Float32},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Float32.ok",
Data: []byte{def.Float32, 63, 128, 0, 0},
Expected: float32(1),
MethodAs: method,
},
{
Name: "PositiveFixNum.ok",
Data: []byte{def.PositiveFixIntMin + 1},
Expected: float32(1),
MethodAs: method,
},
{
Name: "Uint8.error",
Data: []byte{def.Uint8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Uint8.ok",
Data: []byte{def.Uint8, 1},
Expected: float32(1),
MethodAs: method,
},
{
Name: "Uint16.error",
Data: []byte{def.Uint16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Uint16.ok",
Data: []byte{def.Uint16, 0, 1},
Expected: float32(1),
MethodAs: method,
},
{
Name: "Uint32.error",
Data: []byte{def.Uint32},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Uint32.ok",
Data: []byte{def.Uint32, 0, 0, 0, 1},
Expected: float32(1),
MethodAs: method,
},
{
Name: "Uint64.error",
Data: []byte{def.Uint64},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Uint64.ok",
Data: []byte{def.Uint64, 0, 0, 0, 0, 0, 0, 0, 1},
Expected: float32(1),
MethodAs: method,
},
{
Name: "NegativeFixNum.ok",
Data: []byte{0xff},
Expected: float32(-1),
MethodAs: method,
},
{
Name: "Int8.error",
Data: []byte{def.Int8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Int8.ok",
Data: []byte{def.Int8, 0xff},
Expected: float32(-1),
MethodAs: method,
},
{
Name: "Int16.error",
Data: []byte{def.Int16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Int16.ok",
Data: []byte{def.Int16, 0xff, 0xff},
Expected: float32(-1),
MethodAs: method,
},
{
Name: "Int32.error",
Data: []byte{def.Int32},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Int32.ok",
Data: []byte{def.Int32, 0xff, 0xff, 0xff, 0xff},
Expected: float32(-1),
MethodAs: method,
},
{
Name: "Int64.error",
Data: []byte{def.Int64},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Int64.ok",
Data: []byte{def.Int64, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
Expected: float32(-1),
MethodAs: method,
},
{
Name: "Nil.ok",
Data: []byte{def.Nil},
Expected: float32(0),
MethodAs: method,
},
{
Name: "Unexpected",
Data: []byte{def.Str8},
Error: def.ErrCanNotDecode,
MethodAs: method,
},
}
testcases.Run(t)
}
func Test_asFloat64(t *testing.T) {
method := func(d *decoder) func(int, reflect.Kind) (float64, int, error) {
return d.asFloat64
}
testcases := AsXXXTestCases[float64]{
{
Name: "error.code",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Float64.error",
Data: []byte{def.Float64},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Float64.ok",
Data: []byte{def.Float64, 63, 240, 0, 0, 0, 0, 0, 0},
Expected: float64(1),
MethodAs: method,
},
{
Name: "Float32.error",
Data: []byte{def.Float32},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Float32.ok",
Data: []byte{def.Float32, 63, 128, 0, 0},
Expected: float64(1),
MethodAs: method,
},
{
Name: "PositiveFixNum.ok",
Data: []byte{def.PositiveFixIntMin + 1},
Expected: float64(1),
MethodAs: method,
},
{
Name: "Uint8.error",
Data: []byte{def.Uint8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Uint8.ok",
Data: []byte{def.Uint8, 1},
Expected: float64(1),
MethodAs: method,
},
{
Name: "Uint16.error",
Data: []byte{def.Uint16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Uint16.ok",
Data: []byte{def.Uint16, 0, 1},
Expected: float64(1),
MethodAs: method,
},
{
Name: "Uint32.error",
Data: []byte{def.Uint32},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Uint32.ok",
Data: []byte{def.Uint32, 0, 0, 0, 1},
Expected: float64(1),
MethodAs: method,
},
{
Name: "Uint64.error",
Data: []byte{def.Uint64},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Uint64.ok",
Data: []byte{def.Uint64, 0, 0, 0, 0, 0, 0, 0, 1},
Expected: float64(1),
MethodAs: method,
},
{
Name: "NegativeFixNum.ok",
Data: []byte{0xff},
Expected: float64(-1),
MethodAs: method,
},
{
Name: "Int8.error",
Data: []byte{def.Int8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Int8.ok",
Data: []byte{def.Int8, 0xff},
Expected: float64(-1),
MethodAs: method,
},
{
Name: "Int16.error",
Data: []byte{def.Int16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Int16.ok",
Data: []byte{def.Int16, 0xff, 0xff},
Expected: float64(-1),
MethodAs: method,
},
{
Name: "Int32.error",
Data: []byte{def.Int32},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Int32.ok",
Data: []byte{def.Int32, 0xff, 0xff, 0xff, 0xff},
Expected: float64(-1),
MethodAs: method,
},
{
Name: "Int64.error",
Data: []byte{def.Int64},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Int64.ok",
Data: []byte{def.Int64, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
Expected: float64(-1),
MethodAs: method,
},
{
Name: "Nil.ok",
Data: []byte{def.Nil},
Expected: float64(0),
MethodAs: method,
},
{
Name: "Unexpected",
Data: []byte{def.Str8},
Error: def.ErrCanNotDecode,
MethodAs: method,
},
}
testcases.Run(t)
}
================================================
FILE: internal/decoding/int.go
================================================
package decoding
import (
"encoding/binary"
"reflect"
"github.com/shamaton/msgpack/v3/def"
)
func (d *decoder) isPositiveFixNum(v byte) bool {
return def.PositiveFixIntMin <= v && v <= def.PositiveFixIntMax
}
func (d *decoder) isNegativeFixNum(v byte) bool {
return def.NegativeFixintMin <= int8(v) && int8(v) <= def.NegativeFixintMax
}
func (d *decoder) asInt(offset int, k reflect.Kind) (int64, int, error) {
code, _, err := d.readSize1(offset)
if err != nil {
return 0, 0, err
}
switch {
case d.isPositiveFixNum(code):
b, offset, err := d.readSize1(offset)
if err != nil {
return 0, 0, err
}
return int64(b), offset, nil
case d.isNegativeFixNum(code):
b, offset, err := d.readSize1(offset)
if err != nil {
return 0, 0, err
}
return int64(int8(b)), offset, nil
case code == def.Uint8:
offset++
b, offset, err := d.readSize1(offset)
if err != nil {
return 0, 0, err
}
return int64(uint8(b)), offset, nil
case code == def.Int8:
offset++
b, offset, err := d.readSize1(offset)
if err != nil {
return 0, 0, err
}
return int64(int8(b)), offset, nil
case code == def.Uint16:
offset++
bs, offset, err := d.readSize2(offset)
if err != nil {
return 0, 0, err
}
v := binary.BigEndian.Uint16(bs)
return int64(v), offset, nil
case code == def.Int16:
offset++
bs, offset, err := d.readSize2(offset)
if err != nil {
return 0, 0, err
}
v := int16(binary.BigEndian.Uint16(bs))
return int64(v), offset, nil
case code == def.Uint32:
offset++
bs, offset, err := d.readSize4(offset)
if err != nil {
return 0, 0, err
}
v := binary.BigEndian.Uint32(bs)
return int64(v), offset, nil
case code == def.Int32:
offset++
bs, offset, err := d.readSize4(offset)
if err != nil {
return 0, 0, err
}
v := int32(binary.BigEndian.Uint32(bs))
return int64(v), offset, nil
case code == def.Uint64:
offset++
bs, offset, err := d.readSize8(offset)
if err != nil {
return 0, 0, err
}
return int64(binary.BigEndian.Uint64(bs)), offset, nil
case code == def.Int64:
offset++
bs, offset, err := d.readSize8(offset)
if err != nil {
return 0, 0, err
}
return int64(binary.BigEndian.Uint64(bs)), offset, nil
case code == def.Float32:
v, offset, err := d.asFloat32(offset, k)
if err != nil {
return 0, 0, err
}
return int64(v), offset, nil
case code == def.Float64:
v, offset, err := d.asFloat64(offset, k)
if err != nil {
return 0, 0, err
}
return int64(v), offset, nil
case code == def.Nil:
offset++
return 0, offset, nil
}
return 0, 0, d.errorTemplate(code, k)
}
================================================
FILE: internal/decoding/int_test.go
================================================
package decoding
import (
"reflect"
"testing"
"github.com/shamaton/msgpack/v3/def"
)
func Test_asInt(t *testing.T) {
method := func(d *decoder) func(int, reflect.Kind) (int64, int, error) {
return d.asInt
}
testcases := AsXXXTestCases[int64]{
{
Name: "error.code",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "PositiveFixNum.ok",
Data: []byte{def.PositiveFixIntMin + 1},
Expected: int64(1),
MethodAs: method,
},
{
Name: "Uint8.error",
Data: []byte{def.Uint8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Uint8.ok",
Data: []byte{def.Uint8, 1},
Expected: int64(1),
MethodAs: method,
},
{
Name: "Uint16.error",
Data: []byte{def.Uint16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Uint16.ok",
Data: []byte{def.Uint16, 0, 1},
Expected: int64(1),
MethodAs: method,
},
{
Name: "Uint32.error",
Data: []byte{def.Uint32},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Uint32.ok",
Data: []byte{def.Uint32, 0, 0, 0, 1},
Expected: int64(1),
MethodAs: method,
},
{
Name: "Uint64.error",
Data: []byte{def.Uint64},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Uint64.ok",
Data: []byte{def.Uint64, 0, 0, 0, 0, 0, 0, 0, 1},
Expected: int64(1),
MethodAs: method,
},
{
Name: "NegativeFixNum.ok",
Data: []byte{0xff},
Expected: int64(-1),
MethodAs: method,
},
{
Name: "Int8.error",
Data: []byte{def.Int8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Int8.ok",
Data: []byte{def.Int8, 0xff},
Expected: int64(-1),
MethodAs: method,
},
{
Name: "Int16.error",
Data: []byte{def.Int16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Int16.ok",
Data: []byte{def.Int16, 0xff, 0xff},
Expected: int64(-1),
MethodAs: method,
},
{
Name: "Int32.error",
Data: []byte{def.Int32},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Int32.ok",
Data: []byte{def.Int32, 0xff, 0xff, 0xff, 0xff},
Expected: int64(-1),
MethodAs: method,
},
{
Name: "Int64.error",
Data: []byte{def.Int64},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Int64.ok",
Data: []byte{def.Int64, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
Expected: int64(-1),
MethodAs: method,
},
{
Name: "Float32.error",
Data: []byte{def.Float32},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Float32.ok",
Data: []byte{def.Float32, 63, 128, 0, 0},
Expected: int64(1),
MethodAs: method,
},
{
Name: "Float64.error",
Data: []byte{def.Float64},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Float64.ok",
Data: []byte{def.Float64, 63, 240, 0, 0, 0, 0, 0, 0},
Expected: int64(1),
MethodAs: method,
},
{
Name: "Nil.ok",
Data: []byte{def.Nil},
Expected: int64(0),
MethodAs: method,
},
{
Name: "Unexpected",
Data: []byte{def.Str8},
Error: def.ErrCanNotDecode,
MethodAs: method,
},
}
testcases.Run(t)
}
================================================
FILE: internal/decoding/interface.go
================================================
package decoding
import (
"fmt"
"reflect"
"github.com/shamaton/msgpack/v3/def"
)
func (d *decoder) asInterface(offset int, k reflect.Kind) (interface{}, int, error) {
code, _, err := d.readSize1(offset)
if err != nil {
return 0, 0, err
}
switch {
case code == def.Nil:
offset++
return nil, offset, nil
case code == def.True, code == def.False:
v, offset, err := d.asBool(offset, k)
if err != nil {
return nil, 0, err
}
return v, offset, nil
case d.isPositiveFixNum(code), code == def.Uint8:
v, offset, err := d.asUint(offset, k)
if err != nil {
return nil, 0, err
}
return uint8(v), offset, err
case code == def.Uint16:
v, offset, err := d.asUint(offset, k)
if err != nil {
return nil, 0, err
}
return uint16(v), offset, err
case code == def.Uint32:
v, offset, err := d.asUint(offset, k)
if err != nil {
return nil, 0, err
}
return uint32(v), offset, err
case code == def.Uint64:
v, offset, err := d.asUint(offset, k)
if err != nil {
return nil, 0, err
}
return v, offset, err
case d.isNegativeFixNum(code), code == def.Int8:
v, offset, err := d.asInt(offset, k)
if err != nil {
return nil, 0, err
}
return int8(v), offset, err
case code == def.Int16:
v, offset, err := d.asInt(offset, k)
if err != nil {
return nil, 0, err
}
return int16(v), offset, err
case code == def.Int32:
v, offset, err := d.asInt(offset, k)
if err != nil {
return nil, 0, err
}
return int32(v), offset, err
case code == def.Int64:
v, offset, err := d.asInt(offset, k)
if err != nil {
return nil, 0, err
}
return v, offset, err
case code == def.Float32:
v, offset, err := d.asFloat32(offset, k)
if err != nil {
return nil, 0, err
}
return v, offset, err
case code == def.Float64:
v, offset, err := d.asFloat64(offset, k)
if err != nil {
return nil, 0, err
}
return v, offset, err
case d.isFixString(code), code == def.Str8, code == def.Str16, code == def.Str32:
v, offset, err := d.asString(offset, k)
if err != nil {
return nil, 0, err
}
return v, offset, err
case code == def.Bin8, code == def.Bin16, code == def.Bin32:
v, offset, err := d.asBin(offset, k)
if err != nil {
return nil, 0, err
}
return v, offset, err
case d.isFixSlice(code), code == def.Array16, code == def.Array32:
l, o, err := d.sliceLength(offset, k)
if err != nil {
return nil, 0, err
}
if err = d.hasRequiredLeastSliceSize(o, l); err != nil {
return nil, 0, err
}
v := make([]interface{}, l)
for i := 0; i < l; i++ {
vv, o2, err := d.asInterface(o, k)
if err != nil {
return nil, 0, err
}
v[i] = vv
o = o2
}
offset = o
return v, offset, nil
case d.isFixMap(code), code == def.Map16, code == def.Map32:
l, o, err := d.mapLength(offset, k)
if err != nil {
return nil, 0, err
}
if err = d.hasRequiredLeastMapSize(o, l); err != nil {
return nil, 0, err
}
v := make(map[interface{}]interface{}, l)
for i := 0; i < l; i++ {
if err := d.canSetAsMapKey(o); err != nil {
return nil, 0, err
}
key, o2, err := d.asInterface(o, k)
if err != nil {
return nil, 0, err
}
value, o2, err := d.asInterface(o2, k)
if err != nil {
return nil, 0, err
}
v[key] = value
o = o2
}
offset = o
return v, offset, nil
}
/* use ext
if d.isDateTime(offset) {
v, offset, err := d.asDateTime(offset, k)
if err != nil {
return nil, 0, err
}
return v, offset, nil
}
*/
// ext
isExt, _, err := d.extEndOffset(offset)
if err != nil {
return nil, 0, err
}
if isExt {
for i := range extCoders {
if extCoders[i].IsType(offset, &d.data) {
v, offset, err := extCoders[i].AsValue(offset, k, &d.data)
if err != nil {
return nil, 0, err
}
return v, offset, nil
}
}
}
return nil, 0, d.errorTemplate(code, k)
}
func (d *decoder) canSetAsMapKey(index int) error {
code, _, err := d.readSize1(index)
if err != nil {
return err
}
switch {
case d.isFixSlice(code), code == def.Array16, code == def.Array32:
return fmt.Errorf("%w. code: %x", def.ErrCanNotSetSliceAsMapKey, code)
case d.isFixMap(code), code == def.Map16, code == def.Map32:
return fmt.Errorf("%w. code: %x", def.ErrCanNotSetMapAsMapKey, code)
}
return nil
}
================================================
FILE: internal/decoding/interface_test.go
================================================
package decoding
import (
"fmt"
"reflect"
"testing"
"github.com/shamaton/msgpack/v3/def"
"github.com/shamaton/msgpack/v3/ext"
)
func Test_asInterfaceWithCode(t *testing.T) {
dec := testExt2Decoder{}
AddExtDecoder(&dec)
defer RemoveExtDecoder(&dec)
method := func(d *decoder) func(int, reflect.Kind) (any, int, error) {
return d.asInterface
}
testcases := AsXXXTestCases[any]{
{
Name: "error.code",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Uint8.error",
Data: []byte{def.Uint8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Uint16.error",
Data: []byte{def.Uint16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Uint32.error",
Data: []byte{def.Uint32},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Uint64.error",
Data: []byte{def.Uint64},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Int8.error",
Data: []byte{def.Int8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Int16.error",
Data: []byte{def.Int16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Int32.error",
Data: []byte{def.Int32},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Int64.error",
Data: []byte{def.Int64},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Float32.error",
Data: []byte{def.Float32},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Float64.error",
Data: []byte{def.Float64},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Str.error",
Data: []byte{def.Str8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Bin.error",
Data: []byte{def.Bin8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Array.error.length",
Data: []byte{def.Array16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Array.error.required",
Data: []byte{def.Array16, 0, 1},
Error: def.ErrLackDataLengthToSlice,
MethodAs: method,
},
{
Name: "Array.error.set",
Data: []byte{def.Array16, 0, 1, def.Int8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Map.error.length",
Data: []byte{def.Map16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Map.error.required",
Data: []byte{def.Map16, 0, 1},
Error: def.ErrLackDataLengthToMap,
MethodAs: method,
},
{
Name: "Map.error.set.can.slice",
Data: []byte{def.Map16, 0, 1, def.Array16, 0},
Error: def.ErrCanNotSetSliceAsMapKey,
MethodAs: method,
},
{
Name: "Map.error.set.can.map",
Data: []byte{def.Map16, 0, 1, def.Map16, 0},
Error: def.ErrCanNotSetMapAsMapKey,
MethodAs: method,
},
{
Name: "Map.error.set.key",
Data: []byte{def.Map16, 0, 1, def.Str8, 1},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Map.error.set.value",
Data: []byte{def.Map16, 0, 1, def.FixStr + 1, 'a'},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ExtCoder.error.truncated",
Data: []byte{def.Fixext1, 3},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ExtCoder.error",
Data: []byte{def.Fixext1, 3, 0},
Error: ErrTestExtDecoder,
MethodAs: method,
},
}
for _, tc := range testcases {
tc.Run(t)
}
}
// TODO: to testutil
type testExt2Decoder struct {
ext.DecoderCommon
}
var _ ext.Decoder = (*testExt2Decoder)(nil)
func (td *testExt2Decoder) Code() int8 {
return 3
}
func (td *testExt2Decoder) IsType(o int, d *[]byte) bool {
// todo : lack of error handling
code, _ := td.ReadSize1(o, d)
if code == def.Fixext1 {
extCode, _ := td.ReadSize1(o+1, d)
return int8(extCode) == td.Code()
}
return false
}
var ErrTestExtDecoder = fmt.Errorf("testExtDecoder")
func (td *testExt2Decoder) AsValue(_ int, _ reflect.Kind, _ *[]byte) (any, int, error) {
return nil, 0, ErrTestExtDecoder
}
================================================
FILE: internal/decoding/map.go
================================================
package decoding
import (
"encoding/binary"
"reflect"
"github.com/shamaton/msgpack/v3/def"
)
var (
typeMapStringInt = reflect.TypeOf(map[string]int{})
typeMapStringInt8 = reflect.TypeOf(map[string]int8{})
typeMapStringInt16 = reflect.TypeOf(map[string]int16{})
typeMapStringInt32 = reflect.TypeOf(map[string]int32{})
typeMapStringInt64 = reflect.TypeOf(map[string]int64{})
typeMapStringUint = reflect.TypeOf(map[string]uint{})
typeMapStringUint8 = reflect.TypeOf(map[string]uint8{})
typeMapStringUint16 = reflect.TypeOf(map[string]uint16{})
typeMapStringUint32 = reflect.TypeOf(map[string]uint32{})
typeMapStringUint64 = reflect.TypeOf(map[string]uint64{})
typeMapStringFloat32 = reflect.TypeOf(map[string]float32{})
typeMapStringFloat64 = reflect.TypeOf(map[string]float64{})
typeMapStringBool = reflect.TypeOf(map[string]bool{})
typeMapStringString = reflect.TypeOf(map[string]string{})
typeMapIntString = reflect.TypeOf(map[int]string{})
typeMapInt8String = reflect.TypeOf(map[int8]string{})
typeMapInt16String = reflect.TypeOf(map[int16]string{})
typeMapInt32String = reflect.TypeOf(map[int32]string{})
typeMapInt64String = reflect.TypeOf(map[int64]string{})
typeMapIntBool = reflect.TypeOf(map[int]bool{})
typeMapInt8Bool = reflect.TypeOf(map[int8]bool{})
typeMapInt16Bool = reflect.TypeOf(map[int16]bool{})
typeMapInt32Bool = reflect.TypeOf(map[int32]bool{})
typeMapInt64Bool = reflect.TypeOf(map[int64]bool{})
typeMapUintString = reflect.TypeOf(map[uint]string{})
typeMapUint8String = reflect.TypeOf(map[uint8]string{})
typeMapUint16String = reflect.TypeOf(map[uint16]string{})
typeMapUint32String = reflect.TypeOf(map[uint32]string{})
typeMapUint64String = reflect.TypeOf(map[uint64]string{})
typeMapUintBool = reflect.TypeOf(map[uint]bool{})
typeMapUint8Bool = reflect.TypeOf(map[uint8]bool{})
typeMapUint16Bool = reflect.TypeOf(map[uint16]bool{})
typeMapUint32Bool = reflect.TypeOf(map[uint32]bool{})
typeMapUint64Bool = reflect.TypeOf(map[uint64]bool{})
typeMapFloat32String = reflect.TypeOf(map[float32]string{})
typeMapFloat64String = reflect.TypeOf(map[float64]string{})
typeMapFloat32Bool = reflect.TypeOf(map[float32]bool{})
typeMapFloat64Bool = reflect.TypeOf(map[float64]bool{})
)
func (d *decoder) isFixMap(v byte) bool {
return def.FixMap <= v && v <= def.FixMap+0x0f
}
func (d *decoder) mapLength(offset int, k reflect.Kind) (int, int, error) {
code, offset, err := d.readSize1(offset)
if err != nil {
return 0, 0, err
}
switch {
case d.isFixMap(code):
return int(code - def.FixMap), offset, nil
case code == def.Map16:
bs, offset, err := d.readSize2(offset)
if err != nil {
return 0, 0, err
}
return int(binary.BigEndian.Uint16(bs)), offset, nil
case code == def.Map32:
bs, offset, err := d.readSize4(offset)
if err != nil {
return 0, 0, err
}
return int(binary.BigEndian.Uint32(bs)), offset, nil
}
return 0, 0, d.errorTemplate(code, k)
}
func (d *decoder) hasRequiredLeastMapSize(offset, length int) error {
// minimum check (byte length)
if len(d.data[offset:]) < length*2 {
return def.ErrLackDataLengthToMap
}
return nil
}
func (d *decoder) asFixedMap(rv reflect.Value, offset int, l int) (int, bool, error) {
t := rv.Type()
keyKind := t.Key().Kind()
valueKind := t.Elem().Kind()
switch t {
case typeMapStringInt:
m := make(map[string]int, l)
for i := 0; i < l; i++ {
k, o, err := d.asString(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asInt(o, valueKind)
if err != nil {
return 0, false, err
}
m[k] = int(v)
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapStringUint:
m := make(map[string]uint, l)
for i := 0; i < l; i++ {
k, o, err := d.asString(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asUint(o, valueKind)
if err != nil {
return 0, false, err
}
m[k] = uint(v)
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapStringFloat32:
m := make(map[string]float32, l)
for i := 0; i < l; i++ {
k, o, err := d.asString(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asFloat32(o, valueKind)
if err != nil {
return 0, false, err
}
m[k] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapStringFloat64:
m := make(map[string]float64, l)
for i := 0; i < l; i++ {
k, o, err := d.asString(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asFloat64(o, valueKind)
if err != nil {
return 0, false, err
}
m[k] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapStringBool:
m := make(map[string]bool, l)
for i := 0; i < l; i++ {
k, o, err := d.asString(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asBool(o, valueKind)
if err != nil {
return 0, false, err
}
m[k] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapStringString:
m := make(map[string]string, l)
for i := 0; i < l; i++ {
k, o, err := d.asString(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asString(o, valueKind)
if err != nil {
return 0, false, err
}
m[k] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapStringInt8:
m := make(map[string]int8, l)
for i := 0; i < l; i++ {
k, o, err := d.asString(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asInt(o, valueKind)
if err != nil {
return 0, false, err
}
m[k] = int8(v)
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapStringInt16:
m := make(map[string]int16, l)
for i := 0; i < l; i++ {
k, o, err := d.asString(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asInt(o, valueKind)
if err != nil {
return 0, false, err
}
m[k] = int16(v)
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapStringInt32:
m := make(map[string]int32, l)
for i := 0; i < l; i++ {
k, o, err := d.asString(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asInt(o, valueKind)
if err != nil {
return 0, false, err
}
m[k] = int32(v)
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapStringInt64:
m := make(map[string]int64, l)
for i := 0; i < l; i++ {
k, o, err := d.asString(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asInt(o, valueKind)
if err != nil {
return 0, false, err
}
m[k] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapStringUint8:
m := make(map[string]uint8, l)
for i := 0; i < l; i++ {
k, o, err := d.asString(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asUint(o, valueKind)
if err != nil {
return 0, false, err
}
m[k] = uint8(v)
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapStringUint16:
m := make(map[string]uint16, l)
for i := 0; i < l; i++ {
k, o, err := d.asString(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asUint(o, valueKind)
if err != nil {
return 0, false, err
}
m[k] = uint16(v)
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapStringUint32:
m := make(map[string]uint32, l)
for i := 0; i < l; i++ {
k, o, err := d.asString(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asUint(o, valueKind)
if err != nil {
return 0, false, err
}
m[k] = uint32(v)
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapStringUint64:
m := make(map[string]uint64, l)
for i := 0; i < l; i++ {
k, o, err := d.asString(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asUint(o, valueKind)
if err != nil {
return 0, false, err
}
m[k] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapIntString:
m := make(map[int]string, l)
for i := 0; i < l; i++ {
k, o, err := d.asInt(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asString(o, valueKind)
if err != nil {
return 0, false, err
}
m[int(k)] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapInt8String:
m := make(map[int8]string, l)
for i := 0; i < l; i++ {
k, o, err := d.asInt(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asString(o, valueKind)
if err != nil {
return 0, false, err
}
m[int8(k)] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapInt16String:
m := make(map[int16]string, l)
for i := 0; i < l; i++ {
k, o, err := d.asInt(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asString(o, valueKind)
if err != nil {
return 0, false, err
}
m[int16(k)] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapInt32String:
m := make(map[int32]string, l)
for i := 0; i < l; i++ {
k, o, err := d.asInt(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asString(o, valueKind)
if err != nil {
return 0, false, err
}
m[int32(k)] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapInt64String:
m := make(map[int64]string, l)
for i := 0; i < l; i++ {
k, o, err := d.asInt(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asString(o, valueKind)
if err != nil {
return 0, false, err
}
m[k] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapIntBool:
m := make(map[int]bool, l)
for i := 0; i < l; i++ {
k, o, err := d.asInt(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asBool(o, valueKind)
if err != nil {
return 0, false, err
}
m[int(k)] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapInt8Bool:
m := make(map[int8]bool, l)
for i := 0; i < l; i++ {
k, o, err := d.asInt(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asBool(o, valueKind)
if err != nil {
return 0, false, err
}
m[int8(k)] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapInt16Bool:
m := make(map[int16]bool, l)
for i := 0; i < l; i++ {
k, o, err := d.asInt(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asBool(o, valueKind)
if err != nil {
return 0, false, err
}
m[int16(k)] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapInt32Bool:
m := make(map[int32]bool, l)
for i := 0; i < l; i++ {
k, o, err := d.asInt(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asBool(o, valueKind)
if err != nil {
return 0, false, err
}
m[int32(k)] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapInt64Bool:
m := make(map[int64]bool, l)
for i := 0; i < l; i++ {
k, o, err := d.asInt(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asBool(o, valueKind)
if err != nil {
return 0, false, err
}
m[k] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapUintString:
m := make(map[uint]string, l)
for i := 0; i < l; i++ {
k, o, err := d.asUint(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asString(o, valueKind)
if err != nil {
return 0, false, err
}
m[uint(k)] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapUint8String:
m := make(map[uint8]string, l)
for i := 0; i < l; i++ {
k, o, err := d.asUint(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asString(o, valueKind)
if err != nil {
return 0, false, err
}
m[uint8(k)] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapUint16String:
m := make(map[uint16]string, l)
for i := 0; i < l; i++ {
k, o, err := d.asUint(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asString(o, valueKind)
if err != nil {
return 0, false, err
}
m[uint16(k)] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapUint32String:
m := make(map[uint32]string, l)
for i := 0; i < l; i++ {
k, o, err := d.asUint(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asString(o, valueKind)
if err != nil {
return 0, false, err
}
m[uint32(k)] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapUint64String:
m := make(map[uint64]string, l)
for i := 0; i < l; i++ {
k, o, err := d.asUint(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asString(o, valueKind)
if err != nil {
return 0, false, err
}
m[k] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapUintBool:
m := make(map[uint]bool, l)
for i := 0; i < l; i++ {
k, o, err := d.asUint(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asBool(o, valueKind)
if err != nil {
return 0, false, err
}
m[uint(k)] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapUint8Bool:
m := make(map[uint8]bool, l)
for i := 0; i < l; i++ {
k, o, err := d.asUint(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asBool(o, valueKind)
if err != nil {
return 0, false, err
}
m[uint8(k)] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapUint16Bool:
m := make(map[uint16]bool, l)
for i := 0; i < l; i++ {
k, o, err := d.asUint(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asBool(o, valueKind)
if err != nil {
return 0, false, err
}
m[uint16(k)] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapUint32Bool:
m := make(map[uint32]bool, l)
for i := 0; i < l; i++ {
k, o, err := d.asUint(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asBool(o, valueKind)
if err != nil {
return 0, false, err
}
m[uint32(k)] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapUint64Bool:
m := make(map[uint64]bool, l)
for i := 0; i < l; i++ {
k, o, err := d.asUint(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asBool(o, valueKind)
if err != nil {
return 0, false, err
}
m[k] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapFloat32String:
m := make(map[float32]string, l)
for i := 0; i < l; i++ {
k, o, err := d.asFloat32(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asString(o, valueKind)
if err != nil {
return 0, false, err
}
m[k] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapFloat64String:
m := make(map[float64]string, l)
for i := 0; i < l; i++ {
k, o, err := d.asFloat64(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asString(o, valueKind)
if err != nil {
return 0, false, err
}
m[k] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapFloat32Bool:
m := make(map[float32]bool, l)
for i := 0; i < l; i++ {
k, o, err := d.asFloat32(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asBool(o, valueKind)
if err != nil {
return 0, false, err
}
m[k] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
case typeMapFloat64Bool:
m := make(map[float64]bool, l)
for i := 0; i < l; i++ {
k, o, err := d.asFloat64(offset, keyKind)
if err != nil {
return 0, false, err
}
v, o, err := d.asBool(o, valueKind)
if err != nil {
return 0, false, err
}
m[k] = v
offset = o
}
rv.Set(reflect.ValueOf(m))
return offset, true, nil
}
return offset, false, nil
}
================================================
FILE: internal/decoding/map_test.go
================================================
package decoding
import (
"fmt"
"math"
"reflect"
"testing"
"github.com/shamaton/msgpack/v3/def"
tu "github.com/shamaton/msgpack/v3/internal/common/testutil"
)
func Test_mapLength(t *testing.T) {
method := func(d *decoder) func(int, reflect.Kind) (int, int, error) {
return d.mapLength
}
testcases := AsXXXTestCases[int]{
{
Name: "error.code",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "FixMap",
Data: []byte{def.FixMap + 3},
Expected: 3,
MethodAs: method,
},
{
Name: "Map16.error",
Data: []byte{def.Map16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Map16.ok",
Data: []byte{def.Map16, 0xff, 0xff},
Expected: math.MaxUint16,
MethodAs: method,
},
{
Name: "Map32.error",
Data: []byte{def.Map32},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Map32.ok",
Data: []byte{def.Map32, 0xff, 0xff, 0xff, 0xff},
Expected: math.MaxUint32,
MethodAs: method,
},
{
Name: "Unexpected",
Data: []byte{def.Nil},
Error: def.ErrCanNotDecode,
MethodAs: method,
},
}
testcases.Run(t)
}
func Test_asFixedMap_StringInt(t *testing.T) {
run := func(t *testing.T, v any, dv byte) {
method := func(d *decoder) (int, bool, error) {
rv := reflect.ValueOf(v)
return d.asFixedMap(rv.Elem(), 0, 1)
}
name := fmt.Sprintf("%T", v)
testcases := AsXXXTestCases[bool]{
{
Name: name + ".error.asString",
Data: []byte{def.Int32},
Expected: false,
Error: def.ErrCanNotDecode,
MethodAsCustom: method,
},
{
Name: name + ".error.asInt",
Data: []byte{def.FixStr + 1, 'a', def.Str8},
Expected: false,
Error: def.ErrCanNotDecode,
MethodAsCustom: method,
},
{
Name: name + ".ok",
Data: []byte{def.FixStr + 1, 'a', def.PositiveFixIntMin + dv},
Expected: true,
MethodAsCustom: method,
},
}
testcases.Run(t)
}
v1 := new(map[string]int)
run(t, v1, 1)
tu.EqualMap(t, *v1, map[string]int{"a": 1})
v2 := new(map[string]int8)
run(t, v2, 2)
tu.EqualMap(t, *v2, map[string]int8{"a": 2})
v3 := new(map[string]int16)
run(t, v3, 3)
tu.EqualMap(t, *v3, map[string]int16{"a": 3})
v4 := new(map[string]int32)
run(t, v4, 4)
tu.EqualMap(t, *v4, map[string]int32{"a": 4})
v5 := new(map[string]int64)
run(t, v5, 5)
tu.EqualMap(t, *v5, map[string]int64{"a": 5})
}
func Test_asFixedMap_StringUint(t *testing.T) {
run := func(t *testing.T, v any, dv byte) {
method := func(d *decoder) (int, bool, error) {
rv := reflect.ValueOf(v)
return d.asFixedMap(rv.Elem(), 0, 1)
}
name := fmt.Sprintf("%T", v)
testcases := AsXXXTestCases[bool]{
{
Name: name + ".error.asString",
Data: []byte{def.Int32},
Expected: false,
Error: def.ErrCanNotDecode,
MethodAsCustom: method,
},
{
Name: name + ".error.asUint",
Data: []byte{def.FixStr + 1, 'a', def.Str8},
Expected: false,
Error: def.ErrCanNotDecode,
MethodAsCustom: method,
},
{
Name: name + ".ok",
Data: []byte{def.FixStr + 1, 'a', def.Uint8, dv},
Expected: true,
MethodAsCustom: method,
},
}
testcases.Run(t)
}
v1 := new(map[string]uint)
run(t, v1, 1)
tu.EqualMap(t, *v1, map[string]uint{"a": 1})
v2 := new(map[string]uint8)
run(t, v2, 2)
tu.EqualMap(t, *v2, map[string]uint8{"a": 2})
v3 := new(map[string]uint16)
run(t, v3, 3)
tu.EqualMap(t, *v3, map[string]uint16{"a": 3})
v4 := new(map[string]uint32)
run(t, v4, 4)
tu.EqualMap(t, *v4, map[string]uint32{"a": 4})
v5 := new(map[string]uint64)
run(t, v5, 5)
tu.EqualMap(t, *v5, map[string]uint64{"a": 5})
}
func Test_asFixedMap_StringFloat(t *testing.T) {
run := func(t *testing.T, v any, dv byte) {
method := func(d *decoder) (int, bool, error) {
rv := reflect.ValueOf(v)
return d.asFixedMap(rv.Elem(), 0, 1)
}
name := fmt.Sprintf("%T", v)
testcases := AsXXXTestCases[bool]{
{
Name: name + ".error.asString",
Data: []byte{def.Int32},
Expected: false,
Error: def.ErrCanNotDecode,
MethodAsCustom: method,
},
{
Name: name + ".error.asFloat",
Data: []byte{def.FixStr + 1, 'a', def.Str8},
Expected: false,
Error: def.ErrCanNotDecode,
MethodAsCustom: method,
},
{
Name: name + ".ok",
Data: []byte{def.FixStr + 1, 'a', def.Int16, 0, dv},
Expected: true,
MethodAsCustom: method,
},
}
testcases.Run(t)
}
v1 := new(map[string]float32)
run(t, v1, 1)
tu.EqualMap(t, *v1, map[string]float32{"a": 1})
v2 := new(map[string]float64)
run(t, v2, 2)
tu.EqualMap(t, *v2, map[string]float64{"a": 2})
}
func Test_asFixedMap_StringBool(t *testing.T) {
run := func(t *testing.T, v any, dv byte) {
method := func(d *decoder) (int, bool, error) {
rv := reflect.ValueOf(v)
return d.asFixedMap(rv.Elem(), 0, 1)
}
name := fmt.Sprintf("%T", v)
testcases := AsXXXTestCases[bool]{
{
Name: name + ".error.asString",
Data: []byte{def.Int32},
Expected: false,
Error: def.ErrCanNotDecode,
MethodAsCustom: method,
},
{
Name: name + ".error.asBool",
Data: []byte{def.FixStr + 1, 'a', def.Str8},
Expected: false,
Error: def.ErrCanNotDecode,
MethodAsCustom: method,
},
{
Name: name + ".ok",
Data: []byte{def.FixStr + 1, 'a', dv},
Expected: true,
MethodAsCustom: method,
},
}
testcases.Run(t)
}
v1 := new(map[string]bool)
run(t, v1, def.True)
tu.EqualMap(t, *v1, map[string]bool{"a": true})
}
func Test_asFixedMap_StringString(t *testing.T) {
run := func(t *testing.T, v any, dv byte) {
method := func(d *decoder) (int, bool, error) {
rv := reflect.ValueOf(v)
return d.asFixedMap(rv.Elem(), 0, 1)
}
name := fmt.Sprintf("%T", v)
testcases := AsXXXTestCases[bool]{
{
Name: name + ".error.asString",
Data: []byte{def.Int32},
Expected: false,
Error: def.ErrCanNotDecode,
MethodAsCustom: method,
},
{
Name: name + ".error.asString",
Data: []byte{def.FixStr + 1, 'a', def.Int32},
Expected: false,
Error: def.ErrCanNotDecode,
MethodAsCustom: method,
},
{
Name: name + ".ok",
Data: []byte{def.FixStr + 1, 'a', def.FixStr + 1, dv},
Expected: true,
MethodAsCustom: method,
},
}
testcases.Run(t)
}
v1 := new(map[string]string)
run(t, v1, 'b')
tu.EqualMap(t, *v1, map[string]string{"a": "b"})
}
func Test_asFixedMap_IntString(t *testing.T) {
run := func(t *testing.T, v any, dv byte) {
method := func(d *decoder) (int, bool, error) {
rv := reflect.ValueOf(v)
return d.asFixedMap(rv.Elem(), 0, 1)
}
name := fmt.Sprintf("%T", v)
testcases := AsXXXTestCases[bool]{
{
Name: name + ".error.asInt",
Data: []byte{def.Str8},
Expected: false,
Error: def.ErrCanNotDecode,
MethodAsCustom: method,
},
{
Name: name + ".error.asString",
Data: []byte{def.Int8, dv, def.Int32},
Expected: false,
Error: def.ErrCanNotDecode,
MethodAsCustom: method,
},
{
Name: name + ".ok",
Data: []byte{def.Int8, dv, def.FixStr + 1, 'b'},
Expected: true,
MethodAsCustom: method,
},
}
testcases.Run(t)
}
v1 := new(map[int]string)
run(t, v1, 1)
tu.EqualMap(t, *v1, map[int]string{1: "b"})
v2 := new(map[int8]string)
run(t, v2, 2)
tu.EqualMap(t, *v2, map[int8]string{int8(2): "b"})
v3 := new(map[int16]string)
run(t, v3, 3)
tu.EqualMap(t, *v3, map[int16]string{int16(3): "b"})
v4 := new(map[int32]string)
run(t, v4, 4)
tu.EqualMap(t, *v4, map[int32]string{int32(4): "b"})
v5 := new(map[int64]string)
run(t, v5, 5)
tu.EqualMap(t, *v5, map[int64]string{int64(5): "b"})
}
func Test_asFixedMap_IntBool(t *testing.T) {
run := func(t *testing.T, v any, dv byte) {
method := func(d *decoder) (int, bool, error) {
rv := reflect.ValueOf(v)
return d.asFixedMap(rv.Elem(), 0, 1)
}
name := fmt.Sprintf("%T", v)
testcases := AsXXXTestCases[bool]{
{
Name: name + ".error.asInt",
Data: []byte{def.Str8},
Expected: false,
Error: def.ErrCanNotDecode,
MethodAsCustom: method,
},
{
Name: name + ".error.asBool",
Data: []byte{def.Int8, dv, def.Int32},
Expected: false,
Error: def.ErrCanNotDecode,
MethodAsCustom: method,
},
{
Name: name + ".ok",
Data: []byte{def.Int8, dv, def.True},
Expected: true,
MethodAsCustom: method,
},
}
testcases.Run(t)
}
v1 := new(map[int]bool)
run(t, v1, 1)
tu.EqualMap(t, *v1, map[int]bool{1: true})
v2 := new(map[int8]bool)
run(t, v2, 2)
tu.EqualMap(t, *v2, map[int8]bool{int8(2): true})
v3 := new(map[int16]bool)
run(t, v3, 3)
tu.EqualMap(t, *v3, map[int16]bool{int16(3): true})
v4 := new(map[int32]bool)
run(t, v4, 4)
tu.EqualMap(t, *v4, map[int32]bool{int32(4): true})
v5 := new(map[int64]bool)
run(t, v5, 5)
tu.EqualMap(t, *v5, map[int64]bool{int64(5): true})
}
func Test_asFixedMap_UintString(t *testing.T) {
run := func(t *testing.T, v any, dv byte) {
method := func(d *decoder) (int, bool, error) {
rv := reflect.ValueOf(v)
return d.asFixedMap(rv.Elem(), 0, 1)
}
name := fmt.Sprintf("%T", v)
testcases := AsXXXTestCases[bool]{
{
Name: name + ".error.asUint",
Data: []byte{def.Str8},
Expected: false,
Error: def.ErrCanNotDecode,
MethodAsCustom: method,
},
{
Name: name + ".error.asString",
Data: []byte{def.Uint8, dv, def.Int32},
Expected: false,
Error: def.ErrCanNotDecode,
MethodAsCustom: method,
},
{
Name: name + ".ok",
Data: []byte{def.Uint8, dv, def.FixStr + 1, 'b'},
Expected: true,
MethodAsCustom: method,
},
}
testcases.Run(t)
}
v1 := new(map[uint]string)
run(t, v1, 1)
tu.EqualMap(t, *v1, map[uint]string{1: "b"})
v2 := new(map[uint8]string)
run(t, v2, 2)
tu.EqualMap(t, *v2, map[uint8]string{uint8(2): "b"})
v3 := new(map[uint16]string)
run(t, v3, 3)
tu.EqualMap(t, *v3, map[uint16]string{uint16(3): "b"})
v4 := new(map[uint32]string)
run(t, v4, 4)
tu.EqualMap(t, *v4, map[uint32]string{uint32(4): "b"})
v5 := new(map[uint64]string)
run(t, v5, 5)
tu.EqualMap(t, *v5, map[uint64]string{uint64(5): "b"})
}
func Test_asFixedMap_UintBool(t *testing.T) {
run := func(t *testing.T, v any, dv byte) {
method := func(d *decoder) (int, bool, error) {
rv := reflect.ValueOf(v)
return d.asFixedMap(rv.Elem(), 0, 1)
}
name := fmt.Sprintf("%T", v)
testcases := AsXXXTestCases[bool]{
{
Name: name + ".error.asUint",
Data: []byte{def.Str8},
Expected: false,
Error: def.ErrCanNotDecode,
MethodAsCustom: method,
},
{
Name: name + ".error.asBool",
Data: []byte{def.Uint8, dv, def.Int32},
Expected: false,
Error: def.ErrCanNotDecode,
MethodAsCustom: method,
},
{
Name: name + ".ok",
Data: []byte{def.Uint8, dv, def.True},
Expected: true,
MethodAsCustom: method,
},
}
testcases.Run(t)
}
v1 := new(map[uint]bool)
run(t, v1, 1)
tu.EqualMap(t, *v1, map[uint]bool{1: true})
v2 := new(map[uint8]bool)
run(t, v2, 2)
tu.EqualMap(t, *v2, map[uint8]bool{uint8(2): true})
v3 := new(map[uint16]bool)
run(t, v3, 3)
tu.EqualMap(t, *v3, map[uint16]bool{uint16(3): true})
v4 := new(map[uint32]bool)
run(t, v4, 4)
tu.EqualMap(t, *v4, map[uint32]bool{uint32(4): true})
v5 := new(map[uint64]bool)
run(t, v5, 5)
tu.EqualMap(t, *v5, map[uint64]bool{uint64(5): true})
}
func Test_asFixedMap_FloatString(t *testing.T) {
run := func(t *testing.T, v any, dv byte) {
method := func(d *decoder) (int, bool, error) {
rv := reflect.ValueOf(v)
return d.asFixedMap(rv.Elem(), 0, 1)
}
name := fmt.Sprintf("%T", v)
testcases := AsXXXTestCases[bool]{
{
Name: name + ".error.asFloat",
Data: []byte{def.Str8},
Expected: false,
Error: def.ErrCanNotDecode,
MethodAsCustom: method,
},
{
Name: name + ".error.asString",
Data: []byte{def.Uint8, dv, def.Int32},
Expected: false,
Error: def.ErrCanNotDecode,
MethodAsCustom: method,
},
{
Name: name + ".ok",
Data: []byte{def.Uint8, dv, def.FixStr + 1, 'b'},
Expected: true,
MethodAsCustom: method,
},
}
testcases.Run(t)
}
v1 := new(map[float32]string)
run(t, v1, 1)
tu.EqualMap(t, *v1, map[float32]string{1: "b"})
v2 := new(map[float64]string)
run(t, v2, 2)
tu.EqualMap(t, *v2, map[float64]string{2: "b"})
}
func Test_asFixedMap_FloatBool(t *testing.T) {
run := func(t *testing.T, v any, dv byte) {
method := func(d *decoder) (int, bool, error) {
rv := reflect.ValueOf(v)
return d.asFixedMap(rv.Elem(), 0, 1)
}
name := fmt.Sprintf("%T", v)
testcases := AsXXXTestCases[bool]{
{
Name: name + ".error.asFloat",
Data: []byte{def.Str8},
Expected: false,
Error: def.ErrCanNotDecode,
MethodAsCustom: method,
},
{
Name: name + ".error.asBool",
Data: []byte{def.Uint8, dv, def.Int32},
Expected: false,
Error: def.ErrCanNotDecode,
MethodAsCustom: method,
},
{
Name: name + ".ok",
Data: []byte{def.Uint8, dv, def.True},
Expected: true,
MethodAsCustom: method,
},
}
testcases.Run(t)
}
v1 := new(map[float32]bool)
run(t, v1, 1)
tu.EqualMap(t, *v1, map[float32]bool{1: true})
v2 := new(map[float64]bool)
run(t, v2, 2)
tu.EqualMap(t, *v2, map[float64]bool{2: true})
}
================================================
FILE: internal/decoding/nil.go
================================================
package decoding
import "github.com/shamaton/msgpack/v3/def"
func (d *decoder) isCodeNil(v byte) bool {
return def.Nil == v
}
================================================
FILE: internal/decoding/read.go
================================================
package decoding
import (
"github.com/shamaton/msgpack/v3/def"
)
func (d *decoder) readSize1(index int) (byte, int, error) {
rb := def.Byte1
if len(d.data) < index+rb {
return 0, 0, def.ErrTooShortBytes
}
return d.data[index], index + rb, nil
}
func (d *decoder) readSize2(index int) ([]byte, int, error) {
return d.readSizeN(index, def.Byte2)
}
func (d *decoder) readSize4(index int) ([]byte, int, error) {
return d.readSizeN(index, def.Byte4)
}
func (d *decoder) readSize8(index int) ([]byte, int, error) {
return d.readSizeN(index, def.Byte8)
}
func (d *decoder) readSizeN(index, n int) ([]byte, int, error) {
if len(d.data) < index+n {
return emptyBytes, 0, def.ErrTooShortBytes
}
return d.data[index : index+n], index + n, nil
}
================================================
FILE: internal/decoding/slice.go
================================================
package decoding
import (
"encoding/binary"
"reflect"
"github.com/shamaton/msgpack/v3/def"
)
var (
typeIntSlice = reflect.TypeOf([]int{})
typeInt8Slice = reflect.TypeOf([]int8{})
typeInt16Slice = reflect.TypeOf([]int16{})
typeInt32Slice = reflect.TypeOf([]int32{})
typeInt64Slice = reflect.TypeOf([]int64{})
typeUintSlice = reflect.TypeOf([]uint{})
typeUint8Slice = reflect.TypeOf([]uint8{})
typeUint16Slice = reflect.TypeOf([]uint16{})
typeUint32Slice = reflect.TypeOf([]uint32{})
typeUint64Slice = reflect.TypeOf([]uint64{})
typeFloat32Slice = reflect.TypeOf([]float32{})
typeFloat64Slice = reflect.TypeOf([]float64{})
typeStringSlice = reflect.TypeOf([]string{})
typeBoolSlice = reflect.TypeOf([]bool{})
)
func (d *decoder) isFixSlice(v byte) bool {
return def.FixArray <= v && v <= def.FixArray+0x0f
}
func (d *decoder) sliceLength(offset int, k reflect.Kind) (int, int, error) {
code, offset, err := d.readSize1(offset)
if err != nil {
return 0, 0, err
}
switch {
case d.isFixSlice(code):
return int(code - def.FixArray), offset, nil
case code == def.Array16:
bs, offset, err := d.readSize2(offset)
if err != nil {
return 0, 0, err
}
return int(binary.BigEndian.Uint16(bs)), offset, nil
case code == def.Array32:
bs, offset, err := d.readSize4(offset)
if err != nil {
return 0, 0, err
}
return int(binary.BigEndian.Uint32(bs)), offset, nil
}
return 0, 0, d.errorTemplate(code, k)
}
func (d *decoder) hasRequiredLeastSliceSize(offset, length int) error {
// minimum check (byte length)
if len(d.data[offset:]) < length {
return def.ErrLackDataLengthToSlice
}
return nil
}
func (d *decoder) asFixedSlice(rv reflect.Value, offset int, l int) (int, bool, error) {
t := rv.Type()
k := t.Elem().Kind()
switch t {
case typeIntSlice:
sli := make([]int, l)
for i := range sli {
v, o, err := d.asInt(offset, k)
if err != nil {
return 0, false, err
}
sli[i] = int(v)
offset = o
}
rv.Set(reflect.ValueOf(sli))
return offset, true, nil
case typeUintSlice:
sli := make([]uint, l)
for i := range sli {
v, o, err := d.asUint(offset, k)
if err != nil {
return 0, false, err
}
sli[i] = uint(v)
offset = o
}
rv.Set(reflect.ValueOf(sli))
return offset, true, nil
case typeStringSlice:
sli := make([]string, l)
for i := range sli {
v, o, err := d.asString(offset, k)
if err != nil {
return 0, false, err
}
sli[i] = v
offset = o
}
rv.Set(reflect.ValueOf(sli))
return offset, true, nil
case typeBoolSlice:
sli := make([]bool, l)
for i := range sli {
v, o, err := d.asBool(offset, k)
if err != nil {
return 0, false, err
}
sli[i] = v
offset = o
}
rv.Set(reflect.ValueOf(sli))
return offset, true, nil
case typeFloat32Slice:
sli := make([]float32, l)
for i := range sli {
v, o, err := d.asFloat32(offset, k)
if err != nil {
return 0, false, err
}
sli[i] = v
offset = o
}
rv.Set(reflect.ValueOf(sli))
return offset, true, nil
case typeFloat64Slice:
sli := make([]float64, l)
for i := range sli {
v, o, err := d.asFloat64(offset, k)
if err != nil {
return 0, false, err
}
sli[i] = v
offset = o
}
rv.Set(reflect.ValueOf(sli))
return offset, true, nil
case typeInt8Slice:
sli := make([]int8, l)
for i := range sli {
v, o, err := d.asInt(offset, k)
if err != nil {
return 0, false, err
}
sli[i] = int8(v)
offset = o
}
rv.Set(reflect.ValueOf(sli))
return offset, true, nil
case typeInt16Slice:
sli := make([]int16, l)
for i := range sli {
v, o, err := d.asInt(offset, k)
if err != nil {
return 0, false, err
}
sli[i] = int16(v)
offset = o
}
rv.Set(reflect.ValueOf(sli))
return offset, true, nil
case typeInt32Slice:
sli := make([]int32, l)
for i := range sli {
v, o, err := d.asInt(offset, k)
if err != nil {
return 0, false, err
}
sli[i] = int32(v)
offset = o
}
rv.Set(reflect.ValueOf(sli))
return offset, true, nil
case typeInt64Slice:
sli := make([]int64, l)
for i := range sli {
v, o, err := d.asInt(offset, k)
if err != nil {
return 0, false, err
}
sli[i] = v
offset = o
}
rv.Set(reflect.ValueOf(sli))
return offset, true, nil
case typeUint8Slice:
sli := make([]uint8, l)
for i := range sli {
v, o, err := d.asUint(offset, k)
if err != nil {
return 0, false, err
}
sli[i] = uint8(v)
offset = o
}
rv.Set(reflect.ValueOf(sli))
return offset, true, nil
case typeUint16Slice:
sli := make([]uint16, l)
for i := range sli {
v, o, err := d.asUint(offset, k)
if err != nil {
return 0, false, err
}
sli[i] = uint16(v)
offset = o
}
rv.Set(reflect.ValueOf(sli))
return offset, true, nil
case typeUint32Slice:
sli := make([]uint32, l)
for i := range sli {
v, o, err := d.asUint(offset, k)
if err != nil {
return 0, false, err
}
sli[i] = uint32(v)
offset = o
}
rv.Set(reflect.ValueOf(sli))
return offset, true, nil
case typeUint64Slice:
sli := make([]uint64, l)
for i := range sli {
v, o, err := d.asUint(offset, k)
if err != nil {
return 0, false, err
}
sli[i] = v
offset = o
}
rv.Set(reflect.ValueOf(sli))
return offset, true, nil
}
return offset, false, nil
}
================================================
FILE: internal/decoding/slice_test.go
================================================
package decoding
import (
"math"
"reflect"
"testing"
"github.com/shamaton/msgpack/v3/def"
tu "github.com/shamaton/msgpack/v3/internal/common/testutil"
)
func Test_sliceLength(t *testing.T) {
method := func(d *decoder) func(int, reflect.Kind) (int, int, error) {
return d.sliceLength
}
testcases := AsXXXTestCases[int]{
{
Name: "error.code",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "FixArray",
Data: []byte{def.FixArray + 3},
Expected: 3,
MethodAs: method,
},
{
Name: "Array16.error",
Data: []byte{def.Array16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Array16.ok",
Data: []byte{def.Array16, 0xff, 0xff},
Expected: math.MaxUint16,
MethodAs: method,
},
{
Name: "Array32.error",
Data: []byte{def.Array32},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Array32.ok",
Data: []byte{def.Array32, 0xff, 0xff, 0xff, 0xff},
Expected: math.MaxUint32,
MethodAs: method,
},
{
Name: "Unexpected",
Data: []byte{def.Nil},
Error: def.ErrCanNotDecode,
MethodAs: method,
},
}
testcases.Run(t)
}
func Test_asFixedSlice_Int(t *testing.T) {
run := func(t *testing.T, v any) {
method := func(d *decoder) (int, bool, error) {
rv := reflect.ValueOf(v)
return d.asFixedSlice(rv.Elem(), 0, 1)
}
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAsCustom: method,
},
{
Name: "ok",
Data: []byte{def.PositiveFixIntMin + 3},
Expected: true,
MethodAsCustom: method,
},
}
testcases.Run(t)
}
v1 := new([]int)
run(t, v1)
tu.EqualSlice(t, *v1, []int{3})
}
func Test_asFixedSlice_Int8(t *testing.T) {
run := func(t *testing.T, v any) {
method := func(d *decoder) (int, bool, error) {
rv := reflect.ValueOf(v)
return d.asFixedSlice(rv.Elem(), 0, 1)
}
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAsCustom: method,
},
{
Name: "ok",
Data: []byte{def.PositiveFixIntMin + 4},
Expected: true,
MethodAsCustom: method,
},
}
for _, tc := range testcases {
tc.Run(t)
}
}
v1 := new([]int8)
run(t, v1)
tu.EqualSlice(t, *v1, []int8{4})
}
func Test_asFixedSlice_Int16(t *testing.T) {
run := func(t *testing.T, v any) {
method := func(d *decoder) (int, bool, error) {
rv := reflect.ValueOf(v)
return d.asFixedSlice(rv.Elem(), 0, 1)
}
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAsCustom: method,
},
{
Name: "ok",
Data: []byte{def.PositiveFixIntMin + 5},
Expected: true,
MethodAsCustom: method,
},
}
testcases.Run(t)
}
v1 := new([]int16)
run(t, v1)
tu.EqualSlice(t, *v1, []int16{5})
}
func Test_asFixedSlice_Int32(t *testing.T) {
run := func(t *testing.T, v any) {
method := func(d *decoder) (int, bool, error) {
rv := reflect.ValueOf(v)
return d.asFixedSlice(rv.Elem(), 0, 1)
}
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAsCustom: method,
},
{
Name: "ok",
Data: []byte{def.PositiveFixIntMin + 6},
Expected: true,
MethodAsCustom: method,
},
}
testcases.Run(t)
}
v1 := new([]int32)
run(t, v1)
tu.EqualSlice(t, *v1, []int32{6})
}
func Test_asFixedSlice_Int64(t *testing.T) {
run := func(t *testing.T, v any) {
method := func(d *decoder) (int, bool, error) {
rv := reflect.ValueOf(v)
return d.asFixedSlice(rv.Elem(), 0, 1)
}
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAsCustom: method,
},
{
Name: "ok",
Data: []byte{def.PositiveFixIntMin + 7},
Expected: true,
MethodAsCustom: method,
},
}
testcases.Run(t)
}
v1 := new([]int64)
run(t, v1)
tu.EqualSlice(t, *v1, []int64{7})
}
func Test_asFixedSlice_Uint(t *testing.T) {
run := func(t *testing.T, v any) {
method := func(d *decoder) (int, bool, error) {
rv := reflect.ValueOf(v)
return d.asFixedSlice(rv.Elem(), 0, 1)
}
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAsCustom: method,
},
{
Name: "ok",
Data: []byte{def.PositiveFixIntMin + 5},
Expected: true,
MethodAsCustom: method,
},
}
testcases.Run(t)
}
v1 := new([]uint)
run(t, v1)
tu.EqualSlice(t, *v1, []uint{5})
}
func Test_asFixedSlice_Uint8(t *testing.T) {
run := func(t *testing.T, v any) {
method := func(d *decoder) (int, bool, error) {
rv := reflect.ValueOf(v)
return d.asFixedSlice(rv.Elem(), 0, 1)
}
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAsCustom: method,
},
{
Name: "ok",
Data: []byte{def.PositiveFixIntMin + 6},
Expected: true,
MethodAsCustom: method,
},
}
testcases.Run(t)
}
v1 := new([]uint8)
run(t, v1)
tu.EqualSlice(t, *v1, []uint8{6})
}
func Test_asFixedSlice_Uint16(t *testing.T) {
run := func(t *testing.T, v any) {
method := func(d *decoder) (int, bool, error) {
rv := reflect.ValueOf(v)
return d.asFixedSlice(rv.Elem(), 0, 1)
}
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAsCustom: method,
},
{
Name: "ok",
Data: []byte{def.PositiveFixIntMin + 7},
Expected: true,
MethodAsCustom: method,
},
}
testcases.Run(t)
}
v1 := new([]uint16)
run(t, v1)
tu.EqualSlice(t, *v1, []uint16{7})
}
func Test_asFixedSlice_Uint32(t *testing.T) {
run := func(t *testing.T, v any) {
method := func(d *decoder) (int, bool, error) {
rv := reflect.ValueOf(v)
return d.asFixedSlice(rv.Elem(), 0, 1)
}
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAsCustom: method,
},
{
Name: "ok",
Data: []byte{def.PositiveFixIntMin + 8},
Expected: true,
MethodAsCustom: method,
},
}
testcases.Run(t)
}
v1 := new([]uint32)
run(t, v1)
tu.EqualSlice(t, *v1, []uint32{8})
}
func Test_asFixedSlice_Uint64(t *testing.T) {
run := func(t *testing.T, v any) {
method := func(d *decoder) (int, bool, error) {
rv := reflect.ValueOf(v)
return d.asFixedSlice(rv.Elem(), 0, 1)
}
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAsCustom: method,
},
{
Name: "ok",
Data: []byte{def.PositiveFixIntMin + 9},
Expected: true,
MethodAsCustom: method,
},
}
testcases.Run(t)
}
v1 := new([]uint64)
run(t, v1)
tu.EqualSlice(t, *v1, []uint64{9})
}
func Test_asFixedSlice_Float32(t *testing.T) {
run := func(t *testing.T, v any) {
method := func(d *decoder) (int, bool, error) {
rv := reflect.ValueOf(v)
return d.asFixedSlice(rv.Elem(), 0, 1)
}
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAsCustom: method,
},
{
Name: "ok",
Data: []byte{def.Float32, 63, 128, 0, 0},
Expected: true,
MethodAsCustom: method,
},
}
testcases.Run(t)
}
v1 := new([]float32)
run(t, v1)
tu.EqualSlice(t, *v1, []float32{1})
}
func Test_asFixedSlice_Float64(t *testing.T) {
run := func(t *testing.T, v any) {
method := func(d *decoder) (int, bool, error) {
rv := reflect.ValueOf(v)
return d.asFixedSlice(rv.Elem(), 0, 1)
}
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAsCustom: method,
},
{
Name: "ok",
Data: []byte{def.Float64, 63, 240, 0, 0, 0, 0, 0, 0},
Expected: true,
MethodAsCustom: method,
},
}
testcases.Run(t)
}
v1 := new([]float64)
run(t, v1)
tu.EqualSlice(t, *v1, []float64{1})
}
func Test_asFixedSlice_String(t *testing.T) {
run := func(t *testing.T, v any) {
method := func(d *decoder) (int, bool, error) {
rv := reflect.ValueOf(v)
return d.asFixedSlice(rv.Elem(), 0, 2)
}
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAsCustom: method,
},
{
Name: "ok",
Data: []byte{def.FixStr + 1, 'a', def.FixStr + 1, 'b'},
Expected: true,
MethodAsCustom: method,
},
}
testcases.Run(t)
}
v1 := new([]string)
run(t, v1)
tu.EqualSlice(t, *v1, []string{"a", "b"})
}
func Test_asFixedSlice_Bool(t *testing.T) {
run := func(t *testing.T, v any) {
method := func(d *decoder) (int, bool, error) {
rv := reflect.ValueOf(v)
return d.asFixedSlice(rv.Elem(), 0, 1)
}
testcases := AsXXXTestCases[bool]{
{
Name: "error",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAsCustom: method,
},
{
Name: "ok",
Data: []byte{def.True},
Expected: true,
MethodAsCustom: method,
},
}
testcases.Run(t)
}
v1 := new([]bool)
run(t, v1)
tu.EqualSlice(t, *v1, []bool{true})
}
================================================
FILE: internal/decoding/string.go
================================================
package decoding
import (
"encoding/binary"
"reflect"
"github.com/shamaton/msgpack/v3/def"
)
var (
emptyString = ""
emptyBytes = []byte{}
)
func (d *decoder) isCodeString(code byte) bool {
return d.isFixString(code) || code == def.Str8 || code == def.Str16 || code == def.Str32
}
func (d *decoder) isFixString(v byte) bool {
return def.FixStr <= v && v <= def.FixStr+0x1f
}
func (d *decoder) stringByteLength(offset int, k reflect.Kind) (int, int, error) {
code, offset, err := d.readSize1(offset)
if err != nil {
return 0, 0, err
}
if def.FixStr <= code && code <= def.FixStr+0x1f {
l := int(code - def.FixStr)
return l, offset, nil
} else if code == def.Str8 {
b, offset, err := d.readSize1(offset)
if err != nil {
return 0, 0, err
}
return int(b), offset, nil
} else if code == def.Str16 {
b, offset, err := d.readSize2(offset)
if err != nil {
return 0, 0, err
}
return int(binary.BigEndian.Uint16(b)), offset, nil
} else if code == def.Str32 {
b, offset, err := d.readSize4(offset)
if err != nil {
return 0, 0, err
}
return int(binary.BigEndian.Uint32(b)), offset, nil
} else if code == def.Nil {
return 0, offset, nil
}
return 0, 0, d.errorTemplate(code, k)
}
func (d *decoder) asString(offset int, k reflect.Kind) (string, int, error) {
bs, offset, err := d.asStringByte(offset, k)
if err != nil {
return emptyString, 0, err
}
return string(bs), offset, nil
}
func (d *decoder) asStringByte(offset int, k reflect.Kind) ([]byte, int, error) {
l, offset, err := d.stringByteLength(offset, k)
if err != nil {
return emptyBytes, 0, err
}
return d.asStringByteByLength(offset, l, k)
}
func (d *decoder) asStringByteByLength(offset int, l int, k reflect.Kind) ([]byte, int, error) {
if l < 1 {
return emptyBytes, offset, nil
}
return d.readSizeN(offset, l)
}
================================================
FILE: internal/decoding/string_test.go
================================================
package decoding
import (
"math"
"reflect"
"testing"
"github.com/shamaton/msgpack/v3/def"
)
func Test_stringByteLength(t *testing.T) {
method := func(d *decoder) func(int, reflect.Kind) (int, int, error) {
return d.stringByteLength
}
testcases := AsXXXTestCases[int]{
{
Name: "error.code",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "FixStr.ok",
Data: []byte{def.FixStr + 1},
Expected: 1,
MethodAs: method,
},
{
Name: "Str8.error",
Data: []byte{def.Str8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Str8.ok",
Data: []byte{def.Str8, 0xff},
Expected: math.MaxUint8,
MethodAs: method,
},
{
Name: "Str16.error",
Data: []byte{def.Str16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Str16.ok",
Data: []byte{def.Str16, 0xff, 0xff},
Expected: math.MaxUint16,
MethodAs: method,
},
{
Name: "Str32.error",
Data: []byte{def.Str32},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Str32.ok",
Data: []byte{def.Str32, 0xff, 0xff, 0xff, 0xff},
Expected: math.MaxUint32,
MethodAs: method,
},
{
Name: "Nil",
Data: []byte{def.Nil},
Expected: 0,
MethodAs: method,
},
{
Name: "Unexpected",
Data: []byte{def.Array16},
Error: def.ErrCanNotDecode,
MethodAs: method,
},
}
testcases.Run(t)
}
func Test_asString(t *testing.T) {
method := func(d *decoder) func(int, reflect.Kind) (string, int, error) {
return d.asString
}
testcases := AsXXXTestCases[string]{
{
Name: "error.string",
Data: []byte{def.FixStr + 1},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.FixStr + 1, 'a'},
Expected: "a",
MethodAs: method,
},
}
testcases.Run(t)
}
func Test_asStringByte(t *testing.T) {
method := func(d *decoder) func(int, reflect.Kind) ([]byte, int, error) {
return d.asStringByte
}
testcases := AsXXXTestCases[[]byte]{
{
Name: "error",
Data: []byte{def.FixStr + 1},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.FixStr + 1, 'a'},
Expected: []byte{'a'},
MethodAs: method,
},
}
testcases.Run(t)
}
================================================
FILE: internal/decoding/struct.go
================================================
package decoding
import (
"encoding/binary"
"reflect"
"sync"
"github.com/shamaton/msgpack/v3/def"
)
type structCacheTypeMap struct {
keys [][]byte
// fast path detection
hasEmbedded bool
// fast path (hasEmbedded == false): direct field access
simpleIndexes []int
// embedded path (hasEmbedded == true): path-based access
indexes [][]int // field path (support for embedded structs)
}
type structCacheTypeArray struct {
// fast path detection
hasEmbedded bool
// fast path (hasEmbedded == false): direct field access
simpleIndexes []int
// embedded path (hasEmbedded == true): path-based access
indexes [][]int // field path (support for embedded structs)
}
// struct cache map
var (
mapSCTM = sync.Map{}
mapSCTA = sync.Map{}
)
// getFieldByPath returns the field value by following the path of indices.
// The bool indicates whether the path was reachable (no nil pointer in the path).
func getFieldByPath(rv reflect.Value, path []int, allowAlloc bool) (reflect.Value, bool) {
for _, idx := range path {
// Handle pointer indirection if needed
if rv.Kind() == reflect.Ptr {
if rv.IsNil() {
if !allowAlloc {
return reflect.Value{}, false
}
// Allocate new value if pointer is nil
rv.Set(reflect.New(rv.Type().Elem()))
}
rv = rv.Elem()
}
rv = rv.Field(idx)
}
return rv, true
}
func (d *decoder) setStruct(rv reflect.Value, offset int, k reflect.Kind) (int, error) {
/*
if d.isDateTime(offset) {
dt, offset, err := d.asDateTime(offset, k)
if err != nil {
return 0, err
}
rv.Set(reflect.ValueOf(dt))
return offset, nil
}
*/
isExt, _, err := d.extEndOffset(offset)
if err != nil {
return 0, err
}
if isExt {
for i := range extCoders {
if extCoders[i].IsType(offset, &d.data) {
v, offset, err := extCoders[i].AsValue(offset, k, &d.data)
if err != nil {
return 0, err
}
// Validate that the receptacle is of the right value type.
if rv.Type() == reflect.TypeOf(v) {
rv.Set(reflect.ValueOf(v))
return offset, nil
}
}
}
}
if d.asArray {
return d.setStructFromArray(rv, offset, k)
}
return d.setStructFromMap(rv, offset, k)
}
func (d *decoder) setStructFromArray(rv reflect.Value, offset int, k reflect.Kind) (int, error) {
// get length
l, o, err := d.sliceLength(offset, k)
if err != nil {
return 0, err
}
if err = d.hasRequiredLeastSliceSize(o, l); err != nil {
return 0, err
}
// find or create reference
var scta *structCacheTypeArray
cache, findCache := mapSCTA.Load(rv.Type())
if !findCache {
scta = &structCacheTypeArray{}
fields := d.CollectFields(rv.Type(), nil)
// detect embedded fields
hasEmbedded := false
for _, f := range fields {
if len(f.Path) > 1 || len(f.OmitPaths) > 0 {
hasEmbedded = true
break
}
}
scta.hasEmbedded = hasEmbedded
for _, field := range fields {
if hasEmbedded {
scta.indexes = append(scta.indexes, field.Path)
} else {
scta.simpleIndexes = append(scta.simpleIndexes, field.Path[0])
}
}
mapSCTA.Store(rv.Type(), scta)
} else {
scta = cache.(*structCacheTypeArray)
}
// set value
if scta.hasEmbedded {
for i := 0; i < l; i++ {
if i < len(scta.indexes) {
allowAlloc := !d.isCodeNil(d.data[o])
fieldValue, ok := getFieldByPath(rv, scta.indexes[i], allowAlloc)
if ok {
o, err = d.decode(fieldValue, o)
if err != nil {
return 0, err
}
} else {
o, err = d.jumpOffset(o)
if err != nil {
return 0, err
}
}
} else {
o, err = d.jumpOffset(o)
if err != nil {
return 0, err
}
}
}
} else {
for i := 0; i < l; i++ {
if i < len(scta.simpleIndexes) {
o, err = d.decode(rv.Field(scta.simpleIndexes[i]), o)
if err != nil {
return 0, err
}
} else {
o, err = d.jumpOffset(o)
if err != nil {
return 0, err
}
}
}
}
return o, nil
}
func (d *decoder) setStructFromMap(rv reflect.Value, offset int, k reflect.Kind) (int, error) {
// get length
l, o, err := d.mapLength(offset, k)
if err != nil {
return 0, err
}
if err = d.hasRequiredLeastMapSize(o, l); err != nil {
return 0, err
}
var sctm *structCacheTypeMap
cache, cacheFind := mapSCTM.Load(rv.Type())
if !cacheFind {
sctm = &structCacheTypeMap{}
fields := d.CollectFields(rv.Type(), nil)
// detect embedded fields
hasEmbedded := false
for _, f := range fields {
if len(f.Path) > 1 || len(f.OmitPaths) > 0 {
hasEmbedded = true
break
}
}
sctm.hasEmbedded = hasEmbedded
for _, field := range fields {
sctm.keys = append(sctm.keys, []byte(field.Name))
if hasEmbedded {
sctm.indexes = append(sctm.indexes, field.Path)
} else {
sctm.simpleIndexes = append(sctm.simpleIndexes, field.Path[0])
}
}
mapSCTM.Store(rv.Type(), sctm)
} else {
sctm = cache.(*structCacheTypeMap)
}
if sctm.hasEmbedded {
for i := 0; i < l; i++ {
dataKey, o2, err := d.asStringByte(o, k)
if err != nil {
return 0, err
}
fieldPath := []int(nil)
for keyIndex, keyBytes := range sctm.keys {
if len(keyBytes) != len(dataKey) {
continue
}
found := true
for dataIndex := range dataKey {
if dataKey[dataIndex] != keyBytes[dataIndex] {
found = false
break
}
}
if found {
fieldPath = sctm.indexes[keyIndex]
break
}
}
if fieldPath != nil {
allowAlloc := !d.isCodeNil(d.data[o2])
fieldValue, ok := getFieldByPath(rv, fieldPath, allowAlloc)
if ok {
o2, err = d.decode(fieldValue, o2)
if err != nil {
return 0, err
}
} else {
o2, err = d.jumpOffset(o2)
if err != nil {
return 0, err
}
}
} else {
o2, err = d.jumpOffset(o2)
if err != nil {
return 0, err
}
}
o = o2
}
} else {
for i := 0; i < l; i++ {
dataKey, o2, err := d.asStringByte(o, k)
if err != nil {
return 0, err
}
fieldIndex := -1
for keyIndex, keyBytes := range sctm.keys {
if len(keyBytes) != len(dataKey) {
continue
}
found := true
for dataIndex := range dataKey {
if dataKey[dataIndex] != keyBytes[dataIndex] {
found = false
break
}
}
if found {
fieldIndex = sctm.simpleIndexes[keyIndex]
break
}
}
if fieldIndex >= 0 {
o2, err = d.decode(rv.Field(fieldIndex), o2)
if err != nil {
return 0, err
}
} else {
o2, err = d.jumpOffset(o2)
if err != nil {
return 0, err
}
}
o = o2
}
}
return o, nil
}
func (d *decoder) jumpOffset(offset int) (int, error) {
code, offset, err := d.readSize1(offset)
if err != nil {
return 0, err
}
switch {
case code == def.True, code == def.False, code == def.Nil:
// do nothing
case d.isPositiveFixNum(code) || d.isNegativeFixNum(code):
// do nothing
case code == def.Uint8, code == def.Int8:
offset += def.Byte1
case code == def.Uint16, code == def.Int16:
offset += def.Byte2
case code == def.Uint32, code == def.Int32, code == def.Float32:
offset += def.Byte4
case code == def.Uint64, code == def.Int64, code == def.Float64:
offset += def.Byte8
case d.isFixString(code):
offset += int(code - def.FixStr)
case code == def.Str8, code == def.Bin8:
b, o, err := d.readSize1(offset)
if err != nil {
return 0, err
}
o += int(b)
offset = o
case code == def.Str16, code == def.Bin16:
bs, o, err := d.readSize2(offset)
if err != nil {
return 0, err
}
o += int(binary.BigEndian.Uint16(bs))
offset = o
case code == def.Str32, code == def.Bin32:
bs, o, err := d.readSize4(offset)
if err != nil {
return 0, err
}
o += int(binary.BigEndian.Uint32(bs))
offset = o
case d.isFixSlice(code):
l := int(code - def.FixArray)
for i := 0; i < l; i++ {
offset, err = d.jumpOffset(offset)
if err != nil {
return 0, err
}
}
case code == def.Array16:
bs, o, err := d.readSize2(offset)
if err != nil {
return 0, err
}
l := int(binary.BigEndian.Uint16(bs))
for i := 0; i < l; i++ {
o, err = d.jumpOffset(o)
if err != nil {
return 0, err
}
}
offset = o
case code == def.Array32:
bs, o, err := d.readSize4(offset)
if err != nil {
return 0, err
}
l := int(binary.BigEndian.Uint32(bs))
for i := 0; i < l; i++ {
o, err = d.jumpOffset(o)
if err != nil {
return 0, err
}
}
offset = o
case d.isFixMap(code):
l := int(code - def.FixMap)
for i := 0; i < l*2; i++ {
offset, err = d.jumpOffset(offset)
if err != nil {
return 0, err
}
}
case code == def.Map16:
bs, o, err := d.readSize2(offset)
if err != nil {
return 0, err
}
l := int(binary.BigEndian.Uint16(bs))
for i := 0; i < l*2; i++ {
o, err = d.jumpOffset(o)
if err != nil {
return 0, err
}
}
offset = o
case code == def.Map32:
bs, o, err := d.readSize4(offset)
if err != nil {
return 0, err
}
l := int(binary.BigEndian.Uint32(bs))
for i := 0; i < l*2; i++ {
o, err = d.jumpOffset(o)
if err != nil {
return 0, err
}
}
offset = o
default:
isExt, o, err := d.extEndOffsetWithCode(code, offset)
if err != nil {
return 0, err
}
if isExt {
offset = o
}
}
return offset, nil
}
================================================
FILE: internal/decoding/struct_test.go
================================================
package decoding
import (
"reflect"
"testing"
"time"
"github.com/shamaton/msgpack/v3/def"
tu "github.com/shamaton/msgpack/v3/internal/common/testutil"
)
func Test_setStruct_ext(t *testing.T) {
run := func(t *testing.T, rv reflect.Value) {
method := func(d *decoder) func(int, reflect.Kind) (any, int, error) {
return func(offset int, k reflect.Kind) (any, int, error) {
o, err := d.setStruct(rv, offset, k)
return nil, o, err
}
}
testcases := AsXXXTestCases[any]{
{
Name: "ExtCoder.error",
Data: []byte{def.Fixext1, 3, 0},
Error: ErrTestExtDecoder,
MethodAs: method,
},
{
Name: "ExtCoder.ok",
Data: []byte{def.Fixext4, 255, 0, 0, 0, 0},
MethodAs: method,
},
}
testcases.Run(t)
}
ngDec := testExt2Decoder{}
AddExtDecoder(&ngDec)
defer RemoveExtDecoder(&ngDec)
v1 := new(time.Time)
run(t, reflect.ValueOf(v1).Elem())
tu.EqualEqualer(t, *v1, time.Unix(0, 0))
}
func Test_setStructFromMap(t *testing.T) {
run := func(t *testing.T, rv reflect.Value) {
method := func(d *decoder) func(int, reflect.Kind) (any, int, error) {
return func(offset int, k reflect.Kind) (any, int, error) {
o, err := d.setStructFromMap(rv, offset, k)
return nil, o, err
}
}
testcases := AsXXXTestCases[any]{
{
Name: "error.length",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "error.required",
Data: []byte{def.Map16, 0, 1},
Error: def.ErrLackDataLengthToMap,
MethodAs: method,
},
{
Name: "error.key",
Data: []byte{def.Map16, 0, 1, def.Str16, 0},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "error.decode",
Data: []byte{def.Map16, 0, 1, def.FixStr + 1, 'v', def.Array16},
Error: def.ErrCanNotDecode,
MethodAs: method,
},
{
Name: "error.jump",
Data: []byte{def.Map16, 0, 2, def.FixStr + 1, 'v', 0, def.FixStr + 1, 'b'},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.Map16, 0, 1, def.FixStr + 1, 'v', def.PositiveFixIntMin + 7},
MethodAs: method,
},
}
testcases.Run(t)
}
type st struct {
V int `msgpack:"v"`
}
v1 := new(st)
run(t, reflect.ValueOf(v1).Elem())
tu.Equal(t, v1.V, 7)
}
func Test_setStructFromArray(t *testing.T) {
run := func(t *testing.T, rv reflect.Value) {
method := func(d *decoder) func(int, reflect.Kind) (any, int, error) {
return func(offset int, k reflect.Kind) (any, int, error) {
o, err := d.setStructFromArray(rv, offset, k)
return nil, o, err
}
}
testcases := AsXXXTestCases[any]{
{
Name: "error.length",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "error.required",
Data: []byte{def.Array16, 0, 1},
Error: def.ErrLackDataLengthToSlice,
MethodAs: method,
},
{
Name: "error.decode",
Data: []byte{def.Array16, 0, 1, def.Array16},
Error: def.ErrCanNotDecode,
MethodAs: method,
},
{
Name: "error.jump",
Data: []byte{def.Array16, 0, 2, 0, def.Array16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.Array16, 0, 1, def.PositiveFixIntMin + 8},
MethodAs: method,
},
}
testcases.Run(t)
}
type st struct {
V int `msgpack:"v"`
}
v1 := new(st)
run(t, reflect.ValueOf(v1).Elem())
tu.Equal(t, v1.V, 8)
}
func Test_jumpOffset(t *testing.T) {
method := func(d *decoder) func(int, reflect.Kind) (any, int, error) {
return func(offset int, _ reflect.Kind) (any, int, error) {
o, err := d.jumpOffset(offset)
return nil, o, err
}
}
testcases := AsXXXTestCases[any]{
{
Name: "error.read.code",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "True.ok",
Data: []byte{def.True},
MethodAs: method,
},
{
Name: "False.ok",
Data: []byte{def.False},
MethodAs: method,
},
{
Name: "PositiveFixNum.ok",
Data: []byte{def.PositiveFixIntMin + 1},
MethodAs: method,
},
{
Name: "NegativeFixNum.ok",
Data: []byte{0xf0},
MethodAs: method,
},
{
Name: "Uint8.ok",
Data: []byte{def.Uint8, 1},
MethodAs: method,
},
{
Name: "Int8.ok",
Data: []byte{def.Int8, 1},
MethodAs: method,
},
{
Name: "Uint16.ok",
Data: []byte{def.Uint16, 0, 1},
MethodAs: method,
},
{
Name: "Int16.ok",
Data: []byte{def.Int16, 0, 1},
MethodAs: method,
},
{
Name: "Uint32.ok",
Data: []byte{def.Uint32, 0, 0, 0, 0},
MethodAs: method,
},
{
Name: "Int32.ok",
Data: []byte{def.Int32, 0, 0, 0, 0},
MethodAs: method,
},
{
Name: "Float32.ok",
Data: []byte{def.Float32, 0, 0, 0, 0},
MethodAs: method,
},
{
Name: "Uint64.ok",
Data: []byte{def.Uint64, 0, 0, 0, 0, 0, 0, 0, 0},
MethodAs: method,
},
{
Name: "Int64.ok",
Data: []byte{def.Int64, 0, 0, 0, 0, 0, 0, 0, 0},
MethodAs: method,
},
{
Name: "Float64.ok",
Data: []byte{def.Float64, 0, 0, 0, 0, 0, 0, 0, 0},
MethodAs: method,
},
{
Name: "FixStr.ok",
Data: []byte{def.FixStr + 1, 0},
MethodAs: method,
},
{
Name: "Str8.ng.length",
Data: []byte{def.Str8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Str8.ok",
Data: []byte{def.Str8, 1, 'a'},
MethodAs: method,
},
{
Name: "Bin8.ng.length",
Data: []byte{def.Bin8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Bin8.ok",
Data: []byte{def.Bin8, 1, 'a'},
MethodAs: method,
},
{
Name: "Str16.ng.length",
Data: []byte{def.Str16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Str16.ok",
Data: []byte{def.Str16, 0, 1, 'a'},
MethodAs: method,
},
{
Name: "Bin16.ng.length",
Data: []byte{def.Bin16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Bin16.ok",
Data: []byte{def.Bin16, 0, 1, 'a'},
MethodAs: method,
},
{
Name: "Str32.ng.length",
Data: []byte{def.Str32},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Str32.ok",
Data: []byte{def.Str32, 0, 0, 0, 1, 'a'},
MethodAs: method,
},
{
Name: "Bin32.ng.length",
Data: []byte{def.Bin32},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Bin32.ok",
Data: []byte{def.Bin32, 0, 0, 0, 1, 'a'},
MethodAs: method,
},
{
Name: "FixSlice.ng",
Data: []byte{def.FixArray + 1},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "FixSlice.ok",
Data: []byte{def.FixArray + 1, 0xc1},
MethodAs: method,
},
{
Name: "Array16.ng.len",
Data: []byte{def.Array16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Array16.ng.jump",
Data: []byte{def.Array16, 0, 1},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Array16.ok",
Data: []byte{def.Array16, 0, 1, 0xc1},
MethodAs: method,
},
{
Name: "Array32.ng.len",
Data: []byte{def.Array32},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Array32.ng.jump",
Data: []byte{def.Array32, 0, 0, 0, 1},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Array32.ok",
Data: []byte{def.Array32, 0, 0, 0, 1, 0xc1},
MethodAs: method,
},
{
Name: "FixMap.ng",
Data: []byte{def.FixMap + 1},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "FixMap.ok",
Data: []byte{def.FixMap + 1, 0xc1, 0xc1},
MethodAs: method,
},
{
Name: "Map16.ng.len",
Data: []byte{def.Map16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Map16.ng.jump",
Data: []byte{def.Map16, 0, 1},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Map16.ok",
Data: []byte{def.Map16, 0, 1, 0xc1, 0xc1},
MethodAs: method,
},
{
Name: "Map32.ng.len",
Data: []byte{def.Map32},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Map32.ng.jump",
Data: []byte{def.Map32, 0, 0, 0, 1},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Map32.ok",
Data: []byte{def.Map32, 0, 0, 0, 1, 0xc1, 0xc1},
MethodAs: method,
},
{
Name: "Fixext1.ng",
Data: []byte{def.Fixext1},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Fixext1.ok",
Data: []byte{def.Fixext1, 0, 0},
MethodAs: method,
},
{
Name: "Fixext2.ng",
Data: []byte{def.Fixext2},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Fixext2.ok",
Data: []byte{def.Fixext2, 0, 0, 0},
MethodAs: method,
},
{
Name: "Fixext4.ng",
Data: []byte{def.Fixext4},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Fixext4.ok",
Data: []byte{def.Fixext4, 0, 0, 0, 0, 0},
MethodAs: method,
},
{
Name: "Fixext8.ng",
Data: []byte{def.Fixext8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Fixext8.ok",
Data: []byte{def.Fixext8, 0, 0, 0, 0, 0, 0, 0, 0, 0},
MethodAs: method,
},
{
Name: "Fixext16.ng",
Data: []byte{def.Fixext16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Fixext16.ok",
Data: []byte{def.Fixext16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
MethodAs: method,
},
{
Name: "Ext8.ng.size",
Data: []byte{def.Ext8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Ext8.ok",
Data: []byte{def.Ext8, 1, 0, 0},
MethodAs: method,
},
{
Name: "Ext16.ng.size",
Data: []byte{def.Ext16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Ext16.ok",
Data: []byte{def.Ext16, 0, 1, 0, 0},
MethodAs: method,
},
{
Name: "Ext32.ng.size",
Data: []byte{def.Ext32},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Ext32.ok",
Data: []byte{def.Ext32, 0, 0, 0, 1, 0, 0},
MethodAs: method,
},
{
Name: "Unexpected",
Data: []byte{0xc1},
MethodAs: method,
},
}
testcases.Run(t)
}
================================================
FILE: internal/decoding/uint.go
================================================
package decoding
import (
"encoding/binary"
"reflect"
"github.com/shamaton/msgpack/v3/def"
)
func (d *decoder) asUint(offset int, k reflect.Kind) (uint64, int, error) {
code, _, err := d.readSize1(offset)
if err != nil {
return 0, 0, err
}
switch {
case d.isPositiveFixNum(code):
b, offset, err := d.readSize1(offset)
if err != nil {
return 0, 0, err
}
return uint64(b), offset, nil
case d.isNegativeFixNum(code):
b, offset, err := d.readSize1(offset)
if err != nil {
return 0, 0, err
}
return uint64(int8(b)), offset, nil
case code == def.Uint8:
offset++
b, offset, err := d.readSize1(offset)
if err != nil {
return 0, 0, err
}
return uint64(uint8(b)), offset, nil
case code == def.Int8:
offset++
b, offset, err := d.readSize1(offset)
if err != nil {
return 0, 0, err
}
return uint64(int8(b)), offset, nil
case code == def.Uint16:
offset++
bs, offset, err := d.readSize2(offset)
if err != nil {
return 0, 0, err
}
v := binary.BigEndian.Uint16(bs)
return uint64(v), offset, nil
case code == def.Int16:
offset++
bs, offset, err := d.readSize2(offset)
if err != nil {
return 0, 0, err
}
v := int16(binary.BigEndian.Uint16(bs))
return uint64(v), offset, nil
case code == def.Uint32:
offset++
bs, offset, err := d.readSize4(offset)
if err != nil {
return 0, 0, err
}
v := binary.BigEndian.Uint32(bs)
return uint64(v), offset, nil
case code == def.Int32:
offset++
bs, offset, err := d.readSize4(offset)
if err != nil {
return 0, 0, err
}
v := int32(binary.BigEndian.Uint32(bs))
return uint64(v), offset, nil
case code == def.Uint64:
offset++
bs, offset, err := d.readSize8(offset)
if err != nil {
return 0, 0, err
}
return binary.BigEndian.Uint64(bs), offset, nil
case code == def.Int64:
offset++
bs, offset, err := d.readSize8(offset)
if err != nil {
return 0, 0, err
}
return binary.BigEndian.Uint64(bs), offset, nil
case code == def.Nil:
offset++
return 0, offset, nil
}
return 0, 0, d.errorTemplate(code, k)
}
================================================
FILE: internal/decoding/uint_test.go
================================================
package decoding
import (
"math"
"reflect"
"testing"
"github.com/shamaton/msgpack/v3/def"
)
func Test_asUint(t *testing.T) {
method := func(d *decoder) func(int, reflect.Kind) (uint64, int, error) {
return d.asUint
}
testcases := AsXXXTestCases[uint64]{
{
Name: "error.code",
Data: []byte{},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "PositiveFixNum.ok",
Data: []byte{def.PositiveFixIntMin + 1},
Expected: uint64(1),
MethodAs: method,
},
{
Name: "Uint8.error",
Data: []byte{def.Uint8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Uint8.ok",
Data: []byte{def.Uint8, 1},
Expected: uint64(1),
MethodAs: method,
},
{
Name: "Uint16.error",
Data: []byte{def.Uint16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Uint16.ok",
Data: []byte{def.Uint16, 0, 1},
Expected: uint64(1),
MethodAs: method,
},
{
Name: "Uint32.error",
Data: []byte{def.Uint32},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Uint32.ok",
Data: []byte{def.Uint32, 0, 0, 0, 1},
Expected: uint64(1),
MethodAs: method,
},
{
Name: "Uint64.error",
Data: []byte{def.Uint64},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Uint64.ok",
Data: []byte{def.Uint64, 0, 0, 0, 0, 0, 0, 0, 1},
Expected: uint64(1),
MethodAs: method,
},
{
Name: "NegativeFixNum.ok",
Data: []byte{0xff},
Expected: uint64(math.MaxUint64),
MethodAs: method,
},
{
Name: "Int8.error",
Data: []byte{def.Int8},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Int8.ok",
Data: []byte{def.Int8, 0xff},
Expected: uint64(math.MaxUint64),
MethodAs: method,
},
{
Name: "Int16.error",
Data: []byte{def.Int16},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Int16.ok",
Data: []byte{def.Int16, 0xff, 0xff},
Expected: uint64(math.MaxUint64),
MethodAs: method,
},
{
Name: "Int32.error",
Data: []byte{def.Int32},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Int32.ok",
Data: []byte{def.Int32, 0xff, 0xff, 0xff, 0xff},
Expected: uint64(math.MaxUint64),
MethodAs: method,
},
{
Name: "Int64.error",
Data: []byte{def.Int64},
Error: def.ErrTooShortBytes,
MethodAs: method,
},
{
Name: "Int64.ok",
Data: []byte{def.Int64, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
Expected: uint64(math.MaxUint64),
MethodAs: method,
},
{
Name: "Nil.ok",
Data: []byte{def.Nil},
Expected: uint64(0),
MethodAs: method,
},
{
Name: "Unexpected",
Data: []byte{def.Str8},
Error: def.ErrCanNotDecode,
MethodAs: method,
},
}
testcases.Run(t)
}
================================================
FILE: internal/encoding/bool.go
================================================
package encoding
import "github.com/shamaton/msgpack/v3/def"
//func (e *encoder) calcBool() int {
// return 0
//}
func (e *encoder) writeBool(v bool, offset int) int {
if v {
offset = e.setByte1Int(def.True, offset)
} else {
offset = e.setByte1Int(def.False, offset)
}
return offset
}
================================================
FILE: internal/encoding/byte.go
================================================
package encoding
import (
"fmt"
"math"
"reflect"
"github.com/shamaton/msgpack/v3/def"
)
var typeByte = reflect.TypeOf(byte(0))
func (e *encoder) isByteSlice(rv reflect.Value) bool {
return rv.Type().Elem() == typeByte
}
func (e *encoder) calcByteSlice(l int) (int, error) {
if l <= math.MaxUint8 {
return def.Byte1 + def.Byte1 + l, nil
} else if l <= math.MaxUint16 {
return def.Byte1 + def.Byte2 + l, nil
} else if uint(l) <= math.MaxUint32 {
return def.Byte1 + def.Byte4 + l, nil
}
// not supported error
return 0, fmt.Errorf("%w slice length : %d", def.ErrUnsupportedType, l)
}
func (e *encoder) writeByteSliceLength(l int, offset int) int {
if l <= math.MaxUint8 {
offset = e.setByte1Int(def.Bin8, offset)
offset = e.setByte1Int(l, offset)
} else if l <= math.MaxUint16 {
offset = e.setByte1Int(def.Bin16, offset)
offset = e.setByte2Int(l, offset)
} else if uint(l) <= math.MaxUint32 {
offset = e.setByte1Int(def.Bin32, offset)
offset = e.setByte4Int(l, offset)
}
return offset
}
================================================
FILE: internal/encoding/byte_test.go
================================================
package encoding
import (
"math"
"testing"
"github.com/shamaton/msgpack/v3/def"
tu "github.com/shamaton/msgpack/v3/internal/common/testutil"
)
func Test_calcByteSlice(t *testing.T) {
testcases := []struct {
name string
value int
result int
error error
}{
{
name: "u8",
value: math.MaxUint8,
result: def.Byte1 + def.Byte1 + math.MaxUint8,
},
{
name: "u16",
value: math.MaxUint16,
result: def.Byte1 + def.Byte2 + math.MaxUint16,
},
{
name: "u32",
value: math.MaxUint32,
result: def.Byte1 + def.Byte4 + math.MaxUint32,
},
{
name: "u32over",
value: math.MaxUint32 + 1,
error: def.ErrUnsupportedType,
},
}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
e := encoder{}
result, err := e.calcByteSlice(tc.value)
tu.IsError(t, err, tc.error)
tu.Equal(t, result, tc.result)
})
}
}
================================================
FILE: internal/encoding/complex.go
================================================
package encoding
import (
"math"
"github.com/shamaton/msgpack/v3/def"
)
func (e *encoder) calcComplex64() int {
return def.Byte1 + def.Byte1 + def.Byte8
}
func (e *encoder) calcComplex128() int {
return def.Byte1 + def.Byte1 + def.Byte16
}
func (e *encoder) writeComplex64(v complex64, offset int) int {
offset = e.setByte1Int(def.Fixext8, offset)
offset = e.setByte1Int(int(def.ComplexTypeCode()), offset)
offset = e.setByte4Uint64(uint64(math.Float32bits(real(v))), offset)
offset = e.setByte4Uint64(uint64(math.Float32bits(imag(v))), offset)
return offset
}
func (e *encoder) writeComplex128(v complex128, offset int) int {
offset = e.setByte1Int(def.Fixext16, offset)
offset = e.setByte1Int(int(def.ComplexTypeCode()), offset)
offset = e.setByte8Uint64(math.Float64bits(real(v)), offset)
offset = e.setByte8Uint64(math.Float64bits(imag(v)), offset)
return offset
}
================================================
FILE: internal/encoding/encoding.go
================================================
package encoding
import (
"fmt"
"math"
"reflect"
"github.com/shamaton/msgpack/v3/def"
"github.com/shamaton/msgpack/v3/internal/common"
)
type encoder struct {
d []byte
asArray bool
common.Common
mk map[uintptr][]reflect.Value
mv map[uintptr][]reflect.Value
}
// Encode returns the MessagePack-encoded byte array of v.
func Encode(v interface{}, asArray bool) (b []byte, err error) {
e := encoder{asArray: asArray}
/*
defer func() {
e := recover()
if e != nil {
b = nil
err = fmt.Errorf("unexpected error!! \n%s", stackTrace())
}
}()
*/
rv := reflect.ValueOf(v)
if rv.Kind() == reflect.Ptr {
rv = rv.Elem()
if rv.Kind() == reflect.Ptr {
rv = rv.Elem()
}
}
size, err := e.calcSize(rv)
if err != nil {
return nil, err
}
e.d = make([]byte, size)
last := e.create(rv, 0)
if size != last {
return nil, fmt.Errorf("%w size=%d, lastIdx=%d", def.ErrNotMatchLastIndex, size, last)
}
return e.d, err
}
//func stackTrace() string {
// msg := ""
// for depth := 0; ; depth++ {
// _, file, line, ok := runtime.Caller(depth)
// if !ok {
// break
// }
// msg += fmt.Sprintln(depth, ": ", file, ":", line)
// }
// return msg
//}
func (e *encoder) calcSize(rv reflect.Value) (int, error) {
switch rv.Kind() {
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
v := rv.Uint()
return e.calcUint(v), nil
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
v := rv.Int()
return e.calcInt(int64(v)), nil
case reflect.Float32:
return e.calcFloat32(0), nil
case reflect.Float64:
return e.calcFloat64(0), nil
case reflect.String:
return e.calcString(rv.String()), nil
case reflect.Bool:
return def.Byte1, nil
case reflect.Complex64:
return e.calcComplex64(), nil
case reflect.Complex128:
return e.calcComplex128(), nil
case reflect.Slice:
if rv.IsNil() {
return def.Byte1, nil
}
// bin format
if e.isByteSlice(rv) {
size, err := e.calcByteSlice(rv.Len())
if err != nil {
return 0, err
}
return size, nil
}
if size, find := e.calcFixedSlice(rv); find {
return size, nil
}
// func
elem := rv.Type().Elem()
var f structCalcFunc
if elem.Kind() == reflect.Struct {
f = e.getStructCalc(elem)
} else {
f = e.calcSize
}
l := rv.Len()
size, err := e.calcLength(l)
if err != nil {
return 0, err
}
// objects size
for i := 0; i < l; i++ {
s, err := f(rv.Index(i))
if err != nil {
return 0, err
}
size += s
}
return size, nil
case reflect.Array:
// bin format
if e.isByteSlice(rv) {
size, err := e.calcByteSlice(rv.Len())
if err != nil {
return 0, err
}
return size, nil
}
// func
elem := rv.Type().Elem()
var f structCalcFunc
if elem.Kind() == reflect.Struct {
f = e.getStructCalc(elem)
} else {
f = e.calcSize
}
l := rv.Len()
size, err := e.calcLength(l)
if err != nil {
return 0, err
}
// objects size
for i := 0; i < l; i++ {
s, err := f(rv.Index(i))
if err != nil {
return 0, err
}
size += s
}
return size, nil
case reflect.Map:
if rv.IsNil() {
return def.Byte1, nil
}
if size, find := e.calcFixedMap(rv); find {
return size, nil
}
if e.mk == nil {
e.mk = map[uintptr][]reflect.Value{}
e.mv = map[uintptr][]reflect.Value{}
}
keys := rv.MapKeys()
size, err := e.calcLength(len(keys))
if err != nil {
return 0, err
}
// key-value
mv := make([]reflect.Value, len(keys))
i := 0
for _, k := range keys {
keySize, err := e.calcSize(k)
if err != nil {
return 0, err
}
value := rv.MapIndex(k)
valueSize, err := e.calcSize(value)
if err != nil {
return 0, err
}
size += keySize + valueSize
mv[i] = value
i++
}
e.mk[rv.Pointer()], e.mv[rv.Pointer()] = keys, mv
return size, nil
case reflect.Struct:
size, err := e.calcStruct(rv)
if err != nil {
return 0, err
}
return size, nil
case reflect.Ptr:
if rv.IsNil() {
return def.Byte1, nil
}
size, err := e.calcSize(rv.Elem())
if err != nil {
return 0, err
}
return size, nil
case reflect.Interface:
size, err := e.calcSize(rv.Elem())
if err != nil {
return 0, err
}
return size, nil
case reflect.Invalid:
// do nothing (return nil)
return def.Byte1, nil
default:
return 0, fmt.Errorf("%v is %w type", rv.Kind(), def.ErrUnsupportedType)
}
}
func (e *encoder) calcLength(l int) (int, error) {
if l <= 0x0f {
return def.Byte1, nil
} else if l <= math.MaxUint16 {
return def.Byte1 + def.Byte2, nil
} else if uint(l) <= math.MaxUint32 {
return def.Byte1 + def.Byte4, nil
}
// not supported error
return 0, fmt.Errorf("array length %d is %w", l, def.ErrUnsupportedLength)
}
func (e *encoder) create(rv reflect.Value, offset int) int {
switch rv.Kind() {
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
v := rv.Uint()
offset = e.writeUint(v, offset)
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
v := rv.Int()
offset = e.writeInt(v, offset)
case reflect.Float32:
offset = e.writeFloat32(rv.Float(), offset)
case reflect.Float64:
offset = e.writeFloat64(rv.Float(), offset)
case reflect.Bool:
offset = e.writeBool(rv.Bool(), offset)
case reflect.String:
offset = e.writeString(rv.String(), offset)
case reflect.Complex64:
offset = e.writeComplex64(complex64(rv.Complex()), offset)
case reflect.Complex128:
offset = e.writeComplex128(rv.Complex(), offset)
case reflect.Slice:
if rv.IsNil() {
return e.writeNil(offset)
}
// bin format
if e.isByteSlice(rv) {
offset = e.writeByteSliceLength(rv.Len(), offset)
offset = e.setBytes(rv.Bytes(), offset)
return offset
}
if offset, find := e.writeFixedSlice(rv, offset); find {
return offset
}
// func
elem := rv.Type().Elem()
var f structWriteFunc
if elem.Kind() == reflect.Struct {
f = e.getStructWriter(elem)
} else {
f = e.create
}
// objects
l := rv.Len()
offset = e.writeSliceLength(l, offset)
for i := 0; i < l; i++ {
offset = f(rv.Index(i), offset)
}
case reflect.Array:
l := rv.Len()
// bin format
if e.isByteSlice(rv) {
offset = e.writeByteSliceLength(l, offset)
// objects
for i := 0; i < l; i++ {
offset = e.setByte1Uint64(rv.Index(i).Uint(), offset)
}
return offset
}
// format
offset = e.writeSliceLength(l, offset)
// func
elem := rv.Type().Elem()
var f structWriteFunc
if elem.Kind() == reflect.Struct {
f = e.getStructWriter(elem)
} else {
f = e.create
}
// objects
for i := 0; i < l; i++ {
offset = f(rv.Index(i), offset)
}
case reflect.Map:
if rv.IsNil() {
return e.writeNil(offset)
}
l := rv.Len()
offset = e.writeMapLength(l, offset)
if offset, find := e.writeFixedMap(rv, offset); find {
return offset
}
// key-value
p := rv.Pointer()
for i := range e.mk[p] {
offset = e.create(e.mk[p][i], offset)
offset = e.create(e.mv[p][i], offset)
}
case reflect.Struct:
offset = e.writeStruct(rv, offset)
case reflect.Ptr:
if rv.IsNil() {
return e.writeNil(offset)
}
offset = e.create(rv.Elem(), offset)
case reflect.Interface:
offset = e.create(rv.Elem(), offset)
case reflect.Invalid:
return e.writeNil(offset)
}
return offset
}
================================================
FILE: internal/encoding/encoding_test.go
================================================
package encoding
import (
"math"
"reflect"
"strconv"
"testing"
"github.com/shamaton/msgpack/v3/def"
tu "github.com/shamaton/msgpack/v3/internal/common/testutil"
)
func TestEncode(t *testing.T) {
v := 1
vv := &v
b, err :=
gitextract_aynht_4q/ ├── .github/ │ ├── release.yml │ └── workflows/ │ ├── stale.yml │ ├── tagpr.yml │ └── test.yml ├── .gitignore ├── .tagpr ├── CHANGELOG.md ├── LICENSE ├── README.md ├── codecov.yml ├── crash_test.go ├── decode.go ├── def/ │ ├── def.go │ └── error.go ├── encode.go ├── errors.go ├── ext/ │ ├── decode.go │ ├── decoder_stream.go │ ├── encode.go │ └── encode_stream.go ├── go.mod ├── internal/ │ ├── common/ │ │ ├── buffer.go │ │ ├── common.go │ │ ├── common_test.go │ │ └── testutil/ │ │ ├── reader.go │ │ ├── struct.go │ │ └── testutil.go │ ├── decoding/ │ │ ├── bin.go │ │ ├── bin_test.go │ │ ├── bool.go │ │ ├── bool_test.go │ │ ├── complex.go │ │ ├── complex_test.go │ │ ├── decoding.go │ │ ├── decoding_test.go │ │ ├── ext.go │ │ ├── ext_test.go │ │ ├── float.go │ │ ├── float_test.go │ │ ├── int.go │ │ ├── int_test.go │ │ ├── interface.go │ │ ├── interface_test.go │ │ ├── map.go │ │ ├── map_test.go │ │ ├── nil.go │ │ ├── read.go │ │ ├── slice.go │ │ ├── slice_test.go │ │ ├── string.go │ │ ├── string_test.go │ │ ├── struct.go │ │ ├── struct_test.go │ │ ├── uint.go │ │ └── uint_test.go │ ├── encoding/ │ │ ├── bool.go │ │ ├── byte.go │ │ ├── byte_test.go │ │ ├── complex.go │ │ ├── encoding.go │ │ ├── encoding_test.go │ │ ├── ext.go │ │ ├── ext_test.go │ │ ├── float.go │ │ ├── int.go │ │ ├── map.go │ │ ├── nil.go │ │ ├── set.go │ │ ├── slice.go │ │ ├── slice_test.go │ │ ├── string.go │ │ ├── struct.go │ │ ├── struct_test.go │ │ └── uint.go │ └── stream/ │ ├── decoding/ │ │ ├── bin.go │ │ ├── bin_test.go │ │ ├── bool.go │ │ ├── bool_test.go │ │ ├── complex.go │ │ ├── complex_test.go │ │ ├── decoding.go │ │ ├── decoding_test.go │ │ ├── ext.go │ │ ├── ext_test.go │ │ ├── float.go │ │ ├── float_test.go │ │ ├── int.go │ │ ├── int_test.go │ │ ├── interface.go │ │ ├── interface_test.go │ │ ├── map.go │ │ ├── map_test.go │ │ ├── nil.go │ │ ├── read.go │ │ ├── slice.go │ │ ├── slice_test.go │ │ ├── string.go │ │ ├── string_test.go │ │ ├── struct.go │ │ ├── struct_test.go │ │ ├── uint.go │ │ └── uint_test.go │ └── encoding/ │ ├── bool.go │ ├── bool_test.go │ ├── byte.go │ ├── byte_test.go │ ├── complex.go │ ├── complex_test.go │ ├── encoding.go │ ├── encoding_test.go │ ├── ext.go │ ├── ext_test.go │ ├── float.go │ ├── float_test.go │ ├── int.go │ ├── int_test.go │ ├── map.go │ ├── map_test.go │ ├── nil.go │ ├── set.go │ ├── slice.go │ ├── slice_test.go │ ├── string.go │ ├── string_test.go │ ├── struct.go │ ├── struct_test.go │ ├── uint.go │ └── uint_test.go ├── msgpack.go ├── msgpack_example_test.go ├── msgpack_test.go ├── testdata/ │ └── crashers/ │ ├── 007424b0caabdaf653d7efeb3ce6c1c127f628c6 │ ├── 01d1844ec3cdec0e8d60d81fcded73f920270e9c │ ├── 049b2af75fc4ee7160c7ea9bad41a5167b501d32 │ ├── 051d081de15ae4680b4156046787aae72ae0adcc │ ├── 063fea9d12105a80ee56a482aac428543fcf8d49 │ ├── 080c57e02ab7e704e2a2e93aad7674a574dc9d69 │ ├── 0d45579ce9ef9c1ca6e945d3f21ad31097f0c3c0 │ ├── 0f7994b18fb75394c81005c925dd1ae153ad57ad │ ├── 121a9af889bd4ca2266be5a4f680d3bead8d02d6 │ ├── 19eb9972c2a406f15bbae850ac33b42ebd88f7a7 │ ├── 1a3492dbf0b80d08f12ce49c620239e48b74c08c │ ├── 1ae8bba51072f9ff2bdf587596cfb0edf8a5cd12 │ ├── 1b274070ce90f8ccdf0fc33a4afd4e1455766f8b │ ├── 1d49f1635e901393bf65a263810508bea7ec9d51 │ ├── 1e2c5c5ac7754f3e3fd858ce644b6621da2f4d03 │ ├── 236cfc19fdc31facdfe306e479a52bb3c08cb540 │ ├── 2478b7ed4fe72f5030a22146ecf365adba0dc780 │ ├── 24b5d7868ba6df6da0e26365e10fc15bcf72cca6 │ ├── 255b827f8c0a593c5ee7610cdbd31c656f166a37 │ ├── 2a8cbfc34aa4aefa008e9e18276e32fa5e8f56d8 │ ├── 2ba0c664eff181eeb2b101f60c5ca66397f4c386 │ ├── 2c34cfd27e783430e24c2af05361af3540b4d6ad │ ├── 2c4dd5af849b5cda2b7769dc52706e5fa746de73 │ ├── 2cdb9f5adf53f1054ce8e6ceba007396ce6b734b │ ├── 30140397fe38ee61f01eff44b5cfa48285e47889 │ ├── 321500ed9a1796dca3d559d8f129ed31a8790035 │ ├── 3219e4d65ac8671a452900514bc3c7aea2e71be3 │ ├── 36a5cc93968072de9d120643033589df4f316997 │ ├── 3abe9a29f2b95f34da65d88b969e58f4b46b6309 │ ├── 3e5a9e8b50fcdcbe08f8138de6b95b5cd5b69bf2 │ ├── 3f0062c38d031b015f1a8bb82bd370b65d5ca35a │ ├── 4670a8e0d21a624c0d42fd6dc76ef408d2b4e195 │ ├── 47393c214b8f5a3d3c098e3985d24bd1e8d82a85 │ ├── 48947b6f943721ce84ef81e887a16bde2759f7ab │ ├── 49989f6a8875777519c822a92c821cbb95bfc360 │ ├── 4aaffe149efbd0ab6f122a4dc6e9e9aa0a602799 │ ├── 4b65bf83d9b292f65bb5d1b056d68a4811732ef3 │ ├── 4c156cb396c967d81bf3615cbd5ba74221a9c622 │ ├── 4fb8cfeaaac80a1c829b22a43089ef470bcfe5b8 │ ├── 502804b3665c5eb935d6f66e7677f75242f516bb │ ├── 56ff31c3b76d37929e45071a36ca5aa0bc386e09 │ ├── 5bc56c0f00870625b5016a8d242ebe5c2a58802b │ ├── 5e8c489081abe671d760e1840b526f43bc7e6aa3 │ ├── 5ec02b6349403b523d33576c7e2de27fb345edf0 │ ├── 6351ed5a9ac9cbb709ad15b4193edb52b8d37e84 │ ├── 673480b070ea0508c3510627c81a4b519fb7d2f5 │ ├── 683f06bff1a62b73193352f06a7194f0bf60ffb8 │ ├── 68a5e75e9b42928454b320fe8f64ea107e61f60f │ ├── 68be1e92e40e77926e1d9a5c2d800da023f6a4e9 │ ├── 6b7395dabfc4d5a76e276f222c64c4bf7771ffb7 │ ├── 707235f5352edef615d64d00d83fcf92c9dffa57 │ ├── 71819c849b41ee2f4a5b08321b9fc8bf21326ddf │ ├── 730377e1be92f426661e434d4f1cf20a10e16991 │ ├── 73728d128f628772a64990a72340d9fd7987e29b │ ├── 73cc8fe38acd489c2b1fed0a66222aac4e04cc98 │ ├── 74fe2a4034b08b5ecb014b2596e7f21ab55ea729 │ ├── 79aed363731b28a60abf16190df3d60fd1d88e54 │ ├── 7a1d04a0253fbb956c8119c40dc917cb460dabb0 │ ├── 7a96d469f87b8c0fa00a944669469db9c8246714 │ ├── 7b21df3bb234142e7b2dfc81f84eb621f9c7a617 │ ├── 7cd196c0e83037dd1c7aa060e3919f530d5eaa13 │ ├── 8611c05469f8e623e1e035e578d1d50ff2a54e11 │ ├── 861648845b817281bffa42d8ca1c46443cef5cd8 │ ├── 86f9eb6ebcae33f4d3663f90adf430f6d7b5e57c │ ├── 8a90278d26f66fd78e4e38da237c201707bf7ab3 │ ├── 8de4d4284d8227a753986639b1d6e698bc683d8a │ ├── 8e4cb24fea75d067b0d9a5598fdeb66490777000 │ ├── 900843bfb3730b31165e6d480bb212854380de72 │ ├── 964ac50bf26ecb3d0253e5e288484776bbf0abdf │ ├── 98d2aa10f9c5e6d9b1a6fb3dcc6583aa5631882a │ ├── 9ae8dabd9621f44592757414f83d26df04e55bca │ ├── 9b982d96821f364683a7a9cc2495cccc7d5bb705 │ ├── 9ded617601151e2a3dde370fe42f206f6dd38f42 │ ├── 9e2487eee9a3b9f415c36aed893ed2da3d3bace6 │ ├── 9f733d3115030339e63922d6e35920f9dba1207e │ ├── a0bb3eef10ad343fdf00adc2c7a2fab0e4dd679f │ ├── a611449daf97af318de6495f22c907ecb1f83076 │ ├── a8c1d81ff50e57abc043f8bbcc87ce0e123285a7 │ ├── aa1a1bd5b7953186af6c9f2e8f757247fdffa9ce │ ├── b7471e724dfba20b71265eb8f8315ff5add6ccad │ ├── b9df95e660f5bc5d66f2ad7c49339cb3d62d2a99 │ ├── bc22b685617fec260cb94cb1ab9822e393924a35 │ ├── c1a1ed4a1a749c9e38da920c66a4c425e169566b │ ├── c41c1a47577c69284cae60d785ddb240dc3739db │ ├── c4ee5a4632d4f9a51ba57a70cfa2cae832460857 │ ├── c9388db618e924f41e419ccddc068b443657ffa4 │ ├── ce7c29332788aa93186591aceaad307ffbdf9735 │ ├── da39a3ee5e6b4b0d3255bfef95601890afd80709 │ ├── df0c1e8999119939ea4f07c2daeb57b868bb0719 │ ├── e2d6b6d4d9b8346067d2252bfbcefff99a24ed21 │ ├── e62ebb1ab82b8cf630f2b393d89c367dd0b25924 │ ├── e906f0d49a1b91f0b93d64c36bf5a764924ce45f │ ├── ead2a4908cb1750ae6f619656ebf74b153edab25 │ ├── eae5f62c3fc844275194f17d530d26ceafcf941b │ ├── eb9a0e5a353364b221b1e1e3115d34d7948e9ae9 │ ├── edb2dfda8124a5c5935dd1d449f493e868d9f9c0 │ ├── f023f3307ef4fe6b9d8ea2c0ea4fb3bc954f2888 │ ├── f1ec5f959e75412b01270a861f1f1ecdfda1cb9c │ ├── f4aaa2a22e1038e4abda4636592d330fc9fc693b │ ├── f7cb64ffc60ab1f9e0aecbd9c560af1d743fe314 │ ├── f86f8b65ecd59bddb8df4850b538b863021ea14a │ ├── f87f13e299cb66c824237b662a5623647d3af86e │ ├── fa85f6319c6d39864527629c9b25c4b086f398b7 │ └── fc7077d7ef5f47af404835e9ea6401f258b27f83 ├── time/ │ ├── decode.go │ ├── decode_stream.go │ ├── decode_stream_test.go │ ├── decode_test.go │ ├── encode.go │ ├── encode_stream.go │ ├── encode_stream_test.go │ ├── encode_test.go │ └── time.go └── unmarshal_ext_test.go
SYMBOL INDEX (674 symbols across 128 files)
FILE: crash_test.go
function TestCrashBinary (line 16) | func TestCrashBinary(t *testing.T) {
function check (line 38) | func check(t *testing.T, wg *sync.WaitGroup, ch <-chan string) {
FILE: decode.go
function UnmarshalAsMap (line 12) | func UnmarshalAsMap(data []byte, v interface{}) error {
function UnmarshalAsArray (line 18) | func UnmarshalAsArray(data []byte, v interface{}) error {
function UnmarshalReadAsMap (line 24) | func UnmarshalReadAsMap(r io.Reader, v interface{}) error {
function UnmarshalReadAsArray (line 30) | func UnmarshalReadAsArray(r io.Reader, v interface{}) error {
FILE: def/def.go
constant IntSize (line 4) | IntSize = 32 << (^uint(0) >> 63)
constant PositiveFixIntMin (line 10) | PositiveFixIntMin = 0x00
constant PositiveFixIntMax (line 11) | PositiveFixIntMax = 0x7f
constant FixMap (line 13) | FixMap = 0x80
constant FixArray (line 14) | FixArray = 0x90
constant FixStr (line 15) | FixStr = 0xa0
constant Nil (line 17) | Nil = 0xc0
constant False (line 19) | False = 0xc2
constant True (line 20) | True = 0xc3
constant Bin8 (line 22) | Bin8 = 0xc4
constant Bin16 (line 23) | Bin16 = 0xc5
constant Bin32 (line 24) | Bin32 = 0xc6
constant Ext8 (line 26) | Ext8 = 0xc7
constant Ext16 (line 27) | Ext16 = 0xc8
constant Ext32 (line 28) | Ext32 = 0xc9
constant Float32 (line 30) | Float32 = 0xca
constant Float64 (line 31) | Float64 = 0xcb
constant Uint8 (line 33) | Uint8 = 0xcc
constant Uint16 (line 34) | Uint16 = 0xcd
constant Uint32 (line 35) | Uint32 = 0xce
constant Uint64 (line 36) | Uint64 = 0xcf
constant Int8 (line 38) | Int8 = 0xd0
constant Int16 (line 39) | Int16 = 0xd1
constant Int32 (line 40) | Int32 = 0xd2
constant Int64 (line 41) | Int64 = 0xd3
constant Fixext1 (line 43) | Fixext1 = 0xd4
constant Fixext2 (line 44) | Fixext2 = 0xd5
constant Fixext4 (line 45) | Fixext4 = 0xd6
constant Fixext8 (line 46) | Fixext8 = 0xd7
constant Fixext16 (line 47) | Fixext16 = 0xd8
constant Str8 (line 49) | Str8 = 0xd9
constant Str16 (line 50) | Str16 = 0xda
constant Str32 (line 51) | Str32 = 0xdb
constant Array16 (line 53) | Array16 = 0xdc
constant Array32 (line 54) | Array32 = 0xdd
constant Map16 (line 56) | Map16 = 0xde
constant Map32 (line 57) | Map32 = 0xdf
constant NegativeFixintMin (line 59) | NegativeFixintMin = -32
constant NegativeFixintMax (line 60) | NegativeFixintMax = -1
constant Byte1 (line 65) | Byte1 = 1 << iota
constant Byte2 (line 66) | Byte2
constant Byte4 (line 67) | Byte4
constant Byte8 (line 68) | Byte8
constant Byte16 (line 69) | Byte16
constant Byte32 (line 70) | Byte32
constant TimeStamp (line 75) | TimeStamp = -1
function ComplexTypeCode (line 82) | func ComplexTypeCode() int8 { return complexTypeCode }
function SetComplexTypeCode (line 85) | func SetComplexTypeCode(code int8) {
FILE: encode.go
function MarshalAsMap (line 12) | func MarshalAsMap(v interface{}) ([]byte, error) {
function MarshalAsArray (line 18) | func MarshalAsArray(v interface{}) ([]byte, error) {
function MarshalWriteAsMap (line 24) | func MarshalWriteAsMap(w io.Writer, v interface{}) error {
function MarshalWriteAsArray (line 30) | func MarshalWriteAsArray(w io.Writer, v interface{}) error {
FILE: ext/decode.go
type Decoder (line 12) | type Decoder interface
type DecoderCommon (line 26) | type DecoderCommon struct
method ReadSize1 (line 30) | func (cd *DecoderCommon) ReadSize1(index int, d *[]byte) (byte, int) {
method ReadSize2 (line 37) | func (cd *DecoderCommon) ReadSize2(index int, d *[]byte) ([]byte, int) {
method ReadSize4 (line 44) | func (cd *DecoderCommon) ReadSize4(index int, d *[]byte) ([]byte, int) {
method ReadSize8 (line 51) | func (cd *DecoderCommon) ReadSize8(index int, d *[]byte) ([]byte, int) {
method ReadSizeN (line 58) | func (cd *DecoderCommon) ReadSizeN(index, n int, d *[]byte) ([]byte, i...
FILE: ext/decoder_stream.go
type StreamDecoder (line 10) | type StreamDecoder interface
FILE: ext/encode.go
type Encoder (line 10) | type Encoder interface
type EncoderCommon (line 29) | type EncoderCommon struct
method SetByte1Int64 (line 33) | func (c *EncoderCommon) SetByte1Int64(value int64, offset int, d *[]by...
method SetByte2Int64 (line 40) | func (c *EncoderCommon) SetByte2Int64(value int64, offset int, d *[]by...
method SetByte4Int64 (line 48) | func (c *EncoderCommon) SetByte4Int64(value int64, offset int, d *[]by...
method SetByte8Int64 (line 58) | func (c *EncoderCommon) SetByte8Int64(value int64, offset int, d *[]by...
method SetByte1Uint64 (line 72) | func (c *EncoderCommon) SetByte1Uint64(value uint64, offset int, d *[]...
method SetByte2Uint64 (line 79) | func (c *EncoderCommon) SetByte2Uint64(value uint64, offset int, d *[]...
method SetByte4Uint64 (line 87) | func (c *EncoderCommon) SetByte4Uint64(value uint64, offset int, d *[]...
method SetByte8Uint64 (line 97) | func (c *EncoderCommon) SetByte8Uint64(value uint64, offset int, d *[]...
method SetByte1Int (line 111) | func (c *EncoderCommon) SetByte1Int(code, offset int, d *[]byte) int {
method SetByte2Int (line 118) | func (c *EncoderCommon) SetByte2Int(value int, offset int, d *[]byte) ...
method SetByte4Int (line 126) | func (c *EncoderCommon) SetByte4Int(value int, offset int, d *[]byte) ...
method SetByte4Uint32 (line 136) | func (c *EncoderCommon) SetByte4Uint32(value uint32, offset int, d *[]...
method SetBytes (line 146) | func (c *EncoderCommon) SetBytes(bs []byte, offset int, d *[]byte) int {
FILE: ext/encode_stream.go
type StreamEncoder (line 12) | type StreamEncoder interface
type StreamWriter (line 23) | type StreamWriter struct
method WriteByte1Int64 (line 34) | func (w *StreamWriter) WriteByte1Int64(value int64) error {
method WriteByte2Int64 (line 41) | func (w *StreamWriter) WriteByte2Int64(value int64) error {
method WriteByte4Int64 (line 49) | func (w *StreamWriter) WriteByte4Int64(value int64) error {
method WriteByte8Int64 (line 59) | func (w *StreamWriter) WriteByte8Int64(value int64) error {
method WriteByte1Uint64 (line 73) | func (w *StreamWriter) WriteByte1Uint64(value uint64) error {
method WriteByte2Uint64 (line 80) | func (w *StreamWriter) WriteByte2Uint64(value uint64) error {
method WriteByte4Uint64 (line 88) | func (w *StreamWriter) WriteByte4Uint64(value uint64) error {
method WriteByte8Uint64 (line 98) | func (w *StreamWriter) WriteByte8Uint64(value uint64) error {
method WriteByte1Int (line 112) | func (w *StreamWriter) WriteByte1Int(value int) error {
method WriteByte2Int (line 119) | func (w *StreamWriter) WriteByte2Int(value int) error {
method WriteByte4Int (line 127) | func (w *StreamWriter) WriteByte4Int(value int) error {
method WriteByte4Uint32 (line 137) | func (w *StreamWriter) WriteByte4Uint32(value uint32) error {
method WriteBytes (line 147) | func (w *StreamWriter) WriteBytes(bs []byte) error {
function CreateStreamWriter (line 29) | func CreateStreamWriter(w io.Writer, buf *common.Buffer) StreamWriter {
FILE: internal/common/buffer.go
type Buffer (line 8) | type Buffer struct
method Write (line 18) | func (b *Buffer) Write(w io.Writer, vs ...byte) error {
method Flush (line 36) | func (b *Buffer) Flush(w io.Writer) error {
function GetBuffer (line 55) | func GetBuffer() *Buffer {
function PutBuffer (line 61) | func PutBuffer(buf *Buffer) {
FILE: internal/common/common.go
type Common (line 9) | type Common struct
method CollectFields (line 22) | func (c *Common) CollectFields(t reflect.Type, path []int) []FieldInfo {
method collectFields (line 26) | func (c *Common) collectFields(t reflect.Type, path []int, omitPaths [...
method deduplicateFields (line 104) | func (c *Common) deduplicateFields(fields []FieldInfo) []FieldInfo {
method CheckField (line 166) | func (c *Common) CheckField(field reflect.StructField) (public, omit b...
method isPublic (line 195) | func (c *Common) isPublic(name string) bool {
type FieldInfo (line 12) | type FieldInfo struct
function appendOmitPath (line 92) | func appendOmitPath(paths [][]int, path []int) [][]int {
FILE: internal/common/common_test.go
function TestCommon_CheckField (line 10) | func TestCommon_CheckField(t *testing.T) {
FILE: internal/common/testutil/reader.go
type ErrReader (line 10) | type ErrReader struct
method Read (line 16) | func (ErrReader) Read(_ []byte) (int, error) {
function NewErrReader (line 12) | func NewErrReader() *ErrReader {
type TestReader (line 20) | type TestReader struct
method Read (line 30) | func (r *TestReader) Read(b []byte) (n int, err error) {
method Count (line 40) | func (r *TestReader) Count() int {
function NewTestReader (line 26) | func NewTestReader(b []byte) *TestReader {
FILE: internal/common/testutil/struct.go
function CreateStruct (line 12) | func CreateStruct(fieldNum int) (v any, asMapBytes []byte, asArrayBytes ...
FILE: internal/common/testutil/testutil.go
function NoError (line 10) | func NoError(t *testing.T, err error) {
function Error (line 17) | func Error(t *testing.T, err error) {
function IsError (line 24) | func IsError(t *testing.T, actual, expected error) {
function ErrorContains (line 31) | func ErrorContains(t *testing.T, err error, errStr string) {
function Equal (line 41) | func Equal[T any](t *testing.T, actual, expected T) {
function EqualSlice (line 48) | func EqualSlice[T comparable](t *testing.T, actual, expected []T) {
function EqualMap (line 72) | func EqualMap[K comparable, V comparable](t *testing.T, actual, expected...
type Equaler (line 84) | type Equaler interface
function EqualEqualer (line 88) | func EqualEqualer[T Equaler[T]](t *testing.T, actual, expected T) {
FILE: internal/decoding/bin.go
method isCodeBin (line 11) | func (d *decoder) isCodeBin(v byte) bool {
method asBin (line 19) | func (d *decoder) asBin(offset int, k reflect.Kind) ([]byte, int, error) {
method asBinString (line 61) | func (d *decoder) asBinString(offset int, k reflect.Kind) (string, int, ...
FILE: internal/decoding/bin_test.go
function Test_isCodeBin (line 11) | func Test_isCodeBin(t *testing.T) {
function Test_asBin (line 20) | func Test_asBin(t *testing.T) {
FILE: internal/decoding/bool.go
method asBool (line 9) | func (d *decoder) asBool(offset int, k reflect.Kind) (bool, int, error) {
FILE: internal/decoding/bool_test.go
function Test_asBool (line 10) | func Test_asBool(t *testing.T) {
FILE: internal/decoding/complex.go
method asComplex64 (line 12) | func (d *decoder) asComplex64(offset int, k reflect.Kind) (complex64, in...
method asComplex128 (line 64) | func (d *decoder) asComplex128(offset int, k reflect.Kind) (complex128, ...
FILE: internal/decoding/complex_test.go
function Test_asComplex64 (line 10) | func Test_asComplex64(t *testing.T) {
function Test_asComplex128 (line 82) | func Test_asComplex128(t *testing.T) {
FILE: internal/decoding/decoding.go
type decoder (line 11) | type decoder struct
method decode (line 42) | func (d *decoder) decode(rv reflect.Value, offset int) (int, error) {
method errorTemplate (line 341) | func (d *decoder) errorTemplate(code byte, k reflect.Kind) error {
function Decode (line 19) | func Decode(data []byte, v interface{}, asArray bool) error {
FILE: internal/decoding/decoding_test.go
type AsXXXTestCase (line 11) | type AsXXXTestCase struct
type AsXXXTestCases (line 20) | type AsXXXTestCases
method Run (line 22) | func (tcs AsXXXTestCases[T]) Run(t *testing.T) {
method Run (line 28) | func (tc *AsXXXTestCase[T]) Run(t *testing.T) {
function TestDecoding (line 63) | func TestDecoding(t *testing.T) {
function Test_decodeWithCode (line 81) | func Test_decodeWithCode(t *testing.T) {
FILE: internal/decoding/ext.go
function AddExtDecoder (line 17) | func AddExtDecoder(f ext.Decoder) {
function RemoveExtDecoder (line 31) | func RemoveExtDecoder(f ext.Decoder) {
function updateExtCoders (line 44) | func updateExtCoders() {
method extEndOffset (line 53) | func (d *decoder) extEndOffset(offset int) (bool, int, error) {
method extEndOffsetWithCode (line 61) | func (d *decoder) extEndOffsetWithCode(code byte, offset int) (bool, int...
FILE: internal/decoding/ext_test.go
function Test_AddExtDecoder (line 12) | func Test_AddExtDecoder(t *testing.T) {
function Test_RemoveExtDecoder (line 19) | func Test_RemoveExtDecoder(t *testing.T) {
type trackingExtDecoder (line 26) | type trackingExtDecoder struct
method Code (line 31) | func (td *trackingExtDecoder) Code() int8 {
method IsType (line 35) | func (td *trackingExtDecoder) IsType(_ int, _ *[]byte) bool {
method AsValue (line 40) | func (td *trackingExtDecoder) AsValue(_ int, _ reflect.Kind, _ *[]byte...
function TestExtValidationRejectsTruncatedBytesBeforeCustomDecoders (line 45) | func TestExtValidationRejectsTruncatedBytesBeforeCustomDecoders(t *testi...
FILE: internal/decoding/float.go
method asFloat32 (line 11) | func (d *decoder) asFloat32(offset int, k reflect.Kind) (float32, int, e...
method asFloat64 (line 48) | func (d *decoder) asFloat64(offset int, k reflect.Kind) (float64, int, e...
FILE: internal/decoding/float_test.go
function Test_asFloat32 (line 10) | func Test_asFloat32(t *testing.T) {
function Test_asFloat64 (line 157) | func Test_asFloat64(t *testing.T) {
FILE: internal/decoding/int.go
method isPositiveFixNum (line 10) | func (d *decoder) isPositiveFixNum(v byte) bool {
method isNegativeFixNum (line 14) | func (d *decoder) isNegativeFixNum(v byte) bool {
method asInt (line 18) | func (d *decoder) asInt(offset int, k reflect.Kind) (int64, int, error) {
FILE: internal/decoding/int_test.go
function Test_asInt (line 10) | func Test_asInt(t *testing.T) {
FILE: internal/decoding/interface.go
method asInterface (line 10) | func (d *decoder) asInterface(offset int, k reflect.Kind) (interface{}, ...
method canSetAsMapKey (line 184) | func (d *decoder) canSetAsMapKey(index int) error {
FILE: internal/decoding/interface_test.go
function Test_asInterfaceWithCode (line 12) | func Test_asInterfaceWithCode(t *testing.T) {
type testExt2Decoder (line 173) | type testExt2Decoder struct
method Code (line 179) | func (td *testExt2Decoder) Code() int8 {
method IsType (line 183) | func (td *testExt2Decoder) IsType(o int, d *[]byte) bool {
method AsValue (line 195) | func (td *testExt2Decoder) AsValue(_ int, _ reflect.Kind, _ *[]byte) (...
FILE: internal/decoding/map.go
method isFixMap (line 57) | func (d *decoder) isFixMap(v byte) bool {
method mapLength (line 61) | func (d *decoder) mapLength(offset int, k reflect.Kind) (int, int, error) {
method hasRequiredLeastMapSize (line 87) | func (d *decoder) hasRequiredLeastMapSize(offset, length int) error {
method asFixedMap (line 95) | func (d *decoder) asFixedMap(rv reflect.Value, offset int, l int) (int, ...
FILE: internal/decoding/map_test.go
function Test_mapLength (line 13) | func Test_mapLength(t *testing.T) {
function Test_asFixedMap_StringInt (line 64) | func Test_asFixedMap_StringInt(t *testing.T) {
function Test_asFixedMap_StringUint (line 114) | func Test_asFixedMap_StringUint(t *testing.T) {
function Test_asFixedMap_StringFloat (line 164) | func Test_asFixedMap_StringFloat(t *testing.T) {
function Test_asFixedMap_StringBool (line 205) | func Test_asFixedMap_StringBool(t *testing.T) {
function Test_asFixedMap_StringString (line 243) | func Test_asFixedMap_StringString(t *testing.T) {
function Test_asFixedMap_IntString (line 281) | func Test_asFixedMap_IntString(t *testing.T) {
function Test_asFixedMap_IntBool (line 331) | func Test_asFixedMap_IntBool(t *testing.T) {
function Test_asFixedMap_UintString (line 381) | func Test_asFixedMap_UintString(t *testing.T) {
function Test_asFixedMap_UintBool (line 431) | func Test_asFixedMap_UintBool(t *testing.T) {
function Test_asFixedMap_FloatString (line 481) | func Test_asFixedMap_FloatString(t *testing.T) {
function Test_asFixedMap_FloatBool (line 522) | func Test_asFixedMap_FloatBool(t *testing.T) {
FILE: internal/decoding/nil.go
method isCodeNil (line 5) | func (d *decoder) isCodeNil(v byte) bool {
FILE: internal/decoding/read.go
method readSize1 (line 7) | func (d *decoder) readSize1(index int) (byte, int, error) {
method readSize2 (line 15) | func (d *decoder) readSize2(index int) ([]byte, int, error) {
method readSize4 (line 19) | func (d *decoder) readSize4(index int) ([]byte, int, error) {
method readSize8 (line 23) | func (d *decoder) readSize8(index int) ([]byte, int, error) {
method readSizeN (line 27) | func (d *decoder) readSizeN(index, n int) ([]byte, int, error) {
FILE: internal/decoding/slice.go
method isFixSlice (line 31) | func (d *decoder) isFixSlice(v byte) bool {
method sliceLength (line 35) | func (d *decoder) sliceLength(offset int, k reflect.Kind) (int, int, err...
method hasRequiredLeastSliceSize (line 60) | func (d *decoder) hasRequiredLeastSliceSize(offset, length int) error {
method asFixedSlice (line 68) | func (d *decoder) asFixedSlice(rv reflect.Value, offset int, l int) (int...
FILE: internal/decoding/slice_test.go
function Test_sliceLength (line 12) | func Test_sliceLength(t *testing.T) {
function Test_asFixedSlice_Int (line 63) | func Test_asFixedSlice_Int(t *testing.T) {
function Test_asFixedSlice_Int8 (line 92) | func Test_asFixedSlice_Int8(t *testing.T) {
function Test_asFixedSlice_Int16 (line 123) | func Test_asFixedSlice_Int16(t *testing.T) {
function Test_asFixedSlice_Int32 (line 152) | func Test_asFixedSlice_Int32(t *testing.T) {
function Test_asFixedSlice_Int64 (line 181) | func Test_asFixedSlice_Int64(t *testing.T) {
function Test_asFixedSlice_Uint (line 210) | func Test_asFixedSlice_Uint(t *testing.T) {
function Test_asFixedSlice_Uint8 (line 239) | func Test_asFixedSlice_Uint8(t *testing.T) {
function Test_asFixedSlice_Uint16 (line 268) | func Test_asFixedSlice_Uint16(t *testing.T) {
function Test_asFixedSlice_Uint32 (line 297) | func Test_asFixedSlice_Uint32(t *testing.T) {
function Test_asFixedSlice_Uint64 (line 326) | func Test_asFixedSlice_Uint64(t *testing.T) {
function Test_asFixedSlice_Float32 (line 355) | func Test_asFixedSlice_Float32(t *testing.T) {
function Test_asFixedSlice_Float64 (line 384) | func Test_asFixedSlice_Float64(t *testing.T) {
function Test_asFixedSlice_String (line 413) | func Test_asFixedSlice_String(t *testing.T) {
function Test_asFixedSlice_Bool (line 442) | func Test_asFixedSlice_Bool(t *testing.T) {
FILE: internal/decoding/string.go
method isCodeString (line 15) | func (d *decoder) isCodeString(code byte) bool {
method isFixString (line 19) | func (d *decoder) isFixString(v byte) bool {
method stringByteLength (line 23) | func (d *decoder) stringByteLength(offset int, k reflect.Kind) (int, int...
method asString (line 56) | func (d *decoder) asString(offset int, k reflect.Kind) (string, int, err...
method asStringByte (line 64) | func (d *decoder) asStringByte(offset int, k reflect.Kind) ([]byte, int,...
method asStringByteByLength (line 73) | func (d *decoder) asStringByteByLength(offset int, l int, k reflect.Kind...
FILE: internal/decoding/string_test.go
function Test_stringByteLength (line 11) | func Test_stringByteLength(t *testing.T) {
function Test_asString (line 81) | func Test_asString(t *testing.T) {
function Test_asStringByte (line 102) | func Test_asStringByte(t *testing.T) {
FILE: internal/decoding/struct.go
type structCacheTypeMap (line 11) | type structCacheTypeMap struct
type structCacheTypeArray (line 24) | type structCacheTypeArray struct
function getFieldByPath (line 43) | func getFieldByPath(rv reflect.Value, path []int, allowAlloc bool) (refl...
method setStruct (line 61) | func (d *decoder) setStruct(rv reflect.Value, offset int, k reflect.Kind...
method setStructFromArray (line 100) | func (d *decoder) setStructFromArray(rv reflect.Value, offset int, k ref...
method setStructFromMap (line 182) | func (d *decoder) setStructFromMap(rv reflect.Value, offset int, k refle...
method jumpOffset (line 313) | func (d *decoder) jumpOffset(offset int) (int, error) {
FILE: internal/decoding/struct_test.go
function Test_setStruct_ext (line 12) | func Test_setStruct_ext(t *testing.T) {
function Test_setStructFromMap (line 46) | func Test_setStructFromMap(t *testing.T) {
function Test_setStructFromArray (line 104) | func Test_setStructFromArray(t *testing.T) {
function Test_jumpOffset (line 156) | func Test_jumpOffset(t *testing.T) {
FILE: internal/decoding/uint.go
method asUint (line 10) | func (d *decoder) asUint(offset int, k reflect.Kind) (uint64, int, error) {
FILE: internal/decoding/uint_test.go
function Test_asUint (line 11) | func Test_asUint(t *testing.T) {
FILE: internal/encoding/bool.go
method writeBool (line 9) | func (e *encoder) writeBool(v bool, offset int) int {
FILE: internal/encoding/byte.go
method isByteSlice (line 13) | func (e *encoder) isByteSlice(rv reflect.Value) bool {
method calcByteSlice (line 17) | func (e *encoder) calcByteSlice(l int) (int, error) {
method writeByteSliceLength (line 29) | func (e *encoder) writeByteSliceLength(l int, offset int) int {
FILE: internal/encoding/byte_test.go
function Test_calcByteSlice (line 11) | func Test_calcByteSlice(t *testing.T) {
FILE: internal/encoding/complex.go
method calcComplex64 (line 9) | func (e *encoder) calcComplex64() int {
method calcComplex128 (line 13) | func (e *encoder) calcComplex128() int {
method writeComplex64 (line 17) | func (e *encoder) writeComplex64(v complex64, offset int) int {
method writeComplex128 (line 25) | func (e *encoder) writeComplex128(v complex128, offset int) int {
FILE: internal/encoding/encoding.go
type encoder (line 12) | type encoder struct
method calcSize (line 65) | func (e *encoder) calcSize(rv reflect.Value) (int, error) {
method calcLength (line 243) | func (e *encoder) calcLength(l int) (int, error) {
method create (line 255) | func (e *encoder) create(rv reflect.Value, offset int) int {
function Encode (line 21) | func Encode(v interface{}, asArray bool) (b []byte, err error) {
FILE: internal/encoding/encoding_test.go
function TestEncode (line 13) | func TestEncode(t *testing.T) {
function Test_encode (line 23) | func Test_encode(t *testing.T) {
function Test_calcLength (line 226) | func Test_calcLength(t *testing.T) {
FILE: internal/encoding/ext.go
function AddExtEncoder (line 16) | func AddExtEncoder(f ext.Encoder) {
function RemoveExtEncoder (line 30) | func RemoveExtEncoder(f ext.Encoder) {
function updateExtCoders (line 43) | func updateExtCoders() {
FILE: internal/encoding/ext_test.go
function Test_AddExtEncoder (line 10) | func Test_AddExtEncoder(t *testing.T) {
function Test_RemoveExtEncoder (line 17) | func Test_RemoveExtEncoder(t *testing.T) {
FILE: internal/encoding/float.go
method calcFloat32 (line 9) | func (e *encoder) calcFloat32(_ float64) int {
method calcFloat64 (line 13) | func (e *encoder) calcFloat64(_ float64) int {
method writeFloat32 (line 17) | func (e *encoder) writeFloat32(v float64, offset int) int {
method writeFloat64 (line 23) | func (e *encoder) writeFloat64(v float64, offset int) int {
FILE: internal/encoding/int.go
method isNegativeFixInt64 (line 9) | func (e *encoder) isNegativeFixInt64(v int64) bool {
method calcInt (line 13) | func (e *encoder) calcInt(v int64) int {
method writeInt (line 29) | func (e *encoder) writeInt(v int64, offset int) int {
FILE: internal/encoding/map.go
method calcFixedMap (line 10) | func (e *encoder) calcFixedMap(rv reflect.Value) (int, bool) {
method writeMapLength (line 298) | func (e *encoder) writeMapLength(l int, offset int) int {
method writeFixedMap (line 312) | func (e *encoder) writeFixedMap(rv reflect.Value, offset int) (int, bool) {
FILE: internal/encoding/nil.go
method writeNil (line 5) | func (e *encoder) writeNil(offset int) int {
FILE: internal/encoding/set.go
method setByte1Int64 (line 3) | func (e *encoder) setByte1Int64(value int64, offset int) int {
method setByte2Int64 (line 8) | func (e *encoder) setByte2Int64(value int64, offset int) int {
method setByte4Int64 (line 14) | func (e *encoder) setByte4Int64(value int64, offset int) int {
method setByte8Int64 (line 22) | func (e *encoder) setByte8Int64(value int64, offset int) int {
method setByte1Uint64 (line 34) | func (e *encoder) setByte1Uint64(value uint64, offset int) int {
method setByte2Uint64 (line 39) | func (e *encoder) setByte2Uint64(value uint64, offset int) int {
method setByte4Uint64 (line 45) | func (e *encoder) setByte4Uint64(value uint64, offset int) int {
method setByte8Uint64 (line 53) | func (e *encoder) setByte8Uint64(value uint64, offset int) int {
method setByte1Int (line 65) | func (e *encoder) setByte1Int(code, offset int) int {
method setByte2Int (line 70) | func (e *encoder) setByte2Int(value int, offset int) int {
method setByte4Int (line 76) | func (e *encoder) setByte4Int(value int, offset int) int {
method setBytes (line 84) | func (e *encoder) setBytes(bs []byte, offset int) int {
FILE: internal/encoding/slice.go
method calcFixedSlice (line 10) | func (e *encoder) calcFixedSlice(rv reflect.Value) (int, bool) {
method writeSliceLength (line 115) | func (e *encoder) writeSliceLength(l int, offset int) int {
method writeFixedSlice (line 129) | func (e *encoder) writeFixedSlice(rv reflect.Value, offset int) (int, bo...
FILE: internal/encoding/slice_test.go
function Test_FixedSlice (line 10) | func Test_FixedSlice(t *testing.T) {
FILE: internal/encoding/string.go
method calcString (line 10) | func (e *encoder) calcString(v string) int {
method writeString (line 25) | func (e *encoder) writeString(str string, offset int) int {
FILE: internal/encoding/struct.go
type structCache (line 12) | type structCache struct
type structCalcFunc (line 34) | type structCalcFunc
type structWriteFunc (line 35) | type structWriteFunc
function getFieldByPath (line 40) | func getFieldByPath(rv reflect.Value, path []int) (reflect.Value, bool) {
function shouldOmitByParent (line 55) | func shouldOmitByParent(rv reflect.Value, omitPaths [][]int) bool {
method getStructCalc (line 65) | func (e *encoder) getStructCalc(typ reflect.Type) structCalcFunc {
method calcStruct (line 77) | func (e *encoder) calcStruct(rv reflect.Value) (int, error) {
method calcStructArray (line 95) | func (e *encoder) calcStructArray(rv reflect.Value) (int, error) {
method calcStructMap (line 169) | func (e *encoder) calcStructMap(rv reflect.Value) (int, error) {
method calcSizeWithOmitEmpty (line 246) | func (e *encoder) calcSizeWithOmitEmpty(rv reflect.Value, name string, o...
method getStructWriter (line 260) | func (e *encoder) getStructWriter(typ reflect.Type) structWriteFunc {
method writeStruct (line 275) | func (e *encoder) writeStruct(rv reflect.Value, offset int) int {
method writeStructArray (line 294) | func (e *encoder) writeStructArray(rv reflect.Value, offset int) int {
method writeStructMap (line 332) | func (e *encoder) writeStructMap(rv reflect.Value, offset int) int {
FILE: internal/encoding/struct_test.go
function Test_calcStructArray (line 12) | func Test_calcStructArray(t *testing.T) {
function Test_calcStructMap (line 77) | func Test_calcStructMap(t *testing.T) {
function Test_writeStructArray (line 142) | func Test_writeStructArray(t *testing.T) {
function Test_writeStructMap (line 180) | func Test_writeStructMap(t *testing.T) {
function Test_calcSizeWithOmitEmpty (line 218) | func Test_calcSizeWithOmitEmpty(t *testing.T) {
function Test_structCache (line 230) | func Test_structCache(t *testing.T) {
FILE: internal/encoding/uint.go
method calcUint (line 9) | func (e *encoder) calcUint(v uint64) int {
method writeUint (line 23) | func (e *encoder) writeUint(v uint64, offset int) int {
FILE: internal/stream/decoding/bin.go
method isCodeBin (line 11) | func (d *decoder) isCodeBin(v byte) bool {
method asBinWithCode (line 19) | func (d *decoder) asBinWithCode(code byte, k reflect.Kind) ([]byte, erro...
method asBinStringWithCode (line 49) | func (d *decoder) asBinStringWithCode(code byte, k reflect.Kind) (string...
method copySizeN (line 54) | func (d *decoder) copySizeN(n int) ([]byte, error) {
FILE: internal/stream/decoding/bin_test.go
function Test_isCodeBin (line 12) | func Test_isCodeBin(t *testing.T) {
function Test_asBinWithCode (line 21) | func Test_asBinWithCode(t *testing.T) {
FILE: internal/stream/decoding/bool.go
method asBool (line 9) | func (d *decoder) asBool(k reflect.Kind) (bool, error) {
method asBoolWithCode (line 17) | func (d *decoder) asBoolWithCode(code byte, k reflect.Kind) (bool, error) {
FILE: internal/stream/decoding/bool_test.go
function Test_asBool (line 11) | func Test_asBool(t *testing.T) {
function Test_asBoolWithCode (line 36) | func Test_asBoolWithCode(t *testing.T) {
FILE: internal/stream/decoding/complex.go
method asComplex64 (line 12) | func (d *decoder) asComplex64(code byte, k reflect.Kind) (complex64, err...
method asComplex128 (line 61) | func (d *decoder) asComplex128(code byte, k reflect.Kind) (complex128, e...
FILE: internal/stream/decoding/complex_test.go
function Test_asComplex64 (line 11) | func Test_asComplex64(t *testing.T) {
function Test_asComplex128 (line 91) | func Test_asComplex128(t *testing.T) {
FILE: internal/stream/decoding/decoding.go
type decoder (line 12) | type decoder struct
method decode (line 42) | func (d *decoder) decode(rv reflect.Value) error {
method decodeWithCode (line 50) | func (d *decoder) decodeWithCode(code byte, rv reflect.Value) error {
method errorTemplate (line 323) | func (d *decoder) errorTemplate(code byte, k reflect.Kind) error {
function Decode (line 21) | func Decode(r io.Reader, v interface{}, asArray bool) error {
FILE: internal/stream/decoding/decoding_test.go
type AsXXXTestCase (line 13) | type AsXXXTestCase struct
type AsXXXTestCases (line 25) | type AsXXXTestCases
method Run (line 27) | func (tcs AsXXXTestCases[T]) Run(t *testing.T) {
method Run (line 33) | func (tc *AsXXXTestCase[T]) Run(t *testing.T) {
function TestDecoding (line 79) | func TestDecoding(t *testing.T) {
function Test_decodeWithCode (line 93) | func Test_decodeWithCode(t *testing.T) {
FILE: internal/stream/decoding/ext.go
function AddExtDecoder (line 17) | func AddExtDecoder(f ext.StreamDecoder) {
function RemoveExtDecoder (line 31) | func RemoveExtDecoder(f ext.StreamDecoder) {
function updateExtCoders (line 44) | func updateExtCoders() {
method readIfExtType (line 53) | func (d *decoder) readIfExtType(code byte) (innerType int8, data []byte,...
FILE: internal/stream/decoding/ext_test.go
function Test_AddExtDecoder (line 13) | func Test_AddExtDecoder(t *testing.T) {
function Test_RemoveExtDecoder (line 20) | func Test_RemoveExtDecoder(t *testing.T) {
function Test_readIfExtType (line 27) | func Test_readIfExtType(t *testing.T) {
FILE: internal/stream/decoding/float.go
method asFloat32 (line 11) | func (d *decoder) asFloat32(k reflect.Kind) (float32, error) {
method asFloat32WithCode (line 19) | func (d *decoder) asFloat32WithCode(code byte, k reflect.Kind) (float32,...
method asFloat64 (line 49) | func (d *decoder) asFloat64(k reflect.Kind) (float64, error) {
method asFloat64WithCode (line 57) | func (d *decoder) asFloat64WithCode(code byte, k reflect.Kind) (float64,...
FILE: internal/stream/decoding/float_test.go
function Test_asFloat32 (line 11) | func Test_asFloat32(t *testing.T) {
function Test_asFloat32WithCode (line 35) | func Test_asFloat32WithCode(t *testing.T) {
function Test_asFloat64 (line 102) | func Test_asFloat64(t *testing.T) {
function Test_asFloat64WithCode (line 126) | func Test_asFloat64WithCode(t *testing.T) {
FILE: internal/stream/decoding/int.go
method isPositiveFixNum (line 10) | func (d *decoder) isPositiveFixNum(v byte) bool {
method isNegativeFixNum (line 14) | func (d *decoder) isNegativeFixNum(v byte) bool {
method asInt (line 18) | func (d *decoder) asInt(k reflect.Kind) (int64, error) {
method asIntWithCode (line 26) | func (d *decoder) asIntWithCode(code byte, k reflect.Kind) (int64, error) {
FILE: internal/stream/decoding/int_test.go
function Test_asInt (line 11) | func Test_asInt(t *testing.T) {
function Test_asIntWithCode (line 37) | func Test_asIntWithCode(t *testing.T) {
FILE: internal/stream/decoding/interface.go
method asInterface (line 10) | func (d *decoder) asInterface(k reflect.Kind) (interface{}, error) {
method asInterfaceWithCode (line 18) | func (d *decoder) asInterfaceWithCode(code byte, k reflect.Kind) (interf...
method canSetAsMapKey (line 169) | func (d *decoder) canSetAsMapKey(code byte) error {
FILE: internal/stream/decoding/interface_test.go
function Test_asInterface (line 13) | func Test_asInterface(t *testing.T) {
function Test_asInterfaceWithCode (line 39) | func Test_asInterfaceWithCode(t *testing.T) {
type testExt2StreamDecoder (line 220) | type testExt2StreamDecoder struct
method Code (line 224) | func (td *testExt2StreamDecoder) Code() int8 {
method IsType (line 228) | func (td *testExt2StreamDecoder) IsType(_ byte, code int8, _ int) bool {
method ToValue (line 234) | func (td *testExt2StreamDecoder) ToValue(_ byte, _ []byte, k reflect.K...
FILE: internal/stream/decoding/map.go
method isFixMap (line 57) | func (d *decoder) isFixMap(v byte) bool {
method mapLength (line 61) | func (d *decoder) mapLength(code byte, k reflect.Kind) (int, error) {
method asFixedMap (line 82) | func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) {
FILE: internal/stream/decoding/map_test.go
function Test_mapLength (line 14) | func Test_mapLength(t *testing.T) {
function Test_asFixedMap_StringInt (line 70) | func Test_asFixedMap_StringInt(t *testing.T) {
function Test_asFixedMap_StringUint (line 127) | func Test_asFixedMap_StringUint(t *testing.T) {
function Test_asFixedMap_StringFloat (line 184) | func Test_asFixedMap_StringFloat(t *testing.T) {
function Test_asFixedMap_StringBool (line 232) | func Test_asFixedMap_StringBool(t *testing.T) {
function Test_asFixedMap_StringString (line 277) | func Test_asFixedMap_StringString(t *testing.T) {
function Test_asFixedMap_IntString (line 322) | func Test_asFixedMap_IntString(t *testing.T) {
function Test_asFixedMap_IntBool (line 379) | func Test_asFixedMap_IntBool(t *testing.T) {
function Test_asFixedMap_UintString (line 436) | func Test_asFixedMap_UintString(t *testing.T) {
function Test_asFixedMap_UintBool (line 493) | func Test_asFixedMap_UintBool(t *testing.T) {
function Test_asFixedMap_FloatString (line 550) | func Test_asFixedMap_FloatString(t *testing.T) {
function Test_asFixedMap_FloatBool (line 598) | func Test_asFixedMap_FloatBool(t *testing.T) {
FILE: internal/stream/decoding/nil.go
method isCodeNil (line 5) | func (d *decoder) isCodeNil(v byte) bool {
FILE: internal/stream/decoding/read.go
method readSize1 (line 3) | func (d *decoder) readSize1() (byte, error) {
method readSize2 (line 10) | func (d *decoder) readSize2() ([]byte, error) {
method readSize4 (line 17) | func (d *decoder) readSize4() ([]byte, error) {
method readSize8 (line 24) | func (d *decoder) readSize8() ([]byte, error) {
method readSize16 (line 31) | func (d *decoder) readSize16() ([]byte, error) {
method readSizeN (line 38) | func (d *decoder) readSizeN(n int) ([]byte, error) {
FILE: internal/stream/decoding/slice.go
method isFixSlice (line 31) | func (d *decoder) isFixSlice(v byte) bool {
method sliceLength (line 35) | func (d *decoder) sliceLength(code byte, k reflect.Kind) (int, error) {
method asFixedSlice (line 55) | func (d *decoder) asFixedSlice(rv reflect.Value, l int) (bool, error) {
FILE: internal/stream/decoding/slice_test.go
function Test_sliceLength (line 13) | func Test_sliceLength(t *testing.T) {
function Test_asFixedSlice_Int (line 69) | func Test_asFixedSlice_Int(t *testing.T) {
function Test_asFixedSlice_Int8 (line 101) | func Test_asFixedSlice_Int8(t *testing.T) {
function Test_asFixedSlice_Int16 (line 133) | func Test_asFixedSlice_Int16(t *testing.T) {
function Test_asFixedSlice_Int32 (line 165) | func Test_asFixedSlice_Int32(t *testing.T) {
function Test_asFixedSlice_Int64 (line 197) | func Test_asFixedSlice_Int64(t *testing.T) {
function Test_asFixedSlice_Uint (line 229) | func Test_asFixedSlice_Uint(t *testing.T) {
function Test_asFixedSlice_Uint8 (line 261) | func Test_asFixedSlice_Uint8(t *testing.T) {
function Test_asFixedSlice_Uint16 (line 293) | func Test_asFixedSlice_Uint16(t *testing.T) {
function Test_asFixedSlice_Uint32 (line 325) | func Test_asFixedSlice_Uint32(t *testing.T) {
function Test_asFixedSlice_Uint64 (line 357) | func Test_asFixedSlice_Uint64(t *testing.T) {
function Test_asFixedSlice_Float32 (line 389) | func Test_asFixedSlice_Float32(t *testing.T) {
function Test_asFixedSlice_Float64 (line 421) | func Test_asFixedSlice_Float64(t *testing.T) {
function Test_asFixedSlice_String (line 453) | func Test_asFixedSlice_String(t *testing.T) {
function Test_asFixedSlice_Bool (line 485) | func Test_asFixedSlice_Bool(t *testing.T) {
FILE: internal/stream/decoding/string.go
method isCodeString (line 15) | func (d *decoder) isCodeString(code byte) bool {
method isFixString (line 19) | func (d *decoder) isFixString(v byte) bool {
method stringByteLength (line 23) | func (d *decoder) stringByteLength(code byte, k reflect.Kind) (int, erro...
method asString (line 51) | func (d *decoder) asString(k reflect.Kind) (string, error) {
method asStringWithCode (line 59) | func (d *decoder) asStringWithCode(code byte, k reflect.Kind) (string, e...
method asStringByte (line 67) | func (d *decoder) asStringByte(k reflect.Kind) ([]byte, error) {
method asStringByteWithCode (line 75) | func (d *decoder) asStringByteWithCode(code byte, k reflect.Kind) ([]byt...
method asStringByteByLength (line 84) | func (d *decoder) asStringByteByLength(l int, _ reflect.Kind) ([]byte, e...
FILE: internal/stream/decoding/string_test.go
function Test_stringByteLength (line 12) | func Test_stringByteLength(t *testing.T) {
function Test_asString (line 90) | func Test_asString(t *testing.T) {
function Test_asStringByte (line 123) | func Test_asStringByte(t *testing.T) {
FILE: internal/stream/decoding/struct.go
type structCacheTypeMap (line 11) | type structCacheTypeMap struct
type structCacheTypeArray (line 24) | type structCacheTypeArray struct
function getFieldByPath (line 43) | func getFieldByPath(rv reflect.Value, path []int, allowAlloc bool) (refl...
method setStruct (line 61) | func (d *decoder) setStruct(code byte, rv reflect.Value, k reflect.Kind)...
method setStructFromArray (line 91) | func (d *decoder) setStructFromArray(code byte, rv reflect.Value, k refl...
method setStructFromMap (line 170) | func (d *decoder) setStructFromMap(code byte, rv reflect.Value, k reflec...
method jumpOffset (line 296) | func (d *decoder) jumpOffset() error {
FILE: internal/stream/decoding/struct_test.go
function Test_setStruct_ext (line 13) | func Test_setStruct_ext(t *testing.T) {
function Test_setStructFromMap (line 60) | func Test_setStructFromMap(t *testing.T) {
function Test_setStructFromArray (line 123) | func Test_setStructFromArray(t *testing.T) {
function Test_jumpOffset (line 186) | func Test_jumpOffset(t *testing.T) {
FILE: internal/stream/decoding/uint.go
method asUint (line 10) | func (d *decoder) asUint(k reflect.Kind) (uint64, error) {
method asUintWithCode (line 18) | func (d *decoder) asUintWithCode(code byte, k reflect.Kind) (uint64, err...
FILE: internal/stream/decoding/uint_test.go
function Test_asUint (line 15) | func Test_asUint(t *testing.T) {
function Test_asUintWithCode (line 36) | func Test_asUintWithCode(t *testing.T) {
FILE: internal/stream/encoding/bool.go
method writeBool (line 5) | func (e *encoder) writeBool(v bool) error {
FILE: internal/stream/encoding/bool_test.go
function Test_asBool (line 9) | func Test_asBool(t *testing.T) {
FILE: internal/stream/encoding/byte.go
method isByteSlice (line 12) | func (e *encoder) isByteSlice(rv reflect.Value) bool {
method writeByteSliceLength (line 16) | func (e *encoder) writeByteSliceLength(l int) error {
FILE: internal/stream/encoding/byte_test.go
function Test_writeByteSliceLength (line 9) | func Test_writeByteSliceLength(t *testing.T) {
FILE: internal/stream/encoding/complex.go
method writeComplex64 (line 9) | func (e *encoder) writeComplex64(v complex64) error {
method writeComplex128 (line 25) | func (e *encoder) writeComplex128(v complex128) error {
FILE: internal/stream/encoding/complex_test.go
function Test_writeComplex64 (line 9) | func Test_writeComplex64(t *testing.T) {
function Test_writeComplex128 (line 64) | func Test_writeComplex128(t *testing.T) {
FILE: internal/stream/encoding/encoding.go
type encoder (line 12) | type encoder struct
method create (line 43) | func (e *encoder) create(rv reflect.Value) error {
function Encode (line 20) | func Encode(w io.Writer, v any, asArray bool) error {
FILE: internal/stream/encoding/encoding_test.go
constant dummyByte (line 15) | dummyByte = 0xc1
type TestWriter (line 17) | type TestWriter struct
method Write (line 25) | func (w *TestWriter) Write(p []byte) (n int, err error) {
function NewTestWriter (line 33) | func NewTestWriter() *TestWriter {
type AsXXXTestCase (line 37) | type AsXXXTestCase struct
type AsXXXTestCases (line 51) | type AsXXXTestCases
method Run (line 53) | func (tcs AsXXXTestCases[T]) Run(t *testing.T) {
method Run (line 59) | func (tc *AsXXXTestCase[T]) Run(t *testing.T) {
function TestEncode (line 121) | func TestEncode(t *testing.T) {
function Test_create (line 132) | func Test_create(t *testing.T) {
FILE: internal/stream/encoding/ext.go
function AddExtEncoder (line 16) | func AddExtEncoder(f ext.StreamEncoder) {
function RemoveExtEncoder (line 30) | func RemoveExtEncoder(f ext.StreamEncoder) {
function updateExtCoders (line 43) | func updateExtCoders() {
FILE: internal/stream/encoding/ext_test.go
function Test_AddExtEncoder (line 10) | func Test_AddExtEncoder(t *testing.T) {
function Test_RemoveExtEncoder (line 17) | func Test_RemoveExtEncoder(t *testing.T) {
FILE: internal/stream/encoding/float.go
method writeFloat32 (line 9) | func (e *encoder) writeFloat32(v float64) error {
method writeFloat64 (line 19) | func (e *encoder) writeFloat64(v float64) error {
FILE: internal/stream/encoding/float_test.go
function Test_writeFloat32 (line 9) | func Test_writeFloat32(t *testing.T) {
function Test_writeFloat64 (line 44) | func Test_writeFloat64(t *testing.T) {
FILE: internal/stream/encoding/int.go
method isNegativeFixInt64 (line 9) | func (e *encoder) isNegativeFixInt64(v int64) bool {
method writeInt (line 13) | func (e *encoder) writeInt(v int64) error {
FILE: internal/stream/encoding/int_test.go
function Test_asInt (line 10) | func Test_asInt(t *testing.T) {
FILE: internal/stream/encoding/map.go
method writeMapLength (line 10) | func (e *encoder) writeMapLength(l int) error {
method writeFixedMap (line 34) | func (e *encoder) writeFixedMap(rv reflect.Value) (bool, error) {
FILE: internal/stream/encoding/map_test.go
function Test_writeMapLength (line 11) | func Test_writeMapLength(t *testing.T) {
function Test_writeFixedMap (line 78) | func Test_writeFixedMap(t *testing.T) {
FILE: internal/stream/encoding/nil.go
method writeNil (line 5) | func (e *encoder) writeNil() error {
FILE: internal/stream/encoding/set.go
method setByte1Int64 (line 3) | func (e *encoder) setByte1Int64(value int64) error {
method setByte2Int64 (line 7) | func (e *encoder) setByte2Int64(value int64) error {
method setByte4Int64 (line 14) | func (e *encoder) setByte4Int64(value int64) error {
method setByte8Int64 (line 23) | func (e *encoder) setByte8Int64(value int64) error {
method setByte1Uint64 (line 36) | func (e *encoder) setByte1Uint64(value uint64) error {
method setByte2Uint64 (line 40) | func (e *encoder) setByte2Uint64(value uint64) error {
method setByte4Uint64 (line 47) | func (e *encoder) setByte4Uint64(value uint64) error {
method setByte8Uint64 (line 56) | func (e *encoder) setByte8Uint64(value uint64) error {
method setByte1Int (line 69) | func (e *encoder) setByte1Int(value int) error {
method setByte2Int (line 75) | func (e *encoder) setByte2Int(value int) error {
method setByte4Int (line 82) | func (e *encoder) setByte4Int(value int) error {
method setBytes (line 91) | func (e *encoder) setBytes(bs []byte) error {
FILE: internal/stream/encoding/slice.go
method writeSliceLength (line 10) | func (e *encoder) writeSliceLength(l int) error {
method writeFixedSlice (line 34) | func (e *encoder) writeFixedSlice(rv reflect.Value) (bool, error) {
FILE: internal/stream/encoding/slice_test.go
function Test_writeSliceLength (line 11) | func Test_writeSliceLength(t *testing.T) {
function Test_writeFixedSlice (line 78) | func Test_writeFixedSlice(t *testing.T) {
FILE: internal/stream/encoding/string.go
method writeString (line 10) | func (e *encoder) writeString(str string) error {
FILE: internal/stream/encoding/string_test.go
function Test_writeString (line 11) | func Test_writeString(t *testing.T) {
FILE: internal/stream/encoding/struct.go
type structCache (line 13) | type structCache struct
type structWriteFunc (line 34) | type structWriteFunc
function getFieldByPath (line 38) | func getFieldByPath(rv reflect.Value, path []int) (reflect.Value, bool) {
function shouldOmitByParent (line 53) | func shouldOmitByParent(rv reflect.Value, omitPaths [][]int) bool {
method getStructWriter (line 63) | func (e *encoder) getStructWriter(typ reflect.Type) structWriteFunc {
method writeStruct (line 79) | func (e *encoder) writeStruct(rv reflect.Value) error {
method writeStructArray (line 93) | func (e *encoder) writeStructArray(rv reflect.Value) error {
method writeStructMap (line 144) | func (e *encoder) writeStructMap(rv reflect.Value) error {
method getStructCache (line 222) | func (e *encoder) getStructCache(rv reflect.Value) *structCache {
FILE: internal/stream/encoding/struct_test.go
function Test_writeStruct (line 13) | func Test_writeStruct(t *testing.T) {
function Test_writeStructArray (line 90) | func Test_writeStructArray(t *testing.T) {
function Test_writeStructMap (line 200) | func Test_writeStructMap(t *testing.T) {
FILE: internal/stream/encoding/uint.go
method writeUint (line 9) | func (e *encoder) writeUint(v uint64) error {
FILE: internal/stream/encoding/uint_test.go
function Test_asUint (line 10) | func Test_asUint(t *testing.T) {
FILE: msgpack.go
function Marshal (line 21) | func Marshal(v interface{}) ([]byte, error) {
function MarshalWrite (line 26) | func MarshalWrite(w io.Writer, v interface{}) error {
function Unmarshal (line 32) | func Unmarshal(data []byte, v interface{}) error {
function UnmarshalRead (line 38) | func UnmarshalRead(r io.Reader, v interface{}) error {
function AddExtCoder (line 43) | func AddExtCoder(e ext.Encoder, d ext.Decoder) error {
function AddExtStreamCoder (line 53) | func AddExtStreamCoder(e ext.StreamEncoder, d ext.StreamDecoder) error {
function RemoveExtCoder (line 63) | func RemoveExtCoder(e ext.Encoder, d ext.Decoder) error {
function RemoveExtStreamCoder (line 73) | func RemoveExtStreamCoder(e ext.StreamEncoder, d ext.StreamDecoder) error {
function SetComplexTypeCode (line 83) | func SetComplexTypeCode(code int8) {
function SetDecodedTimeAsUTC (line 88) | func SetDecodedTimeAsUTC() {
function SetDecodedTimeAsLocal (line 93) | func SetDecodedTimeAsLocal() {
FILE: msgpack_example_test.go
function ExampleAddExtCoder (line 14) | func ExampleAddExtCoder() {
function ExampleAddExtStreamCoder (line 39) | func ExampleAddExtStreamCoder() {
constant ipNetCode (line 66) | ipNetCode = 50
type IPNetDecoder (line 68) | type IPNetDecoder struct
method Code (line 74) | func (td *IPNetDecoder) Code() int8 {
method IsType (line 78) | func (td *IPNetDecoder) IsType(offset int, d *[]byte) bool {
method AsValue (line 88) | func (td *IPNetDecoder) AsValue(offset int, k reflect.Kind, d *[]byte)...
type IPNetStreamDecoder (line 112) | type IPNetStreamDecoder struct
method Code (line 116) | func (td *IPNetStreamDecoder) Code() int8 {
method IsType (line 120) | func (td *IPNetStreamDecoder) IsType(code byte, innerType int8, _ int)...
method ToValue (line 124) | func (td *IPNetStreamDecoder) ToValue(code byte, data []byte, k reflec...
type IPNetEncoder (line 138) | type IPNetEncoder struct
method Code (line 144) | func (s *IPNetEncoder) Code() int8 {
method Type (line 148) | func (s *IPNetEncoder) Type() reflect.Type {
method CalcByteSize (line 152) | func (s *IPNetEncoder) CalcByteSize(value reflect.Value) (int, error) {
method WriteToBytes (line 157) | func (s *IPNetEncoder) WriteToBytes(value reflect.Value, offset int, b...
type IPNetStreamEncoder (line 168) | type IPNetStreamEncoder struct
method Code (line 172) | func (s *IPNetStreamEncoder) Code() int8 {
method Type (line 176) | func (s *IPNetStreamEncoder) Type() reflect.Type {
method Write (line 180) | func (s *IPNetStreamEncoder) Write(w ext.StreamWriter, value reflect.V...
FILE: msgpack_test.go
function init (line 27) | func init() {
function TestInt (line 32) | func TestInt(t *testing.T) {
function TestUint (line 99) | func TestUint(t *testing.T) {
function TestFloat (line 142) | func TestFloat(t *testing.T) {
function TestBool (line 255) | func TestBool(t *testing.T) {
function TestNil (line 290) | func TestNil(t *testing.T) {
function TestString (line 311) | func TestString(t *testing.T) {
function TestComplex (line 381) | func TestComplex(t *testing.T) {
function TestAny (line 488) | func TestAny(t *testing.T) {
function TestBin (line 593) | func TestBin(t *testing.T) {
function TestArray (line 721) | func TestArray(t *testing.T) {
function TestFixedSlice (line 840) | func TestFixedSlice(t *testing.T) {
function TestFixedMap (line 976) | func TestFixedMap(t *testing.T) {
function TestTime (line 1327) | func TestTime(t *testing.T) {
function TestMap (line 1447) | func TestMap(t *testing.T) {
function TestPointer (line 1539) | func TestPointer(t *testing.T) {
function TestUnsupported (line 1575) | func TestUnsupported(t *testing.T) {
function TestStruct (line 1666) | func TestStruct(t *testing.T) {
function testEmbedded (line 1699) | func testEmbedded(t *testing.T) {
function testEmbeddedStruct (line 1720) | func testEmbeddedStruct(t *testing.T) {
function testStructTag (line 2487) | func testStructTag(t *testing.T) {
function TestStructTagOmitempty (line 2518) | func TestStructTagOmitempty(t *testing.T) {
function testStructArray (line 2613) | func testStructArray(t *testing.T) {
function testStructCode (line 2645) | func testStructCode(t *testing.T) {
function testStructUseCase (line 2721) | func testStructUseCase(t *testing.T) {
function testStructJump (line 2809) | func testStructJump(t *testing.T) {
function TestExt (line 2877) | func TestExt(t *testing.T) {
type ExtStruct (line 2939) | type ExtStruct struct
type ExtInt (line 2953) | type ExtInt
type testDecoder (line 2957) | type testDecoder struct
method Code (line 2965) | func (td *testDecoder) Code() int8 {
method IsType (line 2969) | func (td *testDecoder) IsType(offset int, d *[]byte) bool {
method AsValue (line 2979) | func (td *testDecoder) AsValue(offset int, k reflect.Kind, d *[]byte) ...
type testStreamDecoder (line 3021) | type testStreamDecoder struct
method Code (line 3025) | func (td *testStreamDecoder) Code() int8 {
method IsType (line 3029) | func (td *testStreamDecoder) IsType(code byte, innerType int8, dataLen...
method ToValue (line 3036) | func (td *testStreamDecoder) ToValue(code byte, data []byte, k reflect...
type testEncoder (line 3072) | type testEncoder struct
method Code (line 3078) | func (s *testEncoder) Code() int8 {
method Type (line 3082) | func (s *testEncoder) Type() reflect.Type {
method CalcByteSize (line 3086) | func (s *testEncoder) CalcByteSize(value reflect.Value) (int, error) {
method WriteToBytes (line 3091) | func (s *testEncoder) WriteToBytes(value reflect.Value, offset int, by...
type testStreamEncoder (line 3117) | type testStreamEncoder struct
method Code (line 3121) | func (s *testStreamEncoder) Code() int8 {
method Type (line 3125) | func (s *testStreamEncoder) Type() reflect.Type {
method Write (line 3129) | func (s *testStreamEncoder) Write(w ext.StreamWriter, value reflect.Va...
type Ext2Struct (line 3185) | type Ext2Struct struct
type Ext2Int (line 3188) | type Ext2Int
constant testExt2DecoderCode (line 3191) | testExt2DecoderCode = 3
constant testExt2EncoderCode (line 3192) | testExt2EncoderCode = -3
type testExt2Decoder (line 3195) | type testExt2Decoder struct
method Code (line 3199) | func (td *testExt2Decoder) Code() int8 {
method IsType (line 3203) | func (td *testExt2Decoder) IsType(_ int, _ *[]byte) bool {
method AsValue (line 3207) | func (td *testExt2Decoder) AsValue(_ int, k reflect.Kind, _ *[]byte) (...
type testExt2StreamDecoder (line 3211) | type testExt2StreamDecoder struct
method Code (line 3215) | func (td *testExt2StreamDecoder) Code() int8 {
method IsType (line 3219) | func (td *testExt2StreamDecoder) IsType(_ byte, _ int8, _ int) bool {
method ToValue (line 3223) | func (td *testExt2StreamDecoder) ToValue(_ byte, _ []byte, k reflect.K...
type testExt2Encoder (line 3227) | type testExt2Encoder struct
method Code (line 3233) | func (s *testExt2Encoder) Code() int8 {
method Type (line 3237) | func (s *testExt2Encoder) Type() reflect.Type {
method CalcByteSize (line 3241) | func (s *testExt2Encoder) CalcByteSize(_ reflect.Value) (int, error) {
method WriteToBytes (line 3245) | func (s *testExt2Encoder) WriteToBytes(_ reflect.Value, offset int, _ ...
type testExt2StreamEncoder (line 3249) | type testExt2StreamEncoder struct
method Code (line 3253) | func (s *testExt2StreamEncoder) Code() int8 {
method Type (line 3257) | func (s *testExt2StreamEncoder) Type() reflect.Type {
method Write (line 3261) | func (s *testExt2StreamEncoder) Write(_ ext.StreamWriter, _ reflect.Va...
type Issue44Struct1 (line 3267) | type Issue44Struct1 struct
type Issue44Struct2 (line 3273) | type Issue44Struct2 struct
type Issue44Struct3 (line 3282) | type Issue44Struct3 struct
type Issue44Struct4 (line 3288) | type Issue44Struct4 struct
function TestIssue44 (line 3298) | func TestIssue44(t *testing.T) {
type checker (line 3394) | type checker
type marshaller (line 3395) | type marshaller
type unmarshaller (line 3396) | type unmarshaller
type encdecArg (line 3421) | type encdecArg struct
function encdec (line 3431) | func encdec[T any](t *testing.T, args ...encdecArg[T]) {
function getValue (line 3488) | func getValue(v interface{}) interface{} {
function equalCheck (line 3502) | func equalCheck(in, out interface{}) error {
function NoError (line 3511) | func NoError(t *testing.T, err error) {
function ErrorContains (line 3518) | func ErrorContains(t *testing.T, err error, errStr string) {
FILE: time/decode.go
type timeDecoder (line 17) | type timeDecoder struct
method Code (line 23) | func (td *timeDecoder) Code() int8 {
method readSize1Safe (line 27) | func (td *timeDecoder) readSize1Safe(index int, d *[]byte) (byte, int,...
method readSize4Safe (line 35) | func (td *timeDecoder) readSize4Safe(index int, d *[]byte) ([]byte, in...
method readSize8Safe (line 43) | func (td *timeDecoder) readSize8Safe(index int, d *[]byte) ([]byte, in...
method IsType (line 51) | func (td *timeDecoder) IsType(offset int, d *[]byte) bool {
method AsValue (line 91) | func (td *timeDecoder) AsValue(offset int, k reflect.Kind, d *[]byte) ...
FILE: time/decode_stream.go
type timeStreamDecoder (line 15) | type timeStreamDecoder struct
method Code (line 19) | func (td *timeStreamDecoder) Code() int8 {
method IsType (line 23) | func (td *timeStreamDecoder) IsType(code byte, innerType int8, dataLen...
method ToValue (line 33) | func (td *timeStreamDecoder) ToValue(code byte, data []byte, k reflect...
FILE: time/decode_stream_test.go
function TestStreamDecodeCode (line 13) | func TestStreamDecodeCode(t *testing.T) {
function TestStreamDecodeIsType (line 19) | func TestStreamDecodeIsType(t *testing.T) {
function TestStreamDecodeToValueFixext4 (line 96) | func TestStreamDecodeToValueFixext4(t *testing.T) {
function TestStreamDecodeToValueFixext8 (line 137) | func TestStreamDecodeToValueFixext8(t *testing.T) {
function TestStreamDecodeToValueExt8 (line 185) | func TestStreamDecodeToValueExt8(t *testing.T) {
function TestStreamDecodeToValueErrors (line 226) | func TestStreamDecodeToValueErrors(t *testing.T) {
function TestStreamDecodeToValueTooShort (line 260) | func TestStreamDecodeToValueTooShort(t *testing.T) {
function TestStreamDecodeTimezone (line 281) | func TestStreamDecodeTimezone(t *testing.T) {
function TestStreamDecodeRoundTrip (line 363) | func TestStreamDecodeRoundTrip(t *testing.T) {
FILE: time/decode_test.go
function TestDecodeCode (line 13) | func TestDecodeCode(t *testing.T) {
function TestDecodeIsType (line 19) | func TestDecodeIsType(t *testing.T) {
function TestDecodeIsTypeShortInput (line 78) | func TestDecodeIsTypeShortInput(t *testing.T) {
function TestDecodeAsValueFixext4 (line 102) | func TestDecodeAsValueFixext4(t *testing.T) {
function TestDecodeAsValueFixext8 (line 147) | func TestDecodeAsValueFixext8(t *testing.T) {
function TestDecodeAsValueExt8 (line 199) | func TestDecodeAsValueExt8(t *testing.T) {
function TestDecodeAsValueErrors (line 245) | func TestDecodeAsValueErrors(t *testing.T) {
function TestDecodeAsValueTooShort (line 285) | func TestDecodeAsValueTooShort(t *testing.T) {
function TestDecodeTimezone (line 310) | func TestDecodeTimezone(t *testing.T) {
function TestDecodeRoundTrip (line 396) | func TestDecodeRoundTrip(t *testing.T) {
FILE: time/encode.go
type timeEncoder (line 13) | type timeEncoder struct
method Code (line 19) | func (td *timeEncoder) Code() int8 {
method Type (line 23) | func (s *timeEncoder) Type() reflect.Type {
method CalcByteSize (line 27) | func (s *timeEncoder) CalcByteSize(value reflect.Value) (int, error) {
method WriteToBytes (line 41) | func (s *timeEncoder) WriteToBytes(value reflect.Value, offset int, by...
FILE: time/encode_stream.go
type timeStreamEncoder (line 13) | type timeStreamEncoder struct
method Code (line 17) | func (timeStreamEncoder) Code() int8 {
method Type (line 21) | func (timeStreamEncoder) Type() reflect.Type {
method Write (line 25) | func (e timeStreamEncoder) Write(w ext.StreamWriter, value reflect.Val...
FILE: time/encode_stream_test.go
function TestStreamCode (line 17) | func TestStreamCode(t *testing.T) {
function TestStreamType (line 23) | func TestStreamType(t *testing.T) {
function TestStreamWrite (line 30) | func TestStreamWrite(t *testing.T) {
function TestStreamWriteEdgeCases (line 111) | func TestStreamWriteEdgeCases(t *testing.T) {
function TestStreamEncodedDataAccuracy (line 164) | func TestStreamEncodedDataAccuracy(t *testing.T) {
function TestStreamWriteWithVariousNanoseconds (line 226) | func TestStreamWriteWithVariousNanoseconds(t *testing.T) {
type testErrWriter (line 282) | type testErrWriter struct
method Write (line 287) | func (w *testErrWriter) Write(p []byte) (n int, err error) {
function TestStreamWriteErrors (line 294) | func TestStreamWriteErrors(t *testing.T) {
FILE: time/encode_test.go
function TestCode (line 13) | func TestCode(t *testing.T) {
function TestType (line 19) | func TestType(t *testing.T) {
function TestCalcByteSize (line 26) | func TestCalcByteSize(t *testing.T) {
function TestEncodedDataAccuracy (line 76) | func TestEncodedDataAccuracy(t *testing.T) {
function TestWriteToBytes (line 130) | func TestWriteToBytes(t *testing.T) {
function TestWriteToBytesOffset (line 209) | func TestWriteToBytesOffset(t *testing.T) {
function TestWriteToBytesEdgeCases (line 230) | func TestWriteToBytesEdgeCases(t *testing.T) {
function TestWriteToBytesWithVariousNanoseconds (line 278) | func TestWriteToBytesWithVariousNanoseconds(t *testing.T) {
FILE: time/time.go
function SetDecodedAsLocal (line 6) | func SetDecodedAsLocal(b bool) {
FILE: unmarshal_ext_test.go
function TestUnmarshalTruncatedTimestampExtReturnsTooShort (line 11) | func TestUnmarshalTruncatedTimestampExtReturnsTooShort(t *testing.T) {
Condensed preview — 245 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (746K chars).
[
{
"path": ".github/release.yml",
"chars": 48,
"preview": "changelog:\n exclude:\n labels:\n - tagpr\n"
},
{
"path": ".github/workflows/stale.yml",
"chars": 719,
"preview": "name: Mark stale issues and pull requests\n\n# on:\n# schedule:\n# - cron: '30 11 * * *'\n\njobs:\n stale:\n runs-on: ub"
},
{
"path": ".github/workflows/tagpr.yml",
"chars": 367,
"preview": "name: tagpr\n\non:\n push:\n branches: [\"main\"]\n\njobs:\n tagpr:\n runs-on: ubuntu-latest\n permissions:\n conten"
},
{
"path": ".github/workflows/test.yml",
"chars": 1992,
"preview": "name: test\n\non: [push, pull_request]\n\nenv:\n GOPATH: ${{ github.workspace }}\n WORKSPACE: ${{ github.workspace }}/src/gi"
},
{
"path": ".gitignore",
"chars": 244,
"preview": "# Binaries for programs and plugins\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\n\n# Test binary, build with `go test -c`\n*.test\n\n# Ou"
},
{
"path": ".tagpr",
"chars": 138,
"preview": "[tagpr]\n releaseBranch = main\n versionFile = -\n vPrefix = true\n changelog = true\n release = true\n fixe"
},
{
"path": "CHANGELOG.md",
"chars": 599,
"preview": "# Changelog\n\n## [v3.1.1](https://github.com/shamaton/msgpack/compare/v3.1.0...v3.1.1) - 2026-05-12\n- chore: isolate form"
},
{
"path": "LICENSE",
"chars": 1073,
"preview": "MIT License\n\nCopyright (c) 2025 Masayuki Shamoto\n\nPermission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "README.md",
"chars": 3988,
"preview": "# MessagePack for Golang\n\n[](https://pkg.go.dev"
},
{
"path": "codecov.yml",
"chars": 51,
"preview": "coverage:\n status:\n project: off\n patch: off"
},
{
"path": "crash_test.go",
"chars": 1463,
"preview": "package msgpack_test\n\nimport (\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"sync\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack"
},
{
"path": "decode.go",
"chars": 1081,
"preview": "package msgpack\n\nimport (\n\t\"io\"\n\n\t\"github.com/shamaton/msgpack/v3/internal/decoding\"\n\tstreamdecoding \"github.com/shamato"
},
{
"path": "def/def.go",
"chars": 1153,
"preview": "package def\n\n// IntSize : 32 or 64\nconst IntSize = 32 << (^uint(0) >> 63)\n\nvar IsIntSize32 = IntSize == 32\n\n// message p"
},
{
"path": "def/error.go",
"chars": 1155,
"preview": "package def\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n)\n\nvar (\n\t// base errors\n\n\tErrMsgpack = errors.New(\"\")\n\n\t// decoding errors\n\n\tErr"
},
{
"path": "encode.go",
"chars": 997,
"preview": "package msgpack\n\nimport (\n\t\"io\"\n\n\t\"github.com/shamaton/msgpack/v3/internal/encoding\"\n\tstreamencoding \"github.com/shamato"
},
{
"path": "errors.go",
"chars": 152,
"preview": "package msgpack\n\nimport (\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\n// Error is used in all msgpack error as the based er"
},
{
"path": "ext/decode.go",
"chars": 2225,
"preview": "package ext\n\nimport (\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\n// Decoder defines an interface for decoding "
},
{
"path": "ext/decoder_stream.go",
"chars": 816,
"preview": "package ext\n\nimport (\n\t\"reflect\"\n)\n\n// StreamDecoder defines an interface for decoding streams of data.\n// It provides m"
},
{
"path": "ext/encode.go",
"chars": 5976,
"preview": "package ext\n\nimport (\n\t\"reflect\"\n)\n\n// Encoder defines an interface for encoding values into bytes.\n// It provides metho"
},
{
"path": "ext/encode_stream.go",
"chars": 3832,
"preview": "package ext\n\nimport (\n\t\"io\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/internal/common\"\n)\n\n// StreamEncoder is an inte"
},
{
"path": "go.mod",
"chars": 47,
"preview": "module github.com/shamaton/msgpack/v3\n\ngo 1.23\n"
},
{
"path": "internal/common/buffer.go",
"chars": 997,
"preview": "package common\n\nimport (\n\t\"io\"\n\t\"sync\"\n)\n\ntype Buffer struct {\n\tData []byte\n\tB1 []byte\n\tB2 []byte\n\tB4 []by"
},
{
"path": "internal/common/common.go",
"chars": 5059,
"preview": "package common\n\nimport (\n\t\"reflect\"\n\t\"strings\"\n)\n\n// Common is used encoding/decoding\ntype Common struct{}\n\n// FieldInfo"
},
{
"path": "internal/common/common_test.go",
"chars": 1879,
"preview": "package common\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\n\ttu \"github.com/shamaton/msgpack/v3/internal/common/testutil\"\n)\n\nfunc Te"
},
{
"path": "internal/common/testutil/reader.go",
"chars": 652,
"preview": "package testutil\n\nimport (\n\t\"errors\"\n\t\"io\"\n)\n\nvar ErrReaderErr = errors.New(\"reader error\")\n\ntype ErrReader struct{}\n\nfu"
},
{
"path": "internal/common/testutil/struct.go",
"chars": 1386,
"preview": "package testutil\n\nimport (\n\t\"math\"\n\t\"reflect\"\n\t\"strconv\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\n// CreateStruct retur"
},
{
"path": "internal/common/testutil/testutil.go",
"chars": 2160,
"preview": "package testutil\n\nimport (\n\t\"errors\"\n\t\"reflect\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc NoError(t *testing.T, err error) {\n\tt.Help"
},
{
"path": "internal/decoding/bin.go",
"chars": 1400,
"preview": "package decoding\n\nimport (\n\t\"encoding/binary\"\n\t\"reflect\"\n\t\"unsafe\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (d *de"
},
{
"path": "internal/decoding/bin_test.go",
"chars": 1951,
"preview": "package decoding\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\ttu \"github.com/shamaton/msgpack"
},
{
"path": "internal/decoding/bool.go",
"chars": 391,
"preview": "package decoding\n\nimport (\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (d *decoder) asBool(offset int, k r"
},
{
"path": "internal/decoding/bool_test.go",
"chars": 728,
"preview": "package decoding\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc Test_asBool(t *testing.T"
},
{
"path": "internal/decoding/complex.go",
"chars": 3072,
"preview": "package decoding\n\nimport (\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"math\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc ("
},
{
"path": "internal/decoding/complex_test.go",
"chars": 3656,
"preview": "package decoding\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc Test_asComplex64(t *test"
},
{
"path": "internal/decoding/decoding.go",
"chars": 6830,
"preview": "package decoding\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\t\"github.com/shamaton/msgpack/v3/int"
},
{
"path": "internal/decoding/decoding_test.go",
"chars": 16415,
"preview": "package decoding\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\ttu \"github.com/shamaton/msgpack"
},
{
"path": "internal/decoding/ext.go",
"chars": 4107,
"preview": "package decoding\n\nimport (\n\t\"encoding/binary\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\t\"github.com/shamaton/msgpack/v3/ex"
},
{
"path": "internal/decoding/ext_test.go",
"chars": 2278,
"preview": "package decoding\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\ttu \"github.com/shamaton/msgpack"
},
{
"path": "internal/decoding/float.go",
"chars": 2162,
"preview": "package decoding\n\nimport (\n\t\"encoding/binary\"\n\t\"math\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (d *deco"
},
{
"path": "internal/decoding/float_test.go",
"chars": 6564,
"preview": "package decoding\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc Test_asFloat32(t *testin"
},
{
"path": "internal/decoding/int.go",
"chars": 2624,
"preview": "package decoding\n\nimport (\n\t\"encoding/binary\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (d *decoder) isP"
},
{
"path": "internal/decoding/int_test.go",
"chars": 3425,
"preview": "package decoding\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc Test_asInt(t *testing.T)"
},
{
"path": "internal/decoding/interface.go",
"chars": 4292,
"preview": "package decoding\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (d *decoder) asInterface(off"
},
{
"path": "internal/decoding/interface_test.go",
"chars": 4283,
"preview": "package decoding\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\t\"github.com/shamaton/msg"
},
{
"path": "internal/decoding/map.go",
"chars": 16960,
"preview": "package decoding\n\nimport (\n\t\"encoding/binary\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nvar (\n\ttypeMapStringI"
},
{
"path": "internal/decoding/map_test.go",
"chars": 14387,
"preview": "package decoding\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\ttu \"github.com/s"
},
{
"path": "internal/decoding/nil.go",
"chars": 129,
"preview": "package decoding\n\nimport \"github.com/shamaton/msgpack/v3/def\"\n\nfunc (d *decoder) isCodeNil(v byte) bool {\n\treturn def.Ni"
},
{
"path": "internal/decoding/read.go",
"chars": 755,
"preview": "package decoding\n\nimport (\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (d *decoder) readSize1(index int) (byte, int, e"
},
{
"path": "internal/decoding/slice.go",
"chars": 5346,
"preview": "package decoding\n\nimport (\n\t\"encoding/binary\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nvar (\n\ttypeIntSlice "
},
{
"path": "internal/decoding/slice_test.go",
"chars": 10061,
"preview": "package decoding\n\nimport (\n\t\"math\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\ttu \"github.com/shamaton"
},
{
"path": "internal/decoding/string.go",
"chars": 1847,
"preview": "package decoding\n\nimport (\n\t\"encoding/binary\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nvar (\n\temptyString = "
},
{
"path": "internal/decoding/string_test.go",
"chars": 2388,
"preview": "package decoding\n\nimport (\n\t\"math\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc Test_stringByteL"
},
{
"path": "internal/decoding/struct.go",
"chars": 9235,
"preview": "package decoding\n\nimport (\n\t\"encoding/binary\"\n\t\"reflect\"\n\t\"sync\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\ntype structCa"
},
{
"path": "internal/decoding/struct_test.go",
"chars": 10725,
"preview": "package decoding\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\ttu \"github.com/shamaton"
},
{
"path": "internal/decoding/uint.go",
"chars": 2084,
"preview": "package decoding\n\nimport (\n\t\"encoding/binary\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (d *decoder) asU"
},
{
"path": "internal/decoding/uint_test.go",
"chars": 2980,
"preview": "package decoding\n\nimport (\n\t\"math\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc Test_asUint(t *t"
},
{
"path": "internal/encoding/bool.go",
"chars": 296,
"preview": "package encoding\n\nimport \"github.com/shamaton/msgpack/v3/def\"\n\n//func (e *encoder) calcBool() int {\n//\treturn 0\n//}\n\nfun"
},
{
"path": "internal/encoding/byte.go",
"chars": 1024,
"preview": "package encoding\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nvar typeByte = reflect.Ty"
},
{
"path": "internal/encoding/byte_test.go",
"chars": 893,
"preview": "package encoding\n\nimport (\n\t\"math\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\ttu \"github.com/shamaton/msgpack/v3"
},
{
"path": "internal/encoding/complex.go",
"chars": 889,
"preview": "package encoding\n\nimport (\n\t\"math\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (e *encoder) calcComplex64() int {\n\tre"
},
{
"path": "internal/encoding/encoding.go",
"chars": 7380,
"preview": "package encoding\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\t\"github.com/shamaton/msgpac"
},
{
"path": "internal/encoding/encoding_test.go",
"chars": 4573,
"preview": "package encoding\n\nimport (\n\t\"math\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\ttu \"github.c"
},
{
"path": "internal/encoding/ext.go",
"chars": 2138,
"preview": "package encoding\n\nimport (\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/ext\"\n\t\"github.com/shamaton/msgpack/v3/time\"\n)\n\nv"
},
{
"path": "internal/encoding/ext_test.go",
"chars": 444,
"preview": "package encoding\n\nimport (\n\t\"testing\"\n\n\ttu \"github.com/shamaton/msgpack/v3/internal/common/testutil\"\n\t\"github.com/shamat"
},
{
"path": "internal/encoding/float.go",
"chars": 611,
"preview": "package encoding\n\nimport (\n\t\"math\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (e *encoder) calcFloat32(_ float64) in"
},
{
"path": "internal/encoding/int.go",
"chars": 1221,
"preview": "package encoding\n\nimport (\n\t\"math\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (e *encoder) isNegativeFixInt64(v int6"
},
{
"path": "internal/encoding/map.go",
"chars": 13009,
"preview": "package encoding\n\nimport (\n\t\"math\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (e *encoder) calcFixedMap(r"
},
{
"path": "internal/encoding/nil.go",
"chars": 166,
"preview": "package encoding\n\nimport \"github.com/shamaton/msgpack/v3/def\"\n\nfunc (e *encoder) writeNil(offset int) int {\n\toffset = e."
},
{
"path": "internal/encoding/set.go",
"chars": 2277,
"preview": "package encoding\n\nfunc (e *encoder) setByte1Int64(value int64, offset int) int {\n\te.d[offset] = byte(value)\n\treturn offs"
},
{
"path": "internal/encoding/slice.go",
"chars": 4964,
"preview": "package encoding\n\nimport (\n\t\"math\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (e *encoder) calcFixedSlice"
},
{
"path": "internal/encoding/slice_test.go",
"chars": 1195,
"preview": "package encoding\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\n\ttu \"github.com/shamaton/msgpack/v3/internal/common/testutil\"\n)\n\nfunc "
},
{
"path": "internal/encoding/string.go",
"chars": 1028,
"preview": "package encoding\n\nimport (\n\t\"math\"\n\t\"unsafe\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (e *encoder) calcString(v st"
},
{
"path": "internal/encoding/struct.go",
"chars": 8734,
"preview": "package encoding\n\nimport (\n\t\"math\"\n\t\"reflect\"\n\t\"sync\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\t\"github.com/shamaton/msgpa"
},
{
"path": "internal/encoding/struct_test.go",
"chars": 5910,
"preview": "package encoding\n\nimport (\n\t\"math\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\ttu \"github.com/shamaton"
},
{
"path": "internal/encoding/uint.go",
"chars": 994,
"preview": "package encoding\n\nimport (\n\t\"math\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (e *encoder) calcUint(v uint64) int {\n"
},
{
"path": "internal/stream/decoding/bin.go",
"chars": 1245,
"preview": "package decoding\n\nimport (\n\t\"encoding/binary\"\n\t\"reflect\"\n\t\"unsafe\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (d *de"
},
{
"path": "internal/stream/decoding/bin_test.go",
"chars": 2348,
"preview": "package decoding\n\nimport (\n\t\"io\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\ttu \"github.com/shamaton/m"
},
{
"path": "internal/stream/decoding/bool.go",
"chars": 450,
"preview": "package decoding\n\nimport (\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (d *decoder) asBool(k reflect.Kind)"
},
{
"path": "internal/stream/decoding/bool_test.go",
"chars": 1143,
"preview": "package decoding\n\nimport (\n\t\"io\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc Test_asBool(t *tes"
},
{
"path": "internal/stream/decoding/complex.go",
"chars": 2622,
"preview": "package decoding\n\nimport (\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"math\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc ("
},
{
"path": "internal/stream/decoding/complex_test.go",
"chars": 4302,
"preview": "package decoding\n\nimport (\n\t\"io\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc Test_asComplex64(t"
},
{
"path": "internal/stream/decoding/decoding.go",
"chars": 6135,
"preview": "package decoding\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\t\"github.com/shamaton/msgpack/"
},
{
"path": "internal/stream/decoding/decoding_test.go",
"chars": 20625,
"preview": "package decoding\n\nimport (\n\t\"io\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\t\"github.com/shamaton/msgp"
},
{
"path": "internal/stream/decoding/ext.go",
"chars": 3016,
"preview": "package decoding\n\nimport (\n\t\"encoding/binary\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\t\"github.com/shamaton/msgpack/v3/ex"
},
{
"path": "internal/stream/decoding/ext_test.go",
"chars": 4508,
"preview": "package decoding\n\nimport (\n\t\"io\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\t\"github.com/shamaton/msgpack/v3/inte"
},
{
"path": "internal/stream/decoding/float.go",
"chars": 2142,
"preview": "package decoding\n\nimport (\n\t\"encoding/binary\"\n\t\"math\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (d *deco"
},
{
"path": "internal/stream/decoding/float_test.go",
"chars": 4427,
"preview": "package decoding\n\nimport (\n\t\"io\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc Test_asFloat32(t *"
},
{
"path": "internal/stream/decoding/int.go",
"chars": 2189,
"preview": "package decoding\n\nimport (\n\t\"encoding/binary\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (d *decoder) isP"
},
{
"path": "internal/stream/decoding/int_test.go",
"chars": 4343,
"preview": "package decoding\n\nimport (\n\t\"io\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc Test_asInt(t *test"
},
{
"path": "internal/stream/decoding/interface.go",
"chars": 3775,
"preview": "package decoding\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (d *decoder) asInterface(k r"
},
{
"path": "internal/stream/decoding/interface_test.go",
"chars": 5439,
"preview": "package decoding\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\t\"github.com/shamat"
},
{
"path": "internal/stream/decoding/map.go",
"chars": 14882,
"preview": "package decoding\n\nimport (\n\t\"encoding/binary\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nvar (\n\ttypeMapStringI"
},
{
"path": "internal/stream/decoding/map_test.go",
"chars": 16320,
"preview": "package decoding\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"math\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\ttu \"github"
},
{
"path": "internal/stream/decoding/nil.go",
"chars": 129,
"preview": "package decoding\n\nimport \"github.com/shamaton/msgpack/v3/def\"\n\nfunc (d *decoder) isCodeNil(v byte) bool {\n\treturn def.Ni"
},
{
"path": "internal/stream/decoding/read.go",
"chars": 1053,
"preview": "package decoding\n\nfunc (d *decoder) readSize1() (byte, error) {\n\tif _, err := d.r.Read(d.buf.B1); err != nil {\n\t\treturn "
},
{
"path": "internal/stream/decoding/slice.go",
"chars": 4472,
"preview": "package decoding\n\nimport (\n\t\"encoding/binary\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nvar (\n\ttypeIntSlice "
},
{
"path": "internal/stream/decoding/slice_test.go",
"chars": 10727,
"preview": "package decoding\n\nimport (\n\t\"io\"\n\t\"math\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\ttu \"github.com/sh"
},
{
"path": "internal/stream/decoding/string.go",
"chars": 1991,
"preview": "package decoding\n\nimport (\n\t\"encoding/binary\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nvar (\n\temptyString = "
},
{
"path": "internal/stream/decoding/string_test.go",
"chars": 3017,
"preview": "package decoding\n\nimport (\n\t\"io\"\n\t\"math\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc Test_strin"
},
{
"path": "internal/stream/decoding/struct.go",
"chars": 9569,
"preview": "package decoding\n\nimport (\n\t\"encoding/binary\"\n\t\"reflect\"\n\t\"sync\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\ntype structCa"
},
{
"path": "internal/stream/decoding/struct_test.go",
"chars": 16981,
"preview": "package decoding\n\nimport (\n\t\"io\"\n\t\"reflect\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\ttu \"github.com/sh"
},
{
"path": "internal/stream/decoding/uint.go",
"chars": 1678,
"preview": "package decoding\n\nimport (\n\t\"encoding/binary\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (d *decoder) asU"
},
{
"path": "internal/stream/decoding/uint_test.go",
"chars": 2616,
"preview": "package decoding\n\nimport (\n\t\"bytes\"\n\t\"io\"\n\t\"math\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\t\"github."
},
{
"path": "internal/stream/encoding/bool.go",
"chars": 186,
"preview": "package encoding\n\nimport \"github.com/shamaton/msgpack/v3/def\"\n\nfunc (e *encoder) writeBool(v bool) error {\n\tif v {\n\t\tret"
},
{
"path": "internal/stream/encoding/bool_test.go",
"chars": 501,
"preview": "package encoding\n\nimport (\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc Test_asBool(t *testing.T) {\n\tmethod"
},
{
"path": "internal/stream/encoding/byte.go",
"chars": 780,
"preview": "package encoding\n\nimport (\n\t\"math\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nvar typeByte = reflect.TypeOf(by"
},
{
"path": "internal/stream/encoding/byte_test.go",
"chars": 1602,
"preview": "package encoding\n\nimport (\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc Test_writeByteSliceLength(t *testin"
},
{
"path": "internal/stream/encoding/complex.go",
"chars": 875,
"preview": "package encoding\n\nimport (\n\t\"math\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (e *encoder) writeComplex64(v complex6"
},
{
"path": "internal/stream/encoding/complex_test.go",
"chars": 2411,
"preview": "package encoding\n\nimport (\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc Test_writeComplex64(t *testing.T) {"
},
{
"path": "internal/stream/encoding/encoding.go",
"chars": 3504,
"preview": "package encoding\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\t\"github.com/shamaton/msgpack/"
},
{
"path": "internal/stream/encoding/encoding_test.go",
"chars": 20421,
"preview": "package encoding\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"io\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\t\"githu"
},
{
"path": "internal/stream/encoding/ext.go",
"chars": 969,
"preview": "package encoding\n\nimport (\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/ext\"\n\t\"github.com/shamaton/msgpack/v3/time\"\n)\n\nv"
},
{
"path": "internal/stream/encoding/ext_test.go",
"chars": 456,
"preview": "package encoding\n\nimport (\n\t\"testing\"\n\n\ttu \"github.com/shamaton/msgpack/v3/internal/common/testutil\"\n\t\"github.com/shamat"
},
{
"path": "internal/stream/encoding/float.go",
"chars": 517,
"preview": "package encoding\n\nimport (\n\t\"math\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (e *encoder) writeFloat32(v float64) e"
},
{
"path": "internal/stream/encoding/float_test.go",
"chars": 1361,
"preview": "package encoding\n\nimport (\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc Test_writeFloat32(t *testing.T) {\n\t"
},
{
"path": "internal/stream/encoding/int.go",
"chars": 1071,
"preview": "package encoding\n\nimport (\n\t\"math\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (e *encoder) isNegativeFixInt64(v int6"
},
{
"path": "internal/stream/encoding/int_test.go",
"chars": 2751,
"preview": "package encoding\n\nimport (\n\t\"math\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc Test_asInt(t *testing.T) {\n"
},
{
"path": "internal/stream/encoding/map.go",
"chars": 8934,
"preview": "package encoding\n\nimport (\n\t\"math\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (e *encoder) writeMapLength"
},
{
"path": "internal/stream/encoding/map_test.go",
"chars": 28383,
"preview": "package encoding\n\nimport (\n\t\"math\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc Test_writeMapLen"
},
{
"path": "internal/stream/encoding/nil.go",
"chars": 133,
"preview": "package encoding\n\nimport \"github.com/shamaton/msgpack/v3/def\"\n\nfunc (e *encoder) writeNil() error {\n\treturn e.setByte1In"
},
{
"path": "internal/stream/encoding/set.go",
"chars": 1659,
"preview": "package encoding\n\nfunc (e *encoder) setByte1Int64(value int64) error {\n\treturn e.buf.Write(e.w, byte(value))\n}\n\nfunc (e "
},
{
"path": "internal/stream/encoding/slice.go",
"chars": 2691,
"preview": "package encoding\n\nimport (\n\t\"math\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (e *encoder) writeSliceLeng"
},
{
"path": "internal/stream/encoding/slice_test.go",
"chars": 9037,
"preview": "package encoding\n\nimport (\n\t\"math\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc Test_writeSliceL"
},
{
"path": "internal/stream/encoding/string.go",
"chars": 806,
"preview": "package encoding\n\nimport (\n\t\"math\"\n\t\"unsafe\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (e *encoder) writeString(str"
},
{
"path": "internal/stream/encoding/string_test.go",
"chars": 2406,
"preview": "package encoding\n\nimport (\n\t\"math\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc Test_writeString"
},
{
"path": "internal/stream/encoding/struct.go",
"chars": 5661,
"preview": "package encoding\n\nimport (\n\t\"math\"\n\t\"reflect\"\n\t\"sync\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\t\"github.com/shamaton/msgpa"
},
{
"path": "internal/stream/encoding/struct_test.go",
"chars": 8100,
"preview": "package encoding\n\nimport (\n\t\"math\"\n\t\"reflect\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\ttu \"github.com/"
},
{
"path": "internal/stream/encoding/uint.go",
"chars": 871,
"preview": "package encoding\n\nimport (\n\t\"math\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc (e *encoder) writeUint(v uint64) error"
},
{
"path": "internal/stream/encoding/uint_test.go",
"chars": 2505,
"preview": "package encoding\n\nimport (\n\t\"math\"\n\t\"testing\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n)\n\nfunc Test_asUint(t *testing.T) {"
},
{
"path": "msgpack.go",
"chars": 2868,
"preview": "package msgpack\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\n\t\"github.com/shamaton/msgpack/v3/def\"\n\t\"github.com/shamaton/msgpack/v3/ext\"\n\t\"gi"
},
{
"path": "msgpack_example_test.go",
"chars": 4568,
"preview": "package msgpack_test\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"net\"\n\t\"reflect\"\n\n\t\"github.com/shamaton/msgpack/v3\"\n\t\"github.com/shamato"
},
{
"path": "msgpack_test.go",
"chars": 77245,
"preview": "package msgpack_test\n\nimport (\n\t\"bytes\"\n\t\"encoding/binary\"\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"math\"\n\t\"m"
},
{
"path": "testdata/crashers/007424b0caabdaf653d7efeb3ce6c1c127f628c6",
"chars": 7,
"preview": "0000000"
},
{
"path": "testdata/crashers/01d1844ec3cdec0e8d60d81fcded73f920270e9c",
"chars": 6,
"preview": "000000"
},
{
"path": "testdata/crashers/049b2af75fc4ee7160c7ea9bad41a5167b501d32",
"chars": 3,
"preview": "000"
},
{
"path": "testdata/crashers/051d081de15ae4680b4156046787aae72ae0adcc",
"chars": 1,
"preview": "0"
},
{
"path": "testdata/crashers/063fea9d12105a80ee56a482aac428543fcf8d49",
"chars": 13,
"preview": "0000000000000"
},
{
"path": "testdata/crashers/080c57e02ab7e704e2a2e93aad7674a574dc9d69",
"chars": 9,
"preview": "000000000"
},
{
"path": "testdata/crashers/0d45579ce9ef9c1ca6e945d3f21ad31097f0c3c0",
"chars": 25,
"preview": "0000000000000000000000000"
},
{
"path": "testdata/crashers/0f7994b18fb75394c81005c925dd1ae153ad57ad",
"chars": 3,
"preview": "000"
},
{
"path": "testdata/crashers/121a9af889bd4ca2266be5a4f680d3bead8d02d6",
"chars": 0,
"preview": ""
},
{
"path": "testdata/crashers/19eb9972c2a406f15bbae850ac33b42ebd88f7a7",
"chars": 11,
"preview": "00000000000"
},
{
"path": "testdata/crashers/1a3492dbf0b80d08f12ce49c620239e48b74c08c",
"chars": 10,
"preview": "0000000000"
},
{
"path": "testdata/crashers/1ae8bba51072f9ff2bdf587596cfb0edf8a5cd12",
"chars": 37,
"preview": "0000000000000000000000000000000000000"
},
{
"path": "testdata/crashers/1b274070ce90f8ccdf0fc33a4afd4e1455766f8b",
"chars": 0,
"preview": ""
},
{
"path": "testdata/crashers/1d49f1635e901393bf65a263810508bea7ec9d51",
"chars": 2,
"preview": "00"
},
{
"path": "testdata/crashers/1e2c5c5ac7754f3e3fd858ce644b6621da2f4d03",
"chars": 10,
"preview": "0000000000"
},
{
"path": "testdata/crashers/236cfc19fdc31facdfe306e479a52bb3c08cb540",
"chars": 5,
"preview": "00000"
},
{
"path": "testdata/crashers/2478b7ed4fe72f5030a22146ecf365adba0dc780",
"chars": 4,
"preview": "0000"
},
{
"path": "testdata/crashers/24b5d7868ba6df6da0e26365e10fc15bcf72cca6",
"chars": 2,
"preview": "00"
},
{
"path": "testdata/crashers/255b827f8c0a593c5ee7610cdbd31c656f166a37",
"chars": 2,
"preview": "00"
},
{
"path": "testdata/crashers/2a8cbfc34aa4aefa008e9e18276e32fa5e8f56d8",
"chars": 4,
"preview": "0000"
},
{
"path": "testdata/crashers/2ba0c664eff181eeb2b101f60c5ca66397f4c386",
"chars": 5,
"preview": "00000"
},
{
"path": "testdata/crashers/2c34cfd27e783430e24c2af05361af3540b4d6ad",
"chars": 1,
"preview": "0"
},
{
"path": "testdata/crashers/2c4dd5af849b5cda2b7769dc52706e5fa746de73",
"chars": 2,
"preview": "00"
},
{
"path": "testdata/crashers/2cdb9f5adf53f1054ce8e6ceba007396ce6b734b",
"chars": 8,
"preview": "00000000"
},
{
"path": "testdata/crashers/30140397fe38ee61f01eff44b5cfa48285e47889",
"chars": 0,
"preview": ""
},
{
"path": "testdata/crashers/321500ed9a1796dca3d559d8f129ed31a8790035",
"chars": 21,
"preview": "000000000000000000000"
},
{
"path": "testdata/crashers/3219e4d65ac8671a452900514bc3c7aea2e71be3",
"chars": 29,
"preview": "00000000000000000000000000000"
},
{
"path": "testdata/crashers/36a5cc93968072de9d120643033589df4f316997",
"chars": 16,
"preview": "0000000000000000"
},
{
"path": "testdata/crashers/3abe9a29f2b95f34da65d88b969e58f4b46b6309",
"chars": 19,
"preview": "0000000000000000000"
},
{
"path": "testdata/crashers/3e5a9e8b50fcdcbe08f8138de6b95b5cd5b69bf2",
"chars": 17,
"preview": "00000000000000000"
},
{
"path": "testdata/crashers/3f0062c38d031b015f1a8bb82bd370b65d5ca35a",
"chars": 16,
"preview": "0000000000000000"
},
{
"path": "testdata/crashers/4670a8e0d21a624c0d42fd6dc76ef408d2b4e195",
"chars": 1,
"preview": "0"
},
{
"path": "testdata/crashers/47393c214b8f5a3d3c098e3985d24bd1e8d82a85",
"chars": 6,
"preview": "000000"
},
{
"path": "testdata/crashers/48947b6f943721ce84ef81e887a16bde2759f7ab",
"chars": 36,
"preview": "000000000000000000000000000000000000"
},
{
"path": "testdata/crashers/49989f6a8875777519c822a92c821cbb95bfc360",
"chars": 9,
"preview": "000000000"
},
{
"path": "testdata/crashers/4aaffe149efbd0ab6f122a4dc6e9e9aa0a602799",
"chars": 14,
"preview": "00000000000000"
},
{
"path": "testdata/crashers/4b65bf83d9b292f65bb5d1b056d68a4811732ef3",
"chars": 1,
"preview": "0"
},
{
"path": "testdata/crashers/4c156cb396c967d81bf3615cbd5ba74221a9c622",
"chars": 41,
"preview": "NilBoolãIntМFloat32@I\u000eVFloat64\t!\u0012oStringf"
},
{
"path": "testdata/crashers/4fb8cfeaaac80a1c829b22a43089ef470bcfe5b8",
"chars": 0,
"preview": ""
},
{
"path": "testdata/crashers/502804b3665c5eb935d6f66e7677f75242f516bb",
"chars": 17,
"preview": "00000000000000000"
},
{
"path": "testdata/crashers/56ff31c3b76d37929e45071a36ca5aa0bc386e09",
"chars": 31,
"preview": "0000000000000000000000000000000"
},
{
"path": "testdata/crashers/5bc56c0f00870625b5016a8d242ebe5c2a58802b",
"chars": 26,
"preview": "00000000000000000000000000"
},
{
"path": "testdata/crashers/5e8c489081abe671d760e1840b526f43bc7e6aa3",
"chars": 42,
"preview": "000000000000000000000@I\u000eVFloat64\t!\u0012oString"
},
{
"path": "testdata/crashers/5ec02b6349403b523d33576c7e2de27fb345edf0",
"chars": 4,
"preview": "0000"
},
{
"path": "testdata/crashers/6351ed5a9ac9cbb709ad15b4193edb52b8d37e84",
"chars": 1,
"preview": "0"
},
{
"path": "testdata/crashers/673480b070ea0508c3510627c81a4b519fb7d2f5",
"chars": 1,
"preview": "0"
},
{
"path": "testdata/crashers/683f06bff1a62b73193352f06a7194f0bf60ffb8",
"chars": 21,
"preview": "000000000000000000000"
},
{
"path": "testdata/crashers/68a5e75e9b42928454b320fe8f64ea107e61f60f",
"chars": 6,
"preview": "000000"
},
{
"path": "testdata/crashers/68be1e92e40e77926e1d9a5c2d800da023f6a4e9",
"chars": 25,
"preview": "0000000000000000000000000"
},
{
"path": "testdata/crashers/6b7395dabfc4d5a76e276f222c64c4bf7771ffb7",
"chars": 11,
"preview": "00000000000"
},
{
"path": "testdata/crashers/707235f5352edef615d64d00d83fcf92c9dffa57",
"chars": 44,
"preview": "00000000000000000000000000000000000000000000"
},
{
"path": "testdata/crashers/71819c849b41ee2f4a5b08321b9fc8bf21326ddf",
"chars": 1,
"preview": "0"
},
{
"path": "testdata/crashers/730377e1be92f426661e434d4f1cf20a10e16991",
"chars": 2,
"preview": "00"
},
{
"path": "testdata/crashers/73728d128f628772a64990a72340d9fd7987e29b",
"chars": 1,
"preview": "0"
},
{
"path": "testdata/crashers/73cc8fe38acd489c2b1fed0a66222aac4e04cc98",
"chars": 20,
"preview": "00000000000000000000"
},
{
"path": "testdata/crashers/74fe2a4034b08b5ecb014b2596e7f21ab55ea729",
"chars": 0,
"preview": ""
},
{
"path": "testdata/crashers/79aed363731b28a60abf16190df3d60fd1d88e54",
"chars": 5,
"preview": "00000"
},
{
"path": "testdata/crashers/7a1d04a0253fbb956c8119c40dc917cb460dabb0",
"chars": 38,
"preview": "NilBool£Int\u0003Float32@I\u000eVFloat64\t!\u0012oStri"
},
{
"path": "testdata/crashers/7a96d469f87b8c0fa00a944669469db9c8246714",
"chars": 3,
"preview": "000"
},
{
"path": "testdata/crashers/7b21df3bb234142e7b2dfc81f84eb621f9c7a617",
"chars": 12,
"preview": "000000000000"
},
{
"path": "testdata/crashers/8611c05469f8e623e1e035e578d1d50ff2a54e11",
"chars": 4,
"preview": "0000"
},
{
"path": "testdata/crashers/861648845b817281bffa42d8ca1c46443cef5cd8",
"chars": 33,
"preview": "000000000000000000000000000000000"
},
{
"path": "testdata/crashers/86f9eb6ebcae33f4d3663f90adf430f6d7b5e57c",
"chars": 29,
"preview": "00000000000000000000000000000"
},
{
"path": "testdata/crashers/8a90278d26f66fd78e4e38da237c201707bf7ab3",
"chars": 4,
"preview": "0000"
},
{
"path": "testdata/crashers/8de4d4284d8227a753986639b1d6e698bc683d8a",
"chars": 27,
"preview": "000000000000000000000000000"
},
{
"path": "testdata/crashers/8e4cb24fea75d067b0d9a5598fdeb66490777000",
"chars": 33,
"preview": "000000000000000000000000000000000"
},
{
"path": "testdata/crashers/964ac50bf26ecb3d0253e5e288484776bbf0abdf",
"chars": 9,
"preview": "000000000"
},
{
"path": "testdata/crashers/98d2aa10f9c5e6d9b1a6fb3dcc6583aa5631882a",
"chars": 7,
"preview": "0000000"
},
{
"path": "testdata/crashers/9ae8dabd9621f44592757414f83d26df04e55bca",
"chars": 27,
"preview": "000000000000000000000000000"
}
]
// ... and 45 more files (download for full content)
About this extraction
This page contains the full source code of the shamaton/msgpack GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 245 files (619.5 KB), approximately 221.9k tokens, and a symbol index with 674 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.