用户登录和接口鉴权
This commit is contained in:
32
vendor/github.com/ugorji/go/codec/README.md
generated
vendored
32
vendor/github.com/ugorji/go/codec/README.md
generated
vendored
@@ -80,32 +80,6 @@ Rich Feature Set includes:
|
||||
rpc server/client codec to support msgpack-rpc protocol defined at:
|
||||
https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md
|
||||
|
||||
# Supported build tags
|
||||
|
||||
We gain performance by code-generating fast-paths for slices and maps of built-in types,
|
||||
and monomorphizing generic code explicitly so we gain inlining and de-virtualization benefits.
|
||||
|
||||
The results are 20-40% performance improvements.
|
||||
|
||||
Building and running is configured using build tags as below.
|
||||
|
||||
At runtime:
|
||||
|
||||
- codec.safe: run in safe mode (not using unsafe optimizations)
|
||||
- codec.notmono: use generics code (bypassing performance-boosting monomorphized code)
|
||||
- codec.notfastpath: skip fast path code for slices and maps of built-in types (number, bool, string, bytes)
|
||||
|
||||
Each of these "runtime" tags have a convenience synonym i.e. safe, notmono, notfastpath.
|
||||
Pls use these mostly during development - use codec.XXX in your go files.
|
||||
|
||||
Build only:
|
||||
|
||||
- codec.build: used to generate fastpath and monomorphization code
|
||||
|
||||
Test only:
|
||||
|
||||
- codec.notmammoth: skip the mammoth generated tests
|
||||
|
||||
# Extension Support
|
||||
|
||||
Users can register a function to handle the encoding or decoding of their custom
|
||||
@@ -245,12 +219,6 @@ You can run the tag 'codec.safe' to run tests or build in safe mode. e.g.
|
||||
go test -tags "alltests codec.safe" -run Suite
|
||||
```
|
||||
|
||||
You can run the tag 'codec.notmono' to build bypassing the monomorphized code e.g.
|
||||
|
||||
```
|
||||
go test -tags codec.notmono -run Json
|
||||
```
|
||||
|
||||
# Running Benchmarks
|
||||
|
||||
```
|
||||
|
||||
999
vendor/github.com/ugorji/go/codec/binc.go
generated
vendored
999
vendor/github.com/ugorji/go/codec/binc.go
generated
vendored
File diff suppressed because it is too large
Load Diff
351
vendor/github.com/ugorji/go/codec/build.sh
generated
vendored
351
vendor/github.com/ugorji/go/codec/build.sh
generated
vendored
@@ -1,61 +1,232 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Build and Run the different test permutations.
|
||||
# This helps validate that nothing gets broken.
|
||||
# Run all the different permutations of all the tests and other things
|
||||
# This helps ensure that nothing gets broken.
|
||||
|
||||
_build_proceed() {
|
||||
# return success (0) if we should, and 1 (fail) if not
|
||||
if [[ "${zforce}" ]]; then return 0; fi
|
||||
for a in "fastpath.generated.go" "json.mono.generated.go"; do
|
||||
if [[ ! -e "$a" ]]; then return 0; fi
|
||||
for b in `ls -1 *.go.tmpl gen.go gen_mono.go values_test.go`; do
|
||||
if [[ "$a" -ot "$b" ]]; then return 0; fi
|
||||
done
|
||||
_tests() {
|
||||
local vet="" # TODO: make it off
|
||||
local gover=$( ${gocmd} version | cut -f 3 -d ' ' )
|
||||
[[ $( ${gocmd} version ) == *"gccgo"* ]] && zcover=0
|
||||
[[ $( ${gocmd} version ) == *"gollvm"* ]] && zcover=0
|
||||
case $gover in
|
||||
go1.[7-9]*|go1.1[0-9]*|go2.*|devel*) true ;;
|
||||
*) return 1
|
||||
esac
|
||||
# note that codecgen requires fastpath, so you cannot do "codecgen codec.notfastpath"
|
||||
# we test the following permutations wnich all execute different code paths as below.
|
||||
echo "TestCodecSuite: (fastpath/unsafe), (!fastpath/unsafe), (fastpath/!unsafe), (!fastpath/!unsafe), (codecgen/unsafe)"
|
||||
local echo=1
|
||||
local nc=2 # count
|
||||
local cpus="1,$(nproc)"
|
||||
# if using the race detector, then set nc to
|
||||
if [[ " ${zargs[@]} " =~ "-race" ]]; then
|
||||
cpus="$(nproc)"
|
||||
fi
|
||||
local a=( "" "codec.notfastpath" "codec.safe" "codec.notfastpath codec.safe" "codecgen" )
|
||||
local b=()
|
||||
local c=()
|
||||
for i in "${a[@]}"
|
||||
do
|
||||
local i2=${i:-default}
|
||||
[[ "$zwait" == "1" ]] && echo ">>>> TAGS: 'alltests $i'; RUN: 'TestCodecSuite'"
|
||||
[[ "$zcover" == "1" ]] && c=( -coverprofile "${i2// /-}.cov.out" )
|
||||
true &&
|
||||
${gocmd} vet -printfuncs "errorf" "$@" &&
|
||||
if [[ "$echo" == 1 ]]; then set -o xtrace; fi &&
|
||||
${gocmd} test ${zargs[*]} ${ztestargs[*]} -vet "$vet" -tags "alltests $i" -count $nc -cpu $cpus -run "TestCodecSuite" "${c[@]}" "$@" &
|
||||
if [[ "$echo" == 1 ]]; then set +o xtrace; fi
|
||||
b+=("${i2// /-}.cov.out")
|
||||
[[ "$zwait" == "1" ]] && wait
|
||||
|
||||
# if [[ "$?" != 0 ]]; then return 1; fi
|
||||
done
|
||||
return 1
|
||||
if [[ "$zextra" == "1" ]]; then
|
||||
[[ "$zwait" == "1" ]] && echo ">>>> TAGS: 'codec.notfastpath x'; RUN: 'Test.*X$'"
|
||||
[[ "$zcover" == "1" ]] && c=( -coverprofile "x.cov.out" )
|
||||
${gocmd} test ${zargs[*]} ${ztestargs[*]} -vet "$vet" -tags "codec.notfastpath x" -count $nc -run 'Test.*X$' "${c[@]}" &
|
||||
b+=("x.cov.out")
|
||||
[[ "$zwait" == "1" ]] && wait
|
||||
fi
|
||||
wait
|
||||
# go tool cover is not supported for gccgo, gollvm, other non-standard go compilers
|
||||
[[ "$zcover" == "1" ]] &&
|
||||
command -v gocovmerge &&
|
||||
gocovmerge "${b[@]}" > __merge.cov.out &&
|
||||
${gocmd} tool cover -html=__merge.cov.out
|
||||
}
|
||||
|
||||
# _build generates fastpath.go
|
||||
# is a generation needed?
|
||||
_ng() {
|
||||
local a="$1"
|
||||
if [[ ! -e "$a" ]]; then echo 1; return; fi
|
||||
for i in `ls -1 *.go.tmpl gen.go values_test.go`
|
||||
do
|
||||
if [[ "$a" -ot "$i" ]]; then echo 1; return; fi
|
||||
done
|
||||
}
|
||||
|
||||
_prependbt() {
|
||||
cat > ${2} <<EOF
|
||||
// +build generated
|
||||
|
||||
EOF
|
||||
cat ${1} >> ${2}
|
||||
rm -f ${1}
|
||||
}
|
||||
|
||||
# _build generates fast-path.go and gen-helper.go.
|
||||
_build() {
|
||||
# if ! [[ "${zforce}" || $(_ng "fastpath.generated.go") || $(_ng "json.mono.generated.go") ]]; then return 0; fi
|
||||
_build_proceed
|
||||
if [ $? -eq 1 ]; then return 0; fi
|
||||
if ! [[ "${zforce}" || $(_ng "fast-path.generated.go") || $(_ng "gen-helper.generated.go") || $(_ng "gen.generated.go") ]]; then return 0; fi
|
||||
|
||||
if [ "${zbak}" ]; then
|
||||
_zts=`date '+%m%d%Y_%H%M%S'`
|
||||
_gg=".generated.go"
|
||||
[ -e "fastpath${_gg}" ] && mv fastpath${_gg} fastpath${_gg}__${_zts}.bak
|
||||
[ -e "gen-helper${_gg}" ] && mv gen-helper${_gg} gen-helper${_gg}__${_zts}.bak
|
||||
[ -e "fast-path${_gg}" ] && mv fast-path${_gg} fast-path${_gg}__${_zts}.bak
|
||||
[ -e "gen${_gg}" ] && mv gen${_gg} gen${_gg}__${_zts}.bak
|
||||
fi
|
||||
|
||||
rm -f fast*path.generated.go *mono*generated.go *_generated_test.go gen-from-tmpl*.generated.go
|
||||
fi
|
||||
rm -f gen-helper.generated.go fast-path.generated.go gen.generated.go \
|
||||
*safe.generated.go *_generated_test.go *.generated_ffjson_expose.go
|
||||
|
||||
local btags="codec.build codec.notmono codec.safe codec.notfastpath"
|
||||
cat > gen.generated.go <<EOF
|
||||
// +build codecgen.exec
|
||||
|
||||
// Copyright (c) 2012-2020 Ugorji Nwoke. All rights reserved.
|
||||
// Use of this source code is governed by a MIT license found in the LICENSE file.
|
||||
|
||||
cat > gen-from-tmpl.codec.generated.go <<EOF
|
||||
package codec
|
||||
func GenTmplRun2Go(in, out string) { genTmplRun2Go(in, out) }
|
||||
func GenMonoAll() { genMonoAll() }
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS AUTO-GENERATED FROM gen-dec-(map|array).go.tmpl
|
||||
|
||||
const genDecMapTmpl = \`
|
||||
EOF
|
||||
cat >> gen.generated.go < gen-dec-map.go.tmpl
|
||||
cat >> gen.generated.go <<EOF
|
||||
\`
|
||||
|
||||
const genDecListTmpl = \`
|
||||
EOF
|
||||
cat >> gen.generated.go < gen-dec-array.go.tmpl
|
||||
cat >> gen.generated.go <<EOF
|
||||
\`
|
||||
|
||||
const genEncChanTmpl = \`
|
||||
EOF
|
||||
cat >> gen.generated.go < gen-enc-chan.go.tmpl
|
||||
cat >> gen.generated.go <<EOF
|
||||
\`
|
||||
EOF
|
||||
cat > gen-from-tmpl.codec.generated.go <<EOF
|
||||
package codec
|
||||
func GenRunTmpl2Go(in, out string) { genRunTmpl2Go(in, out) }
|
||||
func GenRunSortTmpl2Go(in, out string) { genRunSortTmpl2Go(in, out) }
|
||||
EOF
|
||||
|
||||
cat > gen-from-tmpl.generated.go <<EOF
|
||||
//go:build ignore
|
||||
# stub xxxRv and xxxRvSlice creation, before you create it
|
||||
cat > gen-from-tmpl.sort-slice-stubs.generated.go <<EOF
|
||||
// +build codecgen.sort_slice
|
||||
|
||||
package codec
|
||||
|
||||
import "reflect"
|
||||
import "time"
|
||||
|
||||
EOF
|
||||
|
||||
for i in string bool uint64 int64 float64 bytes time; do
|
||||
local i2=$i
|
||||
case $i in
|
||||
'time' ) i2="time.Time";;
|
||||
'bytes' ) i2="[]byte";;
|
||||
esac
|
||||
|
||||
cat >> gen-from-tmpl.sort-slice-stubs.generated.go <<EOF
|
||||
type ${i}Rv struct { v ${i2}; r reflect.Value }
|
||||
|
||||
type ${i}RvSlice []${i}Rv
|
||||
|
||||
func (${i}RvSlice) Len() int { return 0 }
|
||||
func (${i}RvSlice) Less(i, j int) bool { return false }
|
||||
func (${i}RvSlice) Swap(i, j int) {}
|
||||
|
||||
type ${i}Intf struct { v ${i2}; i interface{} }
|
||||
|
||||
type ${i}IntfSlice []${i}Intf
|
||||
|
||||
func (${i}IntfSlice) Len() int { return 0 }
|
||||
func (${i}IntfSlice) Less(i, j int) bool { return false }
|
||||
func (${i}IntfSlice) Swap(i, j int) {}
|
||||
|
||||
EOF
|
||||
done
|
||||
|
||||
sed -e 's+// __DO_NOT_REMOVE__NEEDED_FOR_REPLACING__IMPORT_PATH__FOR_CODEC_BENCH__+import . "github.com/ugorji/go/codec"+' \
|
||||
shared_test.go > bench/shared_test.go
|
||||
|
||||
# explicitly return 0 if this passes, else return 1
|
||||
local btags="codec.notfastpath codec.safe codecgen.exec"
|
||||
rm -f sort-slice.generated.go fast-path.generated.go gen-helper.generated.go mammoth_generated_test.go mammoth2_generated_test.go
|
||||
|
||||
cat > gen-from-tmpl.sort-slice.generated.go <<EOF
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import "${zpkg}"
|
||||
|
||||
func main() {
|
||||
codec.GenTmplRun2Go("fastpath.go.tmpl", "base.fastpath.generated.go")
|
||||
codec.GenTmplRun2Go("fastpath.notmono.go.tmpl", "base.fastpath.notmono.generated.go")
|
||||
codec.GenTmplRun2Go("mammoth_test.go.tmpl", "mammoth_generated_test.go")
|
||||
codec.GenMonoAll()
|
||||
codec.GenRunSortTmpl2Go("sort-slice.go.tmpl", "sort-slice.generated.go")
|
||||
}
|
||||
EOF
|
||||
|
||||
${gocmd} run -tags "$btags codecgen.sort_slice" gen-from-tmpl.sort-slice.generated.go || return 1
|
||||
rm -f gen-from-tmpl.sort-slice.generated.go
|
||||
|
||||
cat > gen-from-tmpl.generated.go <<EOF
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import "${zpkg}"
|
||||
|
||||
func main() {
|
||||
codec.GenRunTmpl2Go("fast-path.go.tmpl", "fast-path.generated.go")
|
||||
codec.GenRunTmpl2Go("gen-helper.go.tmpl", "gen-helper.generated.go")
|
||||
codec.GenRunTmpl2Go("mammoth-test.go.tmpl", "mammoth_generated_test.go")
|
||||
codec.GenRunTmpl2Go("mammoth2-test.go.tmpl", "mammoth2_generated_test.go")
|
||||
}
|
||||
EOF
|
||||
|
||||
# explicitly return 0 if this passes, else return 1
|
||||
${gocmd} run -tags "$btags" gen-from-tmpl.generated.go || return 1
|
||||
rm -f gen-from-tmpl*.generated.go
|
||||
rm -f gen-from-tmpl.generated.go
|
||||
|
||||
rm -f gen-from-tmpl.*generated.go
|
||||
return 0
|
||||
}
|
||||
|
||||
_codegenerators() {
|
||||
local c5="_generated_test.go"
|
||||
local c7="$PWD/codecgen"
|
||||
local c8="$c7/__codecgen"
|
||||
local c9="codecgen-scratch.go"
|
||||
|
||||
if ! [[ $zforce || $(_ng "values_codecgen${c5}") ]]; then return 0; fi
|
||||
|
||||
# Note: ensure you run the codecgen for this codebase/directory i.e. ./codecgen/codecgen
|
||||
true &&
|
||||
echo "codecgen ... " &&
|
||||
if [[ $zforce || ! -f "$c8" || "$c7/gen.go" -nt "$c8" ]]; then
|
||||
echo "rebuilding codecgen ... " && ( cd codecgen && ${gocmd} build -o $c8 ${zargs[*]} . )
|
||||
fi &&
|
||||
$c8 -rt 'codecgen' -t 'codecgen generated' -o "values_codecgen${c5}" -d 19780 "$zfin" "$zfin2" &&
|
||||
cp mammoth2_generated_test.go $c9 &&
|
||||
$c8 -t 'codecgen,!codec.notfastpath,!codec.notmammoth generated,!codec.notfastpath,!codec.notmammoth' -o "mammoth2_codecgen${c5}" -d 19781 "mammoth2_generated_test.go" &&
|
||||
rm -f $c9 &&
|
||||
echo "generators done!"
|
||||
}
|
||||
|
||||
_prebuild() {
|
||||
echo "prebuild: zforce: $zforce"
|
||||
local d="$PWD"
|
||||
local zfin="test_values.generated.go"
|
||||
local zfin2="test_values_flex.generated.go"
|
||||
@@ -65,12 +236,13 @@ _prebuild() {
|
||||
# zpkg=${d##*/src/}
|
||||
# zgobase=${d%%/src/*}
|
||||
# rm -f *_generated_test.go
|
||||
# if [[ $zforce ]]; then ${gocmd} install ${zargs[*]} .; fi &&
|
||||
true &&
|
||||
rm -f codecgen-*.go &&
|
||||
_build &&
|
||||
cp $d/values_test.go $d/$zfin &&
|
||||
cp $d/values_flex_test.go $d/$zfin2 &&
|
||||
_codegenerators &&
|
||||
if [[ "$(type -t _codegenerators_external )" = "function" ]]; then _codegenerators_external ; fi &&
|
||||
if [[ $zforce ]]; then ${gocmd} install ${zargs[*]} .; fi &&
|
||||
returncode=0 &&
|
||||
echo "prebuild done successfully"
|
||||
rm -f $d/$zfin $d/$zfin2
|
||||
@@ -79,67 +251,54 @@ _prebuild() {
|
||||
}
|
||||
|
||||
_make() {
|
||||
_prebuild && ${gocmd} install ${zargs[*]} .
|
||||
local makeforce=${zforce}
|
||||
zforce=1
|
||||
(cd codecgen && ${gocmd} install ${zargs[*]} .) && _prebuild && ${gocmd} install ${zargs[*]} .
|
||||
zforce=${makeforce}
|
||||
}
|
||||
|
||||
_clean() {
|
||||
rm -f \
|
||||
gen-from-tmpl.*generated.go \
|
||||
codecgen-*.go \
|
||||
test_values.generated.go test_values_flex.generated.go
|
||||
}
|
||||
|
||||
_tests_run_one() {
|
||||
local tt="alltests $i"
|
||||
local rr="TestCodecSuite"
|
||||
if [[ "x$i" == "xx" ]]; then tt="codec.notmono codec.notfastpath x"; rr='Test.*X$'; fi
|
||||
local g=( ${zargs[*]} ${ztestargs[*]} -count $nc -cpu $cpus -vet "$vet" -tags "$tt" -run "$rr" )
|
||||
[[ "$zcover" == "1" ]] && g+=( -cover )
|
||||
# g+=( -ti "$k" )
|
||||
g+=( -tdiff )
|
||||
[[ "$zcover" == "1" ]] && g+=( -test.gocoverdir $covdir )
|
||||
local -
|
||||
set -x
|
||||
${gocmd} test "${g[@]}" &
|
||||
}
|
||||
_release() {
|
||||
local reply
|
||||
read -p "Pre-release validation takes a few minutes and MUST be run from within GOPATH/src. Confirm y/n? " -n 1 -r reply
|
||||
echo
|
||||
if [[ ! $reply =~ ^[Yy]$ ]]; then return 1; fi
|
||||
|
||||
_tests() {
|
||||
local vet="" # TODO: make it off
|
||||
local gover=$( ${gocmd} version | cut -f 3 -d ' ' )
|
||||
# go tool cover is not supported for gccgo, gollvm, other non-standard go compilers
|
||||
[[ $( ${gocmd} version ) == *"gccgo"* ]] && zcover=0
|
||||
[[ $( ${gocmd} version ) == *"gollvm"* ]] && zcover=0
|
||||
case $gover in
|
||||
go1.2[0-9]*|go2.*|devel*) true ;;
|
||||
*) return 1
|
||||
esac
|
||||
# we test the following permutations wnich all execute different code paths as below.
|
||||
echo "TestCodecSuite: (fastpath/unsafe), (!fastpath/unsafe), (fastpath/!unsafe), (!fastpath/!unsafe)"
|
||||
local nc=2 # count
|
||||
local cpus="1,$(nproc)"
|
||||
# if using the race detector, then set nc to
|
||||
if [[ " ${zargs[@]} " =~ "-race" ]]; then
|
||||
cpus="$(nproc)"
|
||||
fi
|
||||
local covdir=""
|
||||
local a=( "" "codec.safe" "codec.notfastpath" "codec.safe codec.notfastpath"
|
||||
"codec.notmono" "codec.notmono codec.safe"
|
||||
"codec.notmono codec.notfastpath" "codec.notmono codec.safe codec.notfastpath" )
|
||||
[[ "$zextra" == "1" ]] && a+=( "x" )
|
||||
[[ "$zcover" == "1" ]] && covdir=`mktemp -d`
|
||||
${gocmd} vet -printfuncs "errorf" "$@" || return 1
|
||||
for i in "${a[@]}"; do
|
||||
local j=${i:-default}; j="${j// /-}"; j="${j//codec./}"
|
||||
[[ "$zwait" == "1" ]] && echo ">>>> TAGS: 'alltests $i'; RUN: 'TestCodecSuite'"
|
||||
_tests_run_one
|
||||
[[ "$zwait" == "1" ]] && wait
|
||||
# if [[ "$?" != 0 ]]; then return 1; fi
|
||||
# expects GOROOT, GOROOT_BOOTSTRAP to have been set.
|
||||
if [[ -z "${GOROOT// }" || -z "${GOROOT_BOOTSTRAP// }" ]]; then return 1; fi
|
||||
# (cd $GOROOT && git checkout -f master && git pull && git reset --hard)
|
||||
(cd $GOROOT && git pull)
|
||||
local f=`pwd`/make.release.out
|
||||
cat > $f <<EOF
|
||||
========== `date` ===========
|
||||
EOF
|
||||
# # go 1.6 and below kept giving memory errors on Mac OS X during SDK build or go run execution,
|
||||
# # that is fine, as we only explicitly test the last 3 releases and tip (2 years).
|
||||
local makeforce=${zforce}
|
||||
zforce=1
|
||||
for i in 1.10 1.11 1.12 master
|
||||
do
|
||||
echo "*********** $i ***********" >>$f
|
||||
if [[ "$i" != "master" ]]; then i="release-branch.go$i"; fi
|
||||
(false ||
|
||||
(echo "===== BUILDING GO SDK for branch: $i ... =====" &&
|
||||
cd $GOROOT &&
|
||||
git checkout -f $i && git reset --hard && git clean -f . &&
|
||||
cd src && ./make.bash >>$f 2>&1 && sleep 1 ) ) &&
|
||||
echo "===== GO SDK BUILD DONE =====" &&
|
||||
_prebuild &&
|
||||
echo "===== PREBUILD DONE with exit: $? =====" &&
|
||||
_tests "$@"
|
||||
if [[ "$?" != 0 ]]; then return 1; fi
|
||||
done
|
||||
wait
|
||||
[[ "$zcover" == "1" ]] &&
|
||||
echo "go tool covdata output" &&
|
||||
${gocmd} tool covdata percent -i $covdir &&
|
||||
${gocmd} tool covdata textfmt -i $covdir -o __cov.out &&
|
||||
${gocmd} tool cover -html=__cov.out
|
||||
zforce=${makeforce}
|
||||
echo "++++++++ RELEASE TEST SUITES ALL PASSED ++++++++"
|
||||
}
|
||||
|
||||
_usage() {
|
||||
@@ -147,10 +306,11 @@ _usage() {
|
||||
# -pf [p=prebuild (f=force)]
|
||||
|
||||
cat <<EOF
|
||||
primary usage: $0
|
||||
primary usage: $0
|
||||
-t[esow] -> t=tests [e=extra, s=short, o=cover, w=wait]
|
||||
-[md] -> [m=make, d=race detector]
|
||||
-v -> v=verbose (more v's to increase verbose level)
|
||||
-[n l i] -> [n=inlining diagnostics, l=mid-stack inlining, i=check inlining for path (path)]
|
||||
-v -> v=verbose
|
||||
EOF
|
||||
if [[ "$(type -t _usage_run)" = "function" ]]; then _usage_run ; fi
|
||||
}
|
||||
@@ -171,15 +331,15 @@ _main() {
|
||||
local gocmd=${MYGOCMD:-go}
|
||||
|
||||
OPTIND=1
|
||||
while getopts ":cetmnrgpfvldsowikxyz" flag
|
||||
while getopts ":cetmnrgpfvldsowkxyzi" flag
|
||||
do
|
||||
case "x$flag" in
|
||||
'xw') zwait=1 ;;
|
||||
'xv') zverbose+=(1) ;;
|
||||
'xo') zcover=1 ;;
|
||||
'xe') zextra=1 ;;
|
||||
'xw') zwait=1 ;;
|
||||
'xf') zforce=1 ;;
|
||||
'xs') ztestargs+=("-short") ;;
|
||||
'xv') zverbose+=(1) ;;
|
||||
'xl') zargs+=("-gcflags"); zargs+=("-l=4") ;;
|
||||
'xn') zargs+=("-gcflags"); zargs+=("-m=2") ;;
|
||||
'xd') zargs+=("-race") ;;
|
||||
@@ -197,23 +357,14 @@ _main() {
|
||||
'xg') _go ;;
|
||||
'xp') _prebuild "$@" ;;
|
||||
'xc') _clean "$@" ;;
|
||||
esac
|
||||
|
||||
# handle from local run.sh
|
||||
case "x$x" in
|
||||
'xi') _check_inlining_one "$@" ;;
|
||||
'xk') _go_compiler_validation_suite ;;
|
||||
'xx') _analyze_checks "$@" ;;
|
||||
'xy') _analyze_debug_types "$@" ;;
|
||||
'xz') _analyze_do_inlining_and_more "$@" ;;
|
||||
'xk') _go_compiler_validation_suite ;;
|
||||
'xi') _check_inlining_one "$@" ;;
|
||||
esac
|
||||
# unset zforce zargs zbenchflags
|
||||
}
|
||||
|
||||
[ "." = `dirname $0` ] && _main "$@"
|
||||
|
||||
# _xtrace() {
|
||||
# local -
|
||||
# set -x
|
||||
# "${@}"
|
||||
# }
|
||||
|
||||
931
vendor/github.com/ugorji/go/codec/cbor.go
generated
vendored
931
vendor/github.com/ugorji/go/codec/cbor.go
generated
vendored
File diff suppressed because it is too large
Load Diff
42
vendor/github.com/ugorji/go/codec/decimal.go
generated
vendored
42
vendor/github.com/ugorji/go/codec/decimal.go
generated
vendored
@@ -8,19 +8,6 @@ import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type readFloatResult struct {
|
||||
mantissa uint64
|
||||
exp int8
|
||||
neg bool
|
||||
trunc bool
|
||||
bad bool // bad decimal string
|
||||
hardexp bool // exponent is hard to handle (> 2 digits, etc)
|
||||
ok bool
|
||||
// sawdot bool
|
||||
// sawexp bool
|
||||
//_ [2]bool // padding
|
||||
}
|
||||
|
||||
// Per go spec, floats are represented in memory as
|
||||
// IEEE single or double precision floating point values.
|
||||
//
|
||||
@@ -247,10 +234,6 @@ func parseFloat64_custom(b []byte) (f float64, err error) {
|
||||
}
|
||||
|
||||
func parseUint64_simple(b []byte) (n uint64, ok bool) {
|
||||
if len(b) > 1 && b[0] == '0' { // punt on numbers with leading zeros
|
||||
return
|
||||
}
|
||||
|
||||
var i int
|
||||
var n1 uint64
|
||||
var c uint8
|
||||
@@ -373,6 +356,19 @@ func parseNumber(b []byte, z *fauxUnion, preferSignedInt bool) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
type readFloatResult struct {
|
||||
mantissa uint64
|
||||
exp int8
|
||||
neg bool
|
||||
trunc bool
|
||||
bad bool // bad decimal string
|
||||
hardexp bool // exponent is hard to handle (> 2 digits, etc)
|
||||
ok bool
|
||||
// sawdot bool
|
||||
// sawexp bool
|
||||
//_ [2]bool // padding
|
||||
}
|
||||
|
||||
func readFloat(s []byte, y floatinfo) (r readFloatResult) {
|
||||
var i uint // uint, so that we eliminate bounds checking
|
||||
var slen = uint(len(s))
|
||||
@@ -388,23 +384,13 @@ func readFloat(s []byte, y floatinfo) (r readFloatResult) {
|
||||
i++
|
||||
}
|
||||
|
||||
// considered punting early if string has length > maxMantDigits, but doesn't account
|
||||
// we considered punting early if string has length > maxMantDigits, but this doesn't account
|
||||
// for trailing 0's e.g. 700000000000000000000 can be encoded exactly as it is 7e20
|
||||
|
||||
var nd, ndMant, dp int8
|
||||
var sawdot, sawexp bool
|
||||
var xu uint64
|
||||
|
||||
if i+1 < slen && s[i] == '0' {
|
||||
switch s[i+1] {
|
||||
case '.', 'e', 'E':
|
||||
// ok
|
||||
default:
|
||||
r.bad = true
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
LOOP:
|
||||
for ; i < slen; i++ {
|
||||
switch s[i] {
|
||||
|
||||
2168
vendor/github.com/ugorji/go/codec/decode.go
generated
vendored
2168
vendor/github.com/ugorji/go/codec/decode.go
generated
vendored
File diff suppressed because it is too large
Load Diff
116
vendor/github.com/ugorji/go/codec/doc.go
generated
vendored
116
vendor/github.com/ugorji/go/codec/doc.go
generated
vendored
@@ -12,7 +12,7 @@ Supported Serialization formats are:
|
||||
- binc: http://github.com/ugorji/binc
|
||||
- cbor: http://cbor.io http://tools.ietf.org/html/rfc7049
|
||||
- json: http://json.org http://tools.ietf.org/html/rfc7159
|
||||
- simple: (unpublished)
|
||||
- simple:
|
||||
|
||||
This package will carefully use 'package unsafe' for performance reasons in specific places.
|
||||
You can build without unsafe use by passing the safe or appengine tag
|
||||
@@ -78,32 +78,6 @@ Rich Feature Set includes:
|
||||
msgpack-rpc protocol defined at:
|
||||
https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md
|
||||
|
||||
# Supported build tags
|
||||
|
||||
We gain performance by code-generating fast-paths for slices and maps of built-in types,
|
||||
and monomorphizing generic code explicitly so we gain inlining and de-virtualization benefits.
|
||||
|
||||
The results are 20-40% performance improvements.
|
||||
|
||||
Building and running is configured using build tags as below.
|
||||
|
||||
At runtime:
|
||||
|
||||
- codec.safe: run in safe mode (not using unsafe optimizations)
|
||||
- codec.notmono: use generics code (bypassing performance-boosting monomorphized code)
|
||||
- codec.notfastpath: skip fast path code for slices and maps of built-in types (number, bool, string, bytes)
|
||||
|
||||
Each of these "runtime" tags have a convenience synonym i.e. safe, notmono, notfastpath.
|
||||
Pls use these mostly during development - use codec.XXX in your go files.
|
||||
|
||||
Build only:
|
||||
|
||||
- codec.build: used to generate fastpath and monomorphization code
|
||||
|
||||
Test only:
|
||||
|
||||
- codec.notmammoth: skip the mammoth generated tests
|
||||
|
||||
# Extension Support
|
||||
|
||||
Users can register a function to handle the encoding or decoding of
|
||||
@@ -229,10 +203,6 @@ You can run the tag 'codec.safe' to run tests or build in safe mode. e.g.
|
||||
go test -tags codec.safe -run Json
|
||||
go test -tags "alltests codec.safe" -run Suite
|
||||
|
||||
You can run the tag 'codec.notmono' to build bypassing the monomorphized code e.g.
|
||||
|
||||
go test -tags codec.notmono -run Json
|
||||
|
||||
Running Benchmarks
|
||||
|
||||
cd bench
|
||||
@@ -255,87 +225,3 @@ Embedded fields are encoded as if they exist in the top-level struct,
|
||||
with some caveats. See Encode documentation.
|
||||
*/
|
||||
package codec
|
||||
|
||||
/*
|
||||
Generics
|
||||
|
||||
Generics are used across to board to reduce boilerplate, and hopefully
|
||||
improve performance by
|
||||
- reducing need for interface calls (de-virtualization)
|
||||
- resultant inlining of those calls
|
||||
|
||||
encoder/decoder --> Driver (json/cbor/...) --> input/output (bytes or io abstraction)
|
||||
|
||||
There are 2 * 5 * 2 (20) combinations of monomorphized values.
|
||||
|
||||
Key rules
|
||||
- do not use top-level generic functions.
|
||||
Due to type inference, monomorphizing them proves challenging
|
||||
- only use generic methods.
|
||||
Monomorphizing is done at the type once, and method names need not change
|
||||
- do not have method calls have a parameter of an encWriter or decReader.
|
||||
All those calls are handled directly by the driver.
|
||||
- Include a helper type for each parameterized thing, and add all generic functions to them e.g.
|
||||
helperEncWriter[T encWriter]
|
||||
helperEncReader[T decReader]
|
||||
helperEncDriver[T encDriver]
|
||||
helperDecDriver[T decDriver]
|
||||
- Always use T as the generic type name (when needed)
|
||||
- No inline types
|
||||
- No closures taking parameters of generic types
|
||||
|
||||
*/
|
||||
/*
|
||||
Naming convention:
|
||||
|
||||
Currently, as generic and non-generic types/functions/vars are put in the same files,
|
||||
we suffer because:
|
||||
- build takes longer as non-generic code is built when a build tag wants only monomorphised code
|
||||
- files have many lines which are not used at runtime (due to type parameters)
|
||||
- code coverage is inaccurate on a single run
|
||||
|
||||
To resolve this, we are streamlining our file naming strategy.
|
||||
|
||||
Basically, we will have the following nomenclature for filenames:
|
||||
- fastpath (tag:notfastpath): *.notfastpath.*.go vs *.fastpath.*.go
|
||||
- typed parameters (tag:notmono): *.notmono.*.go vs *.mono.*.go
|
||||
- safe (tag:safe): *.safe.*.go vs *.unsafe.go
|
||||
- generated files: *.generated.go
|
||||
- all others (tags:N/A): *.go without safe/mono/fastpath/generated in the name
|
||||
|
||||
The following files will be affected and split/renamed accordingly
|
||||
|
||||
Base files:
|
||||
- binc.go
|
||||
- cbor.go
|
||||
- json.go
|
||||
- msgpack.go
|
||||
- simple.go
|
||||
- decode.go
|
||||
- encode.go
|
||||
|
||||
For each base file, split into __file__.go (containing type parameters) and __file__.base.go.
|
||||
__file__.go will only build with notmono.
|
||||
|
||||
Other files:
|
||||
- fastpath.generated.go -> base.fastpath.generated.go and base.fastpath.notmono.generated.go
|
||||
- fastpath.not.go -> base.notfastpath.go
|
||||
- init.go -> init.notmono.go
|
||||
|
||||
Appropriate build tags will be included in the files, and the right ones only used for
|
||||
monomorphization.
|
||||
*/
|
||||
/*
|
||||
Caching Handle options for fast runtime use
|
||||
|
||||
If using cached values from Handle options, then
|
||||
- re-cache them at each reset() call
|
||||
- reset is always called at the start of each (Must)(En|De)code
|
||||
- which calls (en|de)coder.reset([]byte|io.Reader|String)
|
||||
- which calls (en|de)cDriver.reset()
|
||||
- at reset, (en|de)c(oder|Driver) can re-cache Handle options before each run
|
||||
|
||||
Some examples:
|
||||
- json: e.rawext,di,d,ks,is / d.rawext
|
||||
- decode: (decoderBase) d.jsms,mtr,str,
|
||||
*/
|
||||
|
||||
1660
vendor/github.com/ugorji/go/codec/encode.go
generated
vendored
1660
vendor/github.com/ugorji/go/codec/encode.go
generated
vendored
File diff suppressed because it is too large
Load Diff
2670
vendor/github.com/ugorji/go/codec/gen.go
generated
vendored
2670
vendor/github.com/ugorji/go/codec/gen.go
generated
vendored
File diff suppressed because it is too large
Load Diff
1752
vendor/github.com/ugorji/go/codec/helper.go
generated
vendored
1752
vendor/github.com/ugorji/go/codec/helper.go
generated
vendored
File diff suppressed because it is too large
Load Diff
256
vendor/github.com/ugorji/go/codec/helper_not_unsafe.go
generated
vendored
256
vendor/github.com/ugorji/go/codec/helper_not_unsafe.go
generated
vendored
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT license found in the LICENSE file.
|
||||
|
||||
//go:build !go1.9 || safe || codec.safe || appengine
|
||||
// +build !go1.9 safe codec.safe appengine
|
||||
|
||||
package codec
|
||||
|
||||
@@ -18,11 +19,8 @@ import (
|
||||
|
||||
const safeMode = true
|
||||
|
||||
func isTransientType4Size(size uint32) bool { return true }
|
||||
|
||||
type mapReqParams struct{}
|
||||
|
||||
func getMapReqParams(ti *typeInfo) (r mapReqParams) { return }
|
||||
const transientSizeMax = 0
|
||||
const transientValueHasStringSlice = true
|
||||
|
||||
func byteAt(b []byte, index uint) byte {
|
||||
return b[index]
|
||||
@@ -32,6 +30,14 @@ func setByteAt(b []byte, index uint, val byte) {
|
||||
b[index] = val
|
||||
}
|
||||
|
||||
func byteSliceOf(b []byte, start, end uint) []byte {
|
||||
return b[start:end]
|
||||
}
|
||||
|
||||
// func byteSliceWithLen(b []byte, length uint) []byte {
|
||||
// return b[:length]
|
||||
// }
|
||||
|
||||
func stringView(v []byte) string {
|
||||
return string(v)
|
||||
}
|
||||
@@ -44,24 +50,32 @@ func byteSliceSameData(v1 []byte, v2 []byte) bool {
|
||||
return cap(v1) != 0 && cap(v2) != 0 && &(v1[:1][0]) == &(v2[:1][0])
|
||||
}
|
||||
|
||||
func isNil(v interface{}, checkPtr bool) (rv reflect.Value, b bool) {
|
||||
b = v == nil
|
||||
if b || !checkPtr {
|
||||
return
|
||||
}
|
||||
rv = reflect.ValueOf(v)
|
||||
if rv.Kind() == reflect.Ptr {
|
||||
b = rv.IsNil()
|
||||
}
|
||||
func okBytes2(b []byte) (v [2]byte) {
|
||||
copy(v[:], b)
|
||||
return
|
||||
}
|
||||
|
||||
func ptrToLowLevel(v interface{}) interface{} {
|
||||
return v
|
||||
func okBytes3(b []byte) (v [3]byte) {
|
||||
copy(v[:], b)
|
||||
return
|
||||
}
|
||||
|
||||
func lowLevelToPtr[T any](v interface{}) *T {
|
||||
return v.(*T)
|
||||
func okBytes4(b []byte) (v [4]byte) {
|
||||
copy(v[:], b)
|
||||
return
|
||||
}
|
||||
|
||||
func okBytes8(b []byte) (v [8]byte) {
|
||||
copy(v[:], b)
|
||||
return
|
||||
}
|
||||
|
||||
func isNil(v interface{}) (rv reflect.Value, isnil bool) {
|
||||
rv = reflect.ValueOf(v)
|
||||
if isnilBitset.isset(byte(rv.Kind())) {
|
||||
isnil = rv.IsNil()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func eq4i(i0, i1 interface{}) bool {
|
||||
@@ -71,21 +85,17 @@ func eq4i(i0, i1 interface{}) bool {
|
||||
func rv4iptr(i interface{}) reflect.Value { return reflect.ValueOf(i) }
|
||||
func rv4istr(i interface{}) reflect.Value { return reflect.ValueOf(i) }
|
||||
|
||||
// func rv4i(i interface{}) reflect.Value { return reflect.ValueOf(i) }
|
||||
// func rv4iK(i interface{}, kind byte, isref bool) reflect.Value { return reflect.ValueOf(i) }
|
||||
|
||||
func rv2i(rv reflect.Value) interface{} {
|
||||
if rv.IsValid() {
|
||||
return rv.Interface()
|
||||
}
|
||||
return nil
|
||||
return rv.Interface()
|
||||
}
|
||||
|
||||
func rvAddr(rv reflect.Value, ptrType reflect.Type) reflect.Value {
|
||||
return rv.Addr()
|
||||
}
|
||||
|
||||
func rvPtrIsNil(rv reflect.Value) bool {
|
||||
return rv.IsNil()
|
||||
}
|
||||
|
||||
func rvIsNil(rv reflect.Value) bool {
|
||||
return rv.IsNil()
|
||||
}
|
||||
@@ -121,30 +131,6 @@ func i2rtid(i interface{}) uintptr {
|
||||
|
||||
// --------------------------
|
||||
|
||||
// is this an empty interface/ptr/struct/map/slice/chan/array
|
||||
func isEmptyContainerValue(v reflect.Value, tinfos *TypeInfos, recursive bool) (empty bool) {
|
||||
switch v.Kind() {
|
||||
case reflect.Array:
|
||||
for i, vlen := 0, v.Len(); i < vlen; i++ {
|
||||
if !isEmptyValue(v.Index(i), tinfos, false) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
case reflect.Map, reflect.Slice, reflect.Chan:
|
||||
return v.IsNil() || v.Len() == 0
|
||||
case reflect.Interface, reflect.Ptr:
|
||||
empty = v.IsNil()
|
||||
if recursive && !empty {
|
||||
return isEmptyValue(v.Elem(), tinfos, recursive)
|
||||
}
|
||||
return empty
|
||||
case reflect.Struct:
|
||||
return isEmptyStruct(v, tinfos, recursive)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isEmptyValue(v reflect.Value, tinfos *TypeInfos, recursive bool) bool {
|
||||
switch v.Kind() {
|
||||
case reflect.Invalid:
|
||||
@@ -229,7 +215,7 @@ func isEmptyStruct(v reflect.Value, tinfos *TypeInfos, recursive bool) bool {
|
||||
// We only care about what we can encode/decode,
|
||||
// so that is what we use to check omitEmpty.
|
||||
for _, si := range ti.sfi.source() {
|
||||
sfv := si.fieldNoAlloc(v, true)
|
||||
sfv := si.path.field(v)
|
||||
if sfv.IsValid() && !isEmptyValue(sfv, tinfos, recursive) {
|
||||
return false
|
||||
}
|
||||
@@ -237,10 +223,6 @@ func isEmptyStruct(v reflect.Value, tinfos *TypeInfos, recursive bool) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func makeMapReflect(t reflect.Type, size int) reflect.Value {
|
||||
return reflect.MakeMapWithSize(t, size)
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
|
||||
type perTypeElem struct {
|
||||
@@ -265,9 +247,13 @@ type perType struct {
|
||||
v []perTypeElem
|
||||
}
|
||||
|
||||
type decPerType = perType
|
||||
type decPerType struct {
|
||||
perType
|
||||
}
|
||||
|
||||
type encPerType = perType
|
||||
type encPerType struct {
|
||||
perType
|
||||
}
|
||||
|
||||
func (x *perType) elem(t reflect.Type) *perTypeElem {
|
||||
rtid := rt2id(t)
|
||||
@@ -309,44 +295,10 @@ func (x *perType) AddressableRO(v reflect.Value) (rv reflect.Value) {
|
||||
return
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
type mapIter struct {
|
||||
t *reflect.MapIter
|
||||
m reflect.Value
|
||||
values bool
|
||||
}
|
||||
|
||||
func (t *mapIter) Next() (r bool) {
|
||||
return t.t.Next()
|
||||
}
|
||||
|
||||
func (t *mapIter) Key() reflect.Value {
|
||||
return t.t.Key()
|
||||
}
|
||||
|
||||
func (t *mapIter) Value() (r reflect.Value) {
|
||||
if t.values {
|
||||
return t.t.Value()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (t *mapIter) Done() {}
|
||||
|
||||
func mapRange(t *mapIter, m, k, v reflect.Value, values bool) {
|
||||
*t = mapIter{
|
||||
m: m,
|
||||
t: m.MapRange(),
|
||||
values: values,
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
type structFieldInfos struct {
|
||||
c []*structFieldInfo
|
||||
s []*structFieldInfo
|
||||
t uint8To32TrieNode
|
||||
// byName map[string]*structFieldInfo // find sfi given a name
|
||||
}
|
||||
|
||||
func (x *structFieldInfos) load(source, sorted []*structFieldInfo) {
|
||||
@@ -354,24 +306,55 @@ func (x *structFieldInfos) load(source, sorted []*structFieldInfo) {
|
||||
x.s = sorted
|
||||
}
|
||||
|
||||
// func (x *structFieldInfos) count() int { return len(x.c) }
|
||||
func (x *structFieldInfos) source() (v []*structFieldInfo) { return x.c }
|
||||
func (x *structFieldInfos) sorted() (v []*structFieldInfo) { return x.s }
|
||||
func (x *structFieldInfos) source() (v []*structFieldInfo) { return x.c }
|
||||
|
||||
// --------------------------
|
||||
|
||||
type uint8To32TrieNodeNoKids struct {
|
||||
key uint8
|
||||
valid bool // the value marks the end of a full stored string
|
||||
_ [2]byte // padding
|
||||
value uint32
|
||||
type atomicClsErr struct {
|
||||
v atomic.Value
|
||||
}
|
||||
|
||||
type uint8To32TrieNodeKids = []uint8To32TrieNode
|
||||
func (x *atomicClsErr) load() (e clsErr) {
|
||||
if i := x.v.Load(); i != nil {
|
||||
e = i.(clsErr)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (x *uint8To32TrieNode) setKids(kids []uint8To32TrieNode) { x.kids = kids }
|
||||
func (x *uint8To32TrieNode) getKids() []uint8To32TrieNode { return x.kids }
|
||||
func (x *uint8To32TrieNode) truncKids() { x.kids = x.kids[:0] } // set len to 0
|
||||
func (x *atomicClsErr) store(p clsErr) {
|
||||
x.v.Store(p)
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
type atomicTypeInfoSlice struct {
|
||||
v atomic.Value
|
||||
}
|
||||
|
||||
func (x *atomicTypeInfoSlice) load() (e []rtid2ti) {
|
||||
if i := x.v.Load(); i != nil {
|
||||
e = i.([]rtid2ti)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (x *atomicTypeInfoSlice) store(p []rtid2ti) {
|
||||
x.v.Store(p)
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
type atomicRtidFnSlice struct {
|
||||
v atomic.Value
|
||||
}
|
||||
|
||||
func (x *atomicRtidFnSlice) load() (e []codecRtidFn) {
|
||||
if i := x.v.Load(); i != nil {
|
||||
e = i.([]codecRtidFn)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (x *atomicRtidFnSlice) store(p []codecRtidFn) {
|
||||
x.v.Store(p)
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
func (n *fauxUnion) ru() reflect.Value {
|
||||
@@ -518,13 +501,13 @@ func rvGrowSlice(rv reflect.Value, ti *typeInfo, cap, incr int) (v reflect.Value
|
||||
|
||||
// ----------------
|
||||
|
||||
func rvArrayIndex(rv reflect.Value, i int, _ *typeInfo, _ bool) reflect.Value {
|
||||
func rvSliceIndex(rv reflect.Value, i int, ti *typeInfo) reflect.Value {
|
||||
return rv.Index(i)
|
||||
}
|
||||
|
||||
// func rvArrayIndex(rv reflect.Value, i int, ti *typeInfo) reflect.Value {
|
||||
// return rv.Index(i)
|
||||
// }
|
||||
func rvArrayIndex(rv reflect.Value, i int, ti *typeInfo) reflect.Value {
|
||||
return rv.Index(i)
|
||||
}
|
||||
|
||||
func rvSliceZeroCap(t reflect.Type) (v reflect.Value) {
|
||||
return reflect.MakeSlice(t, 0, 0)
|
||||
@@ -540,7 +523,7 @@ func rvCapSlice(rv reflect.Value) int {
|
||||
|
||||
func rvGetArrayBytes(rv reflect.Value, scratch []byte) (bs []byte) {
|
||||
l := rv.Len()
|
||||
if scratch == nil && rv.CanAddr() {
|
||||
if scratch == nil || rv.CanAddr() {
|
||||
return rv.Slice(0, l).Bytes()
|
||||
}
|
||||
|
||||
@@ -554,7 +537,7 @@ func rvGetArrayBytes(rv reflect.Value, scratch []byte) (bs []byte) {
|
||||
}
|
||||
|
||||
func rvGetArray4Slice(rv reflect.Value) (v reflect.Value) {
|
||||
v = rvZeroAddrK(reflect.ArrayOf(rvLenSlice(rv), rv.Type().Elem()), reflect.Array)
|
||||
v = rvZeroAddrK(reflectArrayOf(rvLenSlice(rv), rv.Type().Elem()), reflect.Array)
|
||||
reflect.Copy(v, rv)
|
||||
return
|
||||
}
|
||||
@@ -664,43 +647,60 @@ func rvLenMap(rv reflect.Value) int {
|
||||
return rv.Len()
|
||||
}
|
||||
|
||||
// func copybytes(to, from []byte) int {
|
||||
// return copy(to, from)
|
||||
// }
|
||||
|
||||
// func copybytestr(to []byte, from string) int {
|
||||
// return copy(to, from)
|
||||
// }
|
||||
|
||||
// func rvLenArray(rv reflect.Value) int { return rv.Len() }
|
||||
|
||||
// ------------ map range and map indexing ----------
|
||||
|
||||
func mapSet(m, k, v reflect.Value, _ mapReqParams) {
|
||||
func mapStoresElemIndirect(elemsize uintptr) bool { return false }
|
||||
|
||||
func mapSet(m, k, v reflect.Value, keyFastKind mapKeyFastKind, _, _ bool) {
|
||||
m.SetMapIndex(k, v)
|
||||
}
|
||||
|
||||
func mapGet(m, k, v reflect.Value, _ mapReqParams) (vv reflect.Value) {
|
||||
func mapGet(m, k, v reflect.Value, keyFastKind mapKeyFastKind, _, _ bool) (vv reflect.Value) {
|
||||
return m.MapIndex(k)
|
||||
}
|
||||
|
||||
// func mapDelete(m, k reflect.Value) {
|
||||
// m.SetMapIndex(k, reflect.Value{})
|
||||
// }
|
||||
|
||||
func mapAddrLoopvarRV(t reflect.Type, k reflect.Kind) (r reflect.Value) {
|
||||
return // reflect.New(t).Elem()
|
||||
}
|
||||
|
||||
// ---------- ENCODER optimized ---------------
|
||||
|
||||
func (d *decoderBase) bytes2Str(in []byte, att dBytesAttachState) (s string, mutable bool) {
|
||||
return d.detach2Str(in, att), false
|
||||
func (e *Encoder) jsondriver() *jsonEncDriver {
|
||||
return e.e.(*jsonEncDriver)
|
||||
}
|
||||
|
||||
// ---------- DECODER optimized ---------------
|
||||
|
||||
func (d *Decoder) jsondriver() *jsonDecDriver {
|
||||
return d.d.(*jsonDecDriver)
|
||||
}
|
||||
|
||||
func (d *Decoder) stringZC(v []byte) (s string) {
|
||||
return d.string(v)
|
||||
}
|
||||
|
||||
func (d *Decoder) mapKeyString(callFnRvk *bool, kstrbs, kstr2bs *[]byte) string {
|
||||
return d.string(*kstr2bs)
|
||||
}
|
||||
|
||||
// ---------- structFieldInfo optimized ---------------
|
||||
|
||||
func (n *structFieldInfoNode) rvField(v reflect.Value) reflect.Value {
|
||||
func (n *structFieldInfoPathNode) rvField(v reflect.Value) reflect.Value {
|
||||
return v.Field(int(n.index))
|
||||
}
|
||||
|
||||
// ---------- others ---------------
|
||||
|
||||
// --------------------------
|
||||
type atomicRtidFnSlice struct {
|
||||
v atomic.Value
|
||||
}
|
||||
|
||||
func (x *atomicRtidFnSlice) load() interface{} {
|
||||
return x.v.Load()
|
||||
}
|
||||
|
||||
func (x *atomicRtidFnSlice) store(p interface{}) {
|
||||
x.v.Store(p)
|
||||
}
|
||||
|
||||
580
vendor/github.com/ugorji/go/codec/helper_unsafe.go
generated
vendored
580
vendor/github.com/ugorji/go/codec/helper_unsafe.go
generated
vendored
@@ -1,15 +1,12 @@
|
||||
// Copyright (c) 2012-2020 Ugorji Nwoke. All rights reserved.
|
||||
// Use of this source code is governed by a MIT license found in the LICENSE file.
|
||||
|
||||
//go:build !safe && !codec.safe && !appengine && go1.21
|
||||
//go:build !safe && !codec.safe && !appengine && go1.9
|
||||
// +build !safe,!codec.safe,!appengine,go1.9
|
||||
|
||||
// minimum of go 1.21 is needed, as that is the minimum for all features and linked functions we need
|
||||
// - typedmemclr : go1.8
|
||||
// - mapassign_fastXXX: go1.9
|
||||
// - clear was added in go1.21
|
||||
// - unsafe.String(Data): go1.20
|
||||
// - unsafe.Add: go1.17
|
||||
// - generics/any: go1.18
|
||||
// minimum of go 1.9 is needed, as that is the minimum for all features and linked functions we need
|
||||
// - typedmemclr was introduced in go 1.8
|
||||
// - mapassign_fastXXX was introduced in go 1.9
|
||||
// etc
|
||||
|
||||
package codec
|
||||
@@ -24,7 +21,7 @@ import (
|
||||
|
||||
// This file has unsafe variants of some helper functions.
|
||||
// MARKER: See helper_unsafe.go for the usage documentation.
|
||||
//
|
||||
|
||||
// There are a number of helper_*unsafe*.go files.
|
||||
//
|
||||
// - helper_unsafe
|
||||
@@ -44,32 +41,19 @@ import (
|
||||
// As of March 2021, we cannot differentiate whether running with gccgo or gollvm
|
||||
// using a build constraint, as both satisfy 'gccgo' build tag.
|
||||
// Consequently, we must use the lowest common denominator to support both.
|
||||
//
|
||||
|
||||
// For reflect.Value code, we decided to do the following:
|
||||
// - if we know the kind, we can elide conditional checks for
|
||||
// - SetXXX (Int, Uint, String, Bool, etc)
|
||||
// - SetLen
|
||||
//
|
||||
// We can also optimize many others, incl IsNil, etc
|
||||
//
|
||||
// We can also optimize
|
||||
// - IsNil
|
||||
|
||||
// MARKER: Some functions here will not be hit during code coverage runs due to optimizations, e.g.
|
||||
// - rvCopySlice: called by decode if rvGrowSlice did not set new slice into pointer to orig slice.
|
||||
// however, helper_unsafe sets it, so no need to call rvCopySlice later
|
||||
// - rvSlice: same as above
|
||||
//
|
||||
// MARKER: Handling flagIndir ----
|
||||
//
|
||||
// flagIndir means that the reflect.Value holds a pointer to the data itself.
|
||||
//
|
||||
// flagIndir can be set for:
|
||||
// - references
|
||||
// Here, type.IfaceIndir() --> false
|
||||
// flagIndir is usually false (except when the value is addressable, where in flagIndir may be true)
|
||||
// - everything else (numbers, bools, string, slice, struct, etc).
|
||||
// Here, type.IfaceIndir() --> true
|
||||
// flagIndir is always true
|
||||
//
|
||||
// This knowlege is used across this file, e.g. in rv2i and rvRefPtr
|
||||
|
||||
const safeMode = false
|
||||
|
||||
@@ -104,9 +88,7 @@ const (
|
||||
const transientSizeMax = 64
|
||||
|
||||
// should struct/array support internal strings and slices?
|
||||
// const transientValueHasStringSlice = false
|
||||
|
||||
func isTransientType4Size(size uint32) bool { return size <= transientSizeMax }
|
||||
const transientValueHasStringSlice = false
|
||||
|
||||
type unsafeString struct {
|
||||
Data unsafe.Pointer
|
||||
@@ -162,8 +144,7 @@ func (x *unsafePerTypeElem) addrFor(k reflect.Kind) unsafe.Pointer {
|
||||
x.slice = unsafeSlice{} // memclr
|
||||
return unsafe.Pointer(&x.slice)
|
||||
}
|
||||
clear(x.arr[:])
|
||||
// x.arr = [transientSizeMax]byte{} // memclr
|
||||
x.arr = [transientSizeMax]byte{} // memclr
|
||||
return unsafe.Pointer(&x.arr)
|
||||
}
|
||||
|
||||
@@ -171,7 +152,9 @@ type perType struct {
|
||||
elems [2]unsafePerTypeElem
|
||||
}
|
||||
|
||||
type decPerType = perType
|
||||
type decPerType struct {
|
||||
perType
|
||||
}
|
||||
|
||||
type encPerType struct{}
|
||||
|
||||
@@ -200,6 +183,19 @@ func byteAt(b []byte, index uint) byte {
|
||||
return *(*byte)(unsafe.Pointer(uintptr((*unsafeSlice)(unsafe.Pointer(&b)).Data) + uintptr(index)))
|
||||
}
|
||||
|
||||
func byteSliceOf(b []byte, start, end uint) []byte {
|
||||
s := (*unsafeSlice)(unsafe.Pointer(&b))
|
||||
s.Data = unsafe.Pointer(uintptr(s.Data) + uintptr(start))
|
||||
s.Len = int(end - start)
|
||||
s.Cap -= int(start)
|
||||
return b
|
||||
}
|
||||
|
||||
// func byteSliceWithLen(b []byte, length uint) []byte {
|
||||
// (*unsafeSlice)(unsafe.Pointer(&b)).Len = int(length)
|
||||
// return b
|
||||
// }
|
||||
|
||||
func setByteAt(b []byte, index uint, val byte) {
|
||||
// b[index] = val
|
||||
*(*byte)(unsafe.Pointer(uintptr((*unsafeSlice)(unsafe.Pointer(&b)).Data) + uintptr(index))) = val
|
||||
@@ -226,26 +222,49 @@ func byteSliceSameData(v1 []byte, v2 []byte) bool {
|
||||
return (*unsafeSlice)(unsafe.Pointer(&v1)).Data == (*unsafeSlice)(unsafe.Pointer(&v2)).Data
|
||||
}
|
||||
|
||||
// isNil checks - without much effort - if an interface is nil.
|
||||
//
|
||||
// returned rv is not guaranteed to be valid (e.g. if v == nil).
|
||||
//
|
||||
// Note that this will handle all pointer-sized types e.g.
|
||||
// pointer, map, chan, func, etc.
|
||||
func isNil(v interface{}, checkPtr bool) (rv reflect.Value, b bool) {
|
||||
b = ((*unsafeIntf)(unsafe.Pointer(&v))).ptr == nil
|
||||
// MARKER: okBytesN functions will copy N bytes into the top slots of the return array.
|
||||
// These functions expect that the bound check already occured and are are valid.
|
||||
// copy(...) does a number of checks which are unnecessary in this situation when in bounds.
|
||||
|
||||
func okBytes2(b []byte) [2]byte {
|
||||
return *((*[2]byte)(((*unsafeSlice)(unsafe.Pointer(&b))).Data))
|
||||
}
|
||||
|
||||
func okBytes3(b []byte) [3]byte {
|
||||
return *((*[3]byte)(((*unsafeSlice)(unsafe.Pointer(&b))).Data))
|
||||
}
|
||||
|
||||
func okBytes4(b []byte) [4]byte {
|
||||
return *((*[4]byte)(((*unsafeSlice)(unsafe.Pointer(&b))).Data))
|
||||
}
|
||||
|
||||
func okBytes8(b []byte) [8]byte {
|
||||
return *((*[8]byte)(((*unsafeSlice)(unsafe.Pointer(&b))).Data))
|
||||
}
|
||||
|
||||
// isNil says whether the value v is nil.
|
||||
// This applies to references like map/ptr/unsafepointer/chan/func,
|
||||
// and non-reference values like interface/slice.
|
||||
func isNil(v interface{}) (rv reflect.Value, isnil bool) {
|
||||
var ui = (*unsafeIntf)(unsafe.Pointer(&v))
|
||||
isnil = ui.ptr == nil
|
||||
if !isnil {
|
||||
rv, isnil = unsafeIsNilIntfOrSlice(ui, v)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ptrToLowLevel[T any](ptr *T) unsafe.Pointer {
|
||||
return unsafe.Pointer(ptr)
|
||||
func unsafeIsNilIntfOrSlice(ui *unsafeIntf, v interface{}) (rv reflect.Value, isnil bool) {
|
||||
rv = reflect.ValueOf(v) // reflect.ValueOf is currently not inline'able - so call it directly
|
||||
tk := rv.Kind()
|
||||
isnil = (tk == reflect.Interface || tk == reflect.Slice) && *(*unsafe.Pointer)(ui.ptr) == nil
|
||||
return
|
||||
}
|
||||
|
||||
func lowLevelToPtr[T any](v unsafe.Pointer) *T {
|
||||
return (*T)(v)
|
||||
}
|
||||
|
||||
// Given that v is a reference (map/func/chan/ptr/unsafepointer) kind, return the pointer
|
||||
// return the pointer for a reference (map/chan/func/pointer/unsafe.Pointer).
|
||||
// true references (map, func, chan, ptr - NOT slice) may be double-referenced? as flagIndir
|
||||
//
|
||||
// Assumes that v is a reference (map/func/chan/ptr/func)
|
||||
func rvRefPtr(v *unsafeReflectValue) unsafe.Pointer {
|
||||
if v.flag&unsafeFlagIndir != 0 {
|
||||
return *(*unsafe.Pointer)(v.ptr)
|
||||
@@ -276,6 +295,13 @@ func rv4istr(i interface{}) (v reflect.Value) {
|
||||
}
|
||||
|
||||
func rv2i(rv reflect.Value) (i interface{}) {
|
||||
// We tap into implememtation details from
|
||||
// the source go stdlib reflect/value.go, and trims the implementation.
|
||||
//
|
||||
// e.g.
|
||||
// - a map/ptr is a reference, thus flagIndir is not set on it
|
||||
// - an int/slice is not a reference, thus flagIndir is set on it
|
||||
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
if refBitset.isset(byte(rv.Kind())) && urv.flag&unsafeFlagIndir != 0 {
|
||||
urv.ptr = *(*unsafe.Pointer)(urv.ptr)
|
||||
@@ -290,22 +316,12 @@ func rvAddr(rv reflect.Value, ptrType reflect.Type) reflect.Value {
|
||||
return rv
|
||||
}
|
||||
|
||||
// return true if this rv - got from a pointer kind - is nil.
|
||||
// For now, only use for struct fields of pointer types, as we're guaranteed
|
||||
// that flagIndir will never be set.
|
||||
func rvPtrIsNil(rv reflect.Value) bool {
|
||||
return rvIsNil(rv)
|
||||
}
|
||||
|
||||
// checks if a nil'able value is nil
|
||||
func rvIsNil(rv reflect.Value) bool {
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
if urv.flag&unsafeFlagIndir == 0 {
|
||||
return urv.ptr == nil
|
||||
if urv.flag&unsafeFlagIndir != 0 {
|
||||
return *(*unsafe.Pointer)(urv.ptr) == nil
|
||||
}
|
||||
// flagIndir is set for a reference (ptr/map/func/unsafepointer/chan)
|
||||
// OR kind is slice/interface
|
||||
return *(*unsafe.Pointer)(urv.ptr) == nil
|
||||
return urv.ptr == nil
|
||||
}
|
||||
|
||||
func rvSetSliceLen(rv reflect.Value, length int) {
|
||||
@@ -483,62 +499,29 @@ func isEmptyValueFallbackRecur(urv *unsafeReflectValue, v reflect.Value, tinfos
|
||||
return false
|
||||
}
|
||||
|
||||
// is this an empty interface/ptr/struct/map/slice/chan/array
|
||||
func isEmptyContainerValue(v reflect.Value, tinfos *TypeInfos, recursive bool) bool {
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&v))
|
||||
switch v.Kind() {
|
||||
case reflect.Slice:
|
||||
return (*unsafeSlice)(urv.ptr).Len == 0
|
||||
case reflect.Struct:
|
||||
if tinfos == nil {
|
||||
tinfos = defTypeInfos
|
||||
}
|
||||
ti := tinfos.find(uintptr(urv.typ))
|
||||
if ti == nil {
|
||||
ti = tinfos.load(v.Type())
|
||||
}
|
||||
return unsafeCmpZero(urv.ptr, int(ti.size))
|
||||
case reflect.Interface, reflect.Ptr:
|
||||
// isnil := urv.ptr == nil // (not sufficient, as a pointer value encodes the type)
|
||||
isnil := urv.ptr == nil || *(*unsafe.Pointer)(urv.ptr) == nil
|
||||
if recursive && !isnil {
|
||||
return isEmptyValue(v.Elem(), tinfos, recursive)
|
||||
}
|
||||
return isnil
|
||||
case reflect.Chan:
|
||||
return urv.ptr == nil || len_chan(rvRefPtr(urv)) == 0
|
||||
case reflect.Map:
|
||||
return urv.ptr == nil || len_map(rvRefPtr(urv)) == 0
|
||||
case reflect.Array:
|
||||
return v.Len() == 0 ||
|
||||
urv.ptr == nil ||
|
||||
urv.typ == nil ||
|
||||
rtsize2(urv.typ) == 0 ||
|
||||
unsafeCmpZero(urv.ptr, int(rtsize2(urv.typ)))
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
|
||||
type structFieldInfos struct {
|
||||
c unsafe.Pointer // source
|
||||
s unsafe.Pointer // sorted
|
||||
t uint8To32TrieNode
|
||||
|
||||
c unsafe.Pointer // source
|
||||
s unsafe.Pointer // sorted
|
||||
length int
|
||||
|
||||
// byName map[string]*structFieldInfo // find sfi given a name
|
||||
}
|
||||
|
||||
// func (x *structFieldInfos) load(source, sorted []*structFieldInfo, sourceNames, sortedNames []string) {
|
||||
func (x *structFieldInfos) load(source, sorted []*structFieldInfo) {
|
||||
var s *unsafeSlice
|
||||
s := (*unsafeSlice)(unsafe.Pointer(&sorted))
|
||||
x.s = s.Data
|
||||
x.length = s.Len
|
||||
s = (*unsafeSlice)(unsafe.Pointer(&source))
|
||||
x.c = s.Data
|
||||
x.length = s.Len
|
||||
s = (*unsafeSlice)(unsafe.Pointer(&sorted))
|
||||
x.s = s.Data
|
||||
}
|
||||
|
||||
func (x *structFieldInfos) sorted() (v []*structFieldInfo) {
|
||||
*(*unsafeSlice)(unsafe.Pointer(&v)) = unsafeSlice{x.s, x.length, x.length}
|
||||
// s := (*unsafeSlice)(unsafe.Pointer(&v))
|
||||
// s.Data = x.sorted0
|
||||
// s.Len = x.length
|
||||
// s.Cap = s.Len
|
||||
return
|
||||
}
|
||||
|
||||
func (x *structFieldInfos) source() (v []*structFieldInfo) {
|
||||
@@ -546,48 +529,66 @@ func (x *structFieldInfos) source() (v []*structFieldInfo) {
|
||||
return
|
||||
}
|
||||
|
||||
func (x *structFieldInfos) sorted() (v []*structFieldInfo) {
|
||||
*(*unsafeSlice)(unsafe.Pointer(&v)) = unsafeSlice{x.s, x.length, x.length}
|
||||
return
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
|
||||
type uint8To32TrieNodeNoKids struct {
|
||||
key uint8
|
||||
valid bool // the value marks the end of a full stored string
|
||||
numkids uint8
|
||||
_ byte // padding
|
||||
value uint32
|
||||
}
|
||||
|
||||
type uint8To32TrieNodeKids = *uint8To32TrieNode
|
||||
|
||||
func (x *uint8To32TrieNode) setKids(kids []uint8To32TrieNode) {
|
||||
x.numkids = uint8(len(kids))
|
||||
x.kids = &kids[0]
|
||||
}
|
||||
func (x *uint8To32TrieNode) getKids() (v []uint8To32TrieNode) {
|
||||
*(*unsafeSlice)(unsafe.Pointer(&v)) = unsafeSlice{unsafe.Pointer(x.kids), int(x.numkids), int(x.numkids)}
|
||||
return
|
||||
}
|
||||
func (x *uint8To32TrieNode) truncKids() { x.numkids = 0 }
|
||||
|
||||
// --------------------------
|
||||
|
||||
// atomicXXX is expected to be 2 words (for symmetry with atomic.Value)
|
||||
//
|
||||
// Note that we do not atomically load/store length and data pointer separately,
|
||||
// as this could lead to some races. Instead, we atomically load/store cappedSlice.
|
||||
//
|
||||
// Note: with atomic.(Load|Store)Pointer, we MUST work with an unsafe.Pointer directly.
|
||||
|
||||
// ----------------------
|
||||
type atomicTypeInfoSlice struct {
|
||||
v unsafe.Pointer // *[]rtid2ti
|
||||
}
|
||||
|
||||
func (x *atomicTypeInfoSlice) load() (s []rtid2ti) {
|
||||
x2 := atomic.LoadPointer(&x.v)
|
||||
if x2 != nil {
|
||||
s = *(*[]rtid2ti)(x2)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (x *atomicTypeInfoSlice) store(p []rtid2ti) {
|
||||
atomic.StorePointer(&x.v, unsafe.Pointer(&p))
|
||||
}
|
||||
|
||||
// MARKER: in safe mode, atomicXXX are atomic.Value, which contains an interface{}.
|
||||
// This is 2 words.
|
||||
// consider padding atomicXXX here with a uintptr, so they fit into 2 words also.
|
||||
|
||||
// --------------------------
|
||||
type atomicRtidFnSlice struct {
|
||||
v unsafe.Pointer // *[]codecRtidFn
|
||||
}
|
||||
|
||||
func (x *atomicRtidFnSlice) load() (s unsafe.Pointer) {
|
||||
return atomic.LoadPointer(&x.v)
|
||||
func (x *atomicRtidFnSlice) load() (s []codecRtidFn) {
|
||||
x2 := atomic.LoadPointer(&x.v)
|
||||
if x2 != nil {
|
||||
s = *(*[]codecRtidFn)(x2)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (x *atomicRtidFnSlice) store(p unsafe.Pointer) {
|
||||
atomic.StorePointer(&x.v, p)
|
||||
func (x *atomicRtidFnSlice) store(p []codecRtidFn) {
|
||||
atomic.StorePointer(&x.v, unsafe.Pointer(&p))
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
type atomicClsErr struct {
|
||||
v unsafe.Pointer // *clsErr
|
||||
}
|
||||
|
||||
func (x *atomicClsErr) load() (e clsErr) {
|
||||
x2 := (*clsErr)(atomic.LoadPointer(&x.v))
|
||||
if x2 != nil {
|
||||
e = *x2
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (x *atomicClsErr) store(p clsErr) {
|
||||
atomic.StorePointer(&x.v, unsafe.Pointer(&p))
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
@@ -659,79 +660,98 @@ func (n *fauxUnion) rb() (v reflect.Value) {
|
||||
|
||||
// --------------------------
|
||||
func rvSetBytes(rv reflect.Value, v []byte) {
|
||||
*(*[]byte)(rvPtr(rv)) = v
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
*(*[]byte)(urv.ptr) = v
|
||||
}
|
||||
|
||||
func rvSetString(rv reflect.Value, v string) {
|
||||
*(*string)(rvPtr(rv)) = v
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
*(*string)(urv.ptr) = v
|
||||
}
|
||||
|
||||
func rvSetBool(rv reflect.Value, v bool) {
|
||||
*(*bool)(rvPtr(rv)) = v
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
*(*bool)(urv.ptr) = v
|
||||
}
|
||||
|
||||
func rvSetTime(rv reflect.Value, v time.Time) {
|
||||
*(*time.Time)(rvPtr(rv)) = v
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
*(*time.Time)(urv.ptr) = v
|
||||
}
|
||||
|
||||
func rvSetFloat32(rv reflect.Value, v float32) {
|
||||
*(*float32)(rvPtr(rv)) = v
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
*(*float32)(urv.ptr) = v
|
||||
}
|
||||
|
||||
func rvSetFloat64(rv reflect.Value, v float64) {
|
||||
*(*float64)(rvPtr(rv)) = v
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
*(*float64)(urv.ptr) = v
|
||||
}
|
||||
|
||||
func rvSetComplex64(rv reflect.Value, v complex64) {
|
||||
*(*complex64)(rvPtr(rv)) = v
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
*(*complex64)(urv.ptr) = v
|
||||
}
|
||||
|
||||
func rvSetComplex128(rv reflect.Value, v complex128) {
|
||||
*(*complex128)(rvPtr(rv)) = v
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
*(*complex128)(urv.ptr) = v
|
||||
}
|
||||
|
||||
func rvSetInt(rv reflect.Value, v int) {
|
||||
*(*int)(rvPtr(rv)) = v
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
*(*int)(urv.ptr) = v
|
||||
}
|
||||
|
||||
func rvSetInt8(rv reflect.Value, v int8) {
|
||||
*(*int8)(rvPtr(rv)) = v
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
*(*int8)(urv.ptr) = v
|
||||
}
|
||||
|
||||
func rvSetInt16(rv reflect.Value, v int16) {
|
||||
*(*int16)(rvPtr(rv)) = v
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
*(*int16)(urv.ptr) = v
|
||||
}
|
||||
|
||||
func rvSetInt32(rv reflect.Value, v int32) {
|
||||
*(*int32)(rvPtr(rv)) = v
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
*(*int32)(urv.ptr) = v
|
||||
}
|
||||
|
||||
func rvSetInt64(rv reflect.Value, v int64) {
|
||||
*(*int64)(rvPtr(rv)) = v
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
*(*int64)(urv.ptr) = v
|
||||
}
|
||||
|
||||
func rvSetUint(rv reflect.Value, v uint) {
|
||||
*(*uint)(rvPtr(rv)) = v
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
*(*uint)(urv.ptr) = v
|
||||
}
|
||||
|
||||
func rvSetUintptr(rv reflect.Value, v uintptr) {
|
||||
*(*uintptr)(rvPtr(rv)) = v
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
*(*uintptr)(urv.ptr) = v
|
||||
}
|
||||
|
||||
func rvSetUint8(rv reflect.Value, v uint8) {
|
||||
*(*uint8)(rvPtr(rv)) = v
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
*(*uint8)(urv.ptr) = v
|
||||
}
|
||||
|
||||
func rvSetUint16(rv reflect.Value, v uint16) {
|
||||
*(*uint16)(rvPtr(rv)) = v
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
*(*uint16)(urv.ptr) = v
|
||||
}
|
||||
|
||||
func rvSetUint32(rv reflect.Value, v uint32) {
|
||||
*(*uint32)(rvPtr(rv)) = v
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
*(*uint32)(urv.ptr) = v
|
||||
}
|
||||
|
||||
func rvSetUint64(rv reflect.Value, v uint64) {
|
||||
*(*uint64)(rvPtr(rv)) = v
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
*(*uint64)(urv.ptr) = v
|
||||
}
|
||||
|
||||
// ----------------
|
||||
@@ -755,10 +775,12 @@ func rvSetDirect(rv reflect.Value, v reflect.Value) {
|
||||
uv := (*unsafeReflectValue)(unsafe.Pointer(&v))
|
||||
if uv.flag&unsafeFlagIndir == 0 {
|
||||
*(*unsafe.Pointer)(urv.ptr) = uv.ptr
|
||||
} else if uv.ptr != unsafeZeroAddr {
|
||||
} else if uv.ptr == unsafeZeroAddr {
|
||||
if urv.ptr != unsafeZeroAddr {
|
||||
typedmemclr(urv.typ, urv.ptr)
|
||||
}
|
||||
} else {
|
||||
typedmemmove(urv.typ, urv.ptr, uv.ptr)
|
||||
} else if urv.ptr != unsafeZeroAddr {
|
||||
typedmemclr(urv.typ, urv.ptr)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -790,9 +812,11 @@ func rvMakeSlice(rv reflect.Value, ti *typeInfo, xlen, xcap int) (_ reflect.Valu
|
||||
// It is typically called when we know that SetLen(...) cannot be done.
|
||||
func rvSlice(rv reflect.Value, length int) reflect.Value {
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
ux := *(*unsafeSlice)(urv.ptr) // copy slice header
|
||||
var x []struct{}
|
||||
ux := (*unsafeSlice)(unsafe.Pointer(&x))
|
||||
*ux = *(*unsafeSlice)(urv.ptr)
|
||||
ux.Len = length
|
||||
urv.ptr = unsafe.Pointer(&ux)
|
||||
urv.ptr = unsafe.Pointer(ux)
|
||||
return rv
|
||||
}
|
||||
|
||||
@@ -810,16 +834,10 @@ func rvGrowSlice(rv reflect.Value, ti *typeInfo, cap, incr int) (v reflect.Value
|
||||
|
||||
// ------------
|
||||
|
||||
func rvArrayIndex(rv reflect.Value, i int, ti *typeInfo, isSlice bool) (v reflect.Value) {
|
||||
func rvSliceIndex(rv reflect.Value, i int, ti *typeInfo) (v reflect.Value) {
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
uv := (*unsafeReflectValue)(unsafe.Pointer(&v))
|
||||
if isSlice {
|
||||
uv.ptr = unsafe.Pointer(uintptr(((*unsafeSlice)(urv.ptr)).Data))
|
||||
} else {
|
||||
uv.ptr = unsafe.Pointer(uintptr(urv.ptr))
|
||||
}
|
||||
uv.ptr = unsafe.Add(uv.ptr, ti.elemsize*uint32(i))
|
||||
// uv.ptr = unsafe.Pointer(ptr + uintptr(int(ti.elemsize)*i))
|
||||
uv.ptr = unsafe.Pointer(uintptr(((*unsafeSlice)(urv.ptr)).Data) + uintptr(int(ti.elemsize)*i))
|
||||
uv.typ = ((*unsafeIntf)(unsafe.Pointer(&ti.elem))).ptr
|
||||
uv.flag = uintptr(ti.elemkind) | unsafeFlagIndir | unsafeFlagAddr
|
||||
return
|
||||
@@ -843,11 +861,19 @@ func rvCapSlice(rv reflect.Value) int {
|
||||
return (*unsafeSlice)(urv.ptr).Cap
|
||||
}
|
||||
|
||||
func rvArrayIndex(rv reflect.Value, i int, ti *typeInfo) (v reflect.Value) {
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
uv := (*unsafeReflectValue)(unsafe.Pointer(&v))
|
||||
uv.ptr = unsafe.Pointer(uintptr(urv.ptr) + uintptr(int(ti.elemsize)*i))
|
||||
uv.typ = ((*unsafeIntf)(unsafe.Pointer(&ti.elem))).ptr
|
||||
uv.flag = uintptr(ti.elemkind) | unsafeFlagIndir | unsafeFlagAddr
|
||||
return
|
||||
}
|
||||
|
||||
// if scratch is nil, then return a writable view (assuming canAddr=true)
|
||||
func rvGetArrayBytes(rv reflect.Value, _ []byte) (bs []byte) {
|
||||
func rvGetArrayBytes(rv reflect.Value, scratch []byte) (bs []byte) {
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
bx := (*unsafeSlice)(unsafe.Pointer(&bs))
|
||||
// bx.Data, bx.Len, bx.Cap = urv.ptr, rv.Len(), bx.Len
|
||||
bx.Data = urv.ptr
|
||||
bx.Len = rv.Len()
|
||||
bx.Cap = bx.Len
|
||||
@@ -863,7 +889,7 @@ func rvGetArray4Slice(rv reflect.Value) (v reflect.Value) {
|
||||
//
|
||||
// Consequently, we use rvLenSlice, not rvCapSlice.
|
||||
|
||||
t := reflect.ArrayOf(rvLenSlice(rv), rv.Type().Elem())
|
||||
t := reflectArrayOf(rvLenSlice(rv), rv.Type().Elem())
|
||||
// v = rvZeroAddrK(t, reflect.Array)
|
||||
|
||||
uv := (*unsafeReflectValue)(unsafe.Pointer(&v))
|
||||
@@ -895,84 +921,99 @@ func rvCopySlice(dest, src reflect.Value, elemType reflect.Type) {
|
||||
|
||||
// ------------
|
||||
|
||||
func rvPtr(rv reflect.Value) unsafe.Pointer {
|
||||
return (*unsafeReflectValue)(unsafe.Pointer(&rv)).ptr
|
||||
}
|
||||
|
||||
func rvGetBool(rv reflect.Value) bool {
|
||||
return *(*bool)(rvPtr(rv))
|
||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
return *(*bool)(v.ptr)
|
||||
}
|
||||
|
||||
func rvGetBytes(rv reflect.Value) []byte {
|
||||
return *(*[]byte)(rvPtr(rv))
|
||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
return *(*[]byte)(v.ptr)
|
||||
}
|
||||
|
||||
func rvGetTime(rv reflect.Value) time.Time {
|
||||
return *(*time.Time)(rvPtr(rv))
|
||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
return *(*time.Time)(v.ptr)
|
||||
}
|
||||
|
||||
func rvGetString(rv reflect.Value) string {
|
||||
return *(*string)(rvPtr(rv))
|
||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
return *(*string)(v.ptr)
|
||||
}
|
||||
|
||||
func rvGetFloat64(rv reflect.Value) float64 {
|
||||
return *(*float64)(rvPtr(rv))
|
||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
return *(*float64)(v.ptr)
|
||||
}
|
||||
|
||||
func rvGetFloat32(rv reflect.Value) float32 {
|
||||
return *(*float32)(rvPtr(rv))
|
||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
return *(*float32)(v.ptr)
|
||||
}
|
||||
|
||||
func rvGetComplex64(rv reflect.Value) complex64 {
|
||||
return *(*complex64)(rvPtr(rv))
|
||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
return *(*complex64)(v.ptr)
|
||||
}
|
||||
|
||||
func rvGetComplex128(rv reflect.Value) complex128 {
|
||||
return *(*complex128)(rvPtr(rv))
|
||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
return *(*complex128)(v.ptr)
|
||||
}
|
||||
|
||||
func rvGetInt(rv reflect.Value) int {
|
||||
return *(*int)(rvPtr(rv))
|
||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
return *(*int)(v.ptr)
|
||||
}
|
||||
|
||||
func rvGetInt8(rv reflect.Value) int8 {
|
||||
return *(*int8)(rvPtr(rv))
|
||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
return *(*int8)(v.ptr)
|
||||
}
|
||||
|
||||
func rvGetInt16(rv reflect.Value) int16 {
|
||||
return *(*int16)(rvPtr(rv))
|
||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
return *(*int16)(v.ptr)
|
||||
}
|
||||
|
||||
func rvGetInt32(rv reflect.Value) int32 {
|
||||
return *(*int32)(rvPtr(rv))
|
||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
return *(*int32)(v.ptr)
|
||||
}
|
||||
|
||||
func rvGetInt64(rv reflect.Value) int64 {
|
||||
return *(*int64)(rvPtr(rv))
|
||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
return *(*int64)(v.ptr)
|
||||
}
|
||||
|
||||
func rvGetUint(rv reflect.Value) uint {
|
||||
return *(*uint)(rvPtr(rv))
|
||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
return *(*uint)(v.ptr)
|
||||
}
|
||||
|
||||
func rvGetUint8(rv reflect.Value) uint8 {
|
||||
return *(*uint8)(rvPtr(rv))
|
||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
return *(*uint8)(v.ptr)
|
||||
}
|
||||
|
||||
func rvGetUint16(rv reflect.Value) uint16 {
|
||||
return *(*uint16)(rvPtr(rv))
|
||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
return *(*uint16)(v.ptr)
|
||||
}
|
||||
|
||||
func rvGetUint32(rv reflect.Value) uint32 {
|
||||
return *(*uint32)(rvPtr(rv))
|
||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
return *(*uint32)(v.ptr)
|
||||
}
|
||||
|
||||
func rvGetUint64(rv reflect.Value) uint64 {
|
||||
return *(*uint64)(rvPtr(rv))
|
||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
return *(*uint64)(v.ptr)
|
||||
}
|
||||
|
||||
func rvGetUintptr(rv reflect.Value) uintptr {
|
||||
return *(*uintptr)(rvPtr(rv))
|
||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
return *(*uintptr)(v.ptr)
|
||||
}
|
||||
|
||||
func rvLenMap(rv reflect.Value) int {
|
||||
@@ -986,6 +1027,32 @@ func rvLenMap(rv reflect.Value) int {
|
||||
return len_map(rvRefPtr((*unsafeReflectValue)(unsafe.Pointer(&rv))))
|
||||
}
|
||||
|
||||
// copy is an intrinsic, which may use asm if length is small,
|
||||
// or make a runtime call to runtime.memmove if length is large.
|
||||
// Performance suffers when you always call runtime.memmove function.
|
||||
//
|
||||
// Consequently, there's no value in a copybytes call - just call copy() directly
|
||||
|
||||
// func copybytes(to, from []byte) (n int) {
|
||||
// n = (*unsafeSlice)(unsafe.Pointer(&from)).Len
|
||||
// memmove(
|
||||
// (*unsafeSlice)(unsafe.Pointer(&to)).Data,
|
||||
// (*unsafeSlice)(unsafe.Pointer(&from)).Data,
|
||||
// uintptr(n),
|
||||
// )
|
||||
// return
|
||||
// }
|
||||
|
||||
// func copybytestr(to []byte, from string) (n int) {
|
||||
// n = (*unsafeSlice)(unsafe.Pointer(&from)).Len
|
||||
// memmove(
|
||||
// (*unsafeSlice)(unsafe.Pointer(&to)).Data,
|
||||
// (*unsafeSlice)(unsafe.Pointer(&from)).Data,
|
||||
// uintptr(n),
|
||||
// )
|
||||
// return
|
||||
// }
|
||||
|
||||
// Note: it is hard to find len(...) of an array type,
|
||||
// as that is a field in the arrayType representing the array, and hard to introspect.
|
||||
//
|
||||
@@ -998,26 +1065,24 @@ func rvLenMap(rv reflect.Value) int {
|
||||
//
|
||||
// It is more performant to provide a value that the map entry is set into,
|
||||
// and that elides the allocation.
|
||||
|
||||
// go 1.4+ has runtime/hashmap.go or runtime/map.go which has a
|
||||
// hIter struct with the first 2 values being key and value
|
||||
// of the current iteration.
|
||||
//
|
||||
// go 1.4 through go 1.23 (in runtime/hashmap.go or runtime/map.go) has a hIter struct
|
||||
// with the first 2 values being pointers for key and value of the current iteration.
|
||||
// The next 6 values are pointers, followed by numeric types (uintptr, uint8, bool, etc).
|
||||
// This *hIter is passed to mapiterinit, mapiternext, mapiterkey, mapiterelem.
|
||||
// We bypass the reflect wrapper functions and just use the *hIter directly.
|
||||
//
|
||||
// In go 1.24, swissmap was introduced, and it provides a compatibility layer
|
||||
// for hIter (called linknameIter). This has only 2 pointer fields after the key and value pointers.
|
||||
// Though *hIter has many fields, we only care about the first 2.
|
||||
//
|
||||
// Note: We bypass the reflect wrapper functions and just use the *hIter directly.
|
||||
// We directly embed this in unsafeMapIter below
|
||||
//
|
||||
// When 'faking' these types with our own, we MUST ensure that the GC sees the pointers
|
||||
// appropriately. These are reflected in goversion_(no)swissmap_unsafe.go files.
|
||||
// In these files, we pad the extra spaces appropriately.
|
||||
//
|
||||
// Note: the faux hIter/linknameIter is directly embedded in unsafeMapIter below
|
||||
// hiter is typically about 12 words, but we just fill up unsafeMapIter to 32 words,
|
||||
// so it fills multiple cache lines and can give some extra space to accomodate small growth.
|
||||
|
||||
type unsafeMapIter struct {
|
||||
mtyp, mptr unsafe.Pointer
|
||||
k, v unsafeReflectValue
|
||||
k, v reflect.Value
|
||||
kisref bool
|
||||
visref bool
|
||||
mapvalues bool
|
||||
@@ -1027,7 +1092,7 @@ type unsafeMapIter struct {
|
||||
it struct {
|
||||
key unsafe.Pointer
|
||||
value unsafe.Pointer
|
||||
_ unsafeMapIterPadding
|
||||
_ [20]uintptr // padding for other fields (to make up 32 words for enclosing struct)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1047,16 +1112,18 @@ func (t *unsafeMapIter) Next() (r bool) {
|
||||
}
|
||||
|
||||
if helperUnsafeDirectAssignMapEntry || t.kisref {
|
||||
t.k.ptr = t.it.key
|
||||
(*unsafeReflectValue)(unsafe.Pointer(&t.k)).ptr = t.it.key
|
||||
} else {
|
||||
typedmemmove(t.k.typ, t.k.ptr, t.it.key)
|
||||
k := (*unsafeReflectValue)(unsafe.Pointer(&t.k))
|
||||
typedmemmove(k.typ, k.ptr, t.it.key)
|
||||
}
|
||||
|
||||
if t.mapvalues {
|
||||
if helperUnsafeDirectAssignMapEntry || t.visref {
|
||||
t.v.ptr = t.it.value
|
||||
(*unsafeReflectValue)(unsafe.Pointer(&t.v)).ptr = t.it.value
|
||||
} else {
|
||||
typedmemmove(t.v.typ, t.v.ptr, t.it.value)
|
||||
v := (*unsafeReflectValue)(unsafe.Pointer(&t.v))
|
||||
typedmemmove(v.typ, v.ptr, t.it.value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1064,11 +1131,11 @@ func (t *unsafeMapIter) Next() (r bool) {
|
||||
}
|
||||
|
||||
func (t *unsafeMapIter) Key() (r reflect.Value) {
|
||||
return *(*reflect.Value)(unsafe.Pointer(&t.k))
|
||||
return t.k
|
||||
}
|
||||
|
||||
func (t *unsafeMapIter) Value() (r reflect.Value) {
|
||||
return *(*reflect.Value)(unsafe.Pointer(&t.v))
|
||||
return t.v
|
||||
}
|
||||
|
||||
func (t *unsafeMapIter) Done() {}
|
||||
@@ -1095,14 +1162,14 @@ func mapRange(t *mapIter, m, k, v reflect.Value, mapvalues bool) {
|
||||
// t.it = (*unsafeMapHashIter)(reflect_mapiterinit(t.mtyp, t.mptr))
|
||||
mapiterinit(t.mtyp, t.mptr, unsafe.Pointer(&t.it))
|
||||
|
||||
t.k = *(*unsafeReflectValue)(unsafe.Pointer(&k))
|
||||
t.k = k
|
||||
t.kisref = refBitset.isset(byte(k.Kind()))
|
||||
|
||||
if mapvalues {
|
||||
t.v = *(*unsafeReflectValue)(unsafe.Pointer(&v))
|
||||
t.v = v
|
||||
t.visref = refBitset.isset(byte(v.Kind()))
|
||||
} else {
|
||||
t.v = unsafeReflectValue{}
|
||||
t.v = reflect.Value{}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1115,6 +1182,13 @@ func unsafeMapKVPtr(urv *unsafeReflectValue) unsafe.Pointer {
|
||||
return urv.ptr
|
||||
}
|
||||
|
||||
// func mapDelete(m, k reflect.Value) {
|
||||
// var urv = (*unsafeReflectValue)(unsafe.Pointer(&k))
|
||||
// var kptr = unsafeMapKVPtr(urv)
|
||||
// urv = (*unsafeReflectValue)(unsafe.Pointer(&m))
|
||||
// mapdelete(urv.typ, rv2ptr(urv), kptr)
|
||||
// }
|
||||
|
||||
// return an addressable reflect value that can be used in mapRange and mapGet operations.
|
||||
//
|
||||
// all calls to mapGet or mapRange will call here to get an addressable reflect.Value.
|
||||
@@ -1131,39 +1205,53 @@ func mapAddrLoopvarRV(t reflect.Type, k reflect.Kind) (rv reflect.Value) {
|
||||
return
|
||||
}
|
||||
|
||||
func makeMapReflect(typ reflect.Type, size int) (rv reflect.Value) {
|
||||
t := (*unsafeIntf)(unsafe.Pointer(&typ)).ptr
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
urv.typ = t
|
||||
urv.flag = uintptr(reflect.Map)
|
||||
urv.ptr = makemap(t, size, nil)
|
||||
return
|
||||
// ---------- ENCODER optimized ---------------
|
||||
|
||||
func (e *Encoder) jsondriver() *jsonEncDriver {
|
||||
return (*jsonEncDriver)((*unsafeIntf)(unsafe.Pointer(&e.e)).ptr)
|
||||
}
|
||||
|
||||
func (d *decoderBase) bytes2Str(in []byte, state dBytesAttachState) (s string, mutable bool) {
|
||||
return stringView(in), state <= dBytesAttachBuffer
|
||||
func (d *Decoder) zerocopystate() bool {
|
||||
return d.decByteState == decByteStateZerocopy && d.h.ZeroCopy
|
||||
}
|
||||
|
||||
func (d *Decoder) stringZC(v []byte) (s string) {
|
||||
// MARKER: inline zerocopystate directly so genHelper forwarding function fits within inlining cost
|
||||
|
||||
// if d.zerocopystate() {
|
||||
if d.decByteState == decByteStateZerocopy && d.h.ZeroCopy {
|
||||
return stringView(v)
|
||||
}
|
||||
return d.string(v)
|
||||
}
|
||||
|
||||
func (d *Decoder) mapKeyString(callFnRvk *bool, kstrbs, kstr2bs *[]byte) string {
|
||||
if !d.zerocopystate() {
|
||||
*callFnRvk = true
|
||||
if d.decByteState == decByteStateReuseBuf {
|
||||
*kstrbs = append((*kstrbs)[:0], (*kstr2bs)...)
|
||||
*kstr2bs = *kstrbs
|
||||
}
|
||||
}
|
||||
return stringView(*kstr2bs)
|
||||
}
|
||||
|
||||
// ---------- DECODER optimized ---------------
|
||||
|
||||
func (d *Decoder) jsondriver() *jsonDecDriver {
|
||||
return (*jsonDecDriver)((*unsafeIntf)(unsafe.Pointer(&d.d)).ptr)
|
||||
}
|
||||
|
||||
// ---------- structFieldInfo optimized ---------------
|
||||
|
||||
func (n *structFieldInfoNode) rvField(v reflect.Value) (rv reflect.Value) {
|
||||
func (n *structFieldInfoPathNode) rvField(v reflect.Value) (rv reflect.Value) {
|
||||
// we already know this is exported, and maybe embedded (based on what si says)
|
||||
uv := (*unsafeReflectValue)(unsafe.Pointer(&v))
|
||||
|
||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
||||
// clear flagEmbedRO if necessary, and inherit permission bits from v
|
||||
urv.flag = uv.flag&(unsafeFlagStickyRO|unsafeFlagIndir|unsafeFlagAddr) | uintptr(n.kind)
|
||||
urv.typ = ((*unsafeIntf)(unsafe.Pointer(&n.typ))).ptr
|
||||
urv.ptr = unsafe.Pointer(uintptr(uv.ptr) + uintptr(n.offset))
|
||||
|
||||
// *(*unsafeReflectValue)(unsafe.Pointer(&rv)) = unsafeReflectValue{
|
||||
// unsafeIntf: unsafeIntf{
|
||||
// typ: ((*unsafeIntf)(unsafe.Pointer(&n.typ))).ptr,
|
||||
// ptr: unsafe.Pointer(uintptr(uv.ptr) + uintptr(n.offset)),
|
||||
// },
|
||||
// flag: uv.flag&(unsafeFlagStickyRO|unsafeFlagIndir|unsafeFlagAddr) | uintptr(n.kind),
|
||||
// }
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1211,6 +1299,10 @@ func unsafeNew(typ unsafe.Pointer) unsafe.Pointer {
|
||||
// failing with "error: undefined reference" error.
|
||||
// however, runtime.{mallocgc, newarray} are supported, so use that instead.
|
||||
|
||||
//go:linkname memmove runtime.memmove
|
||||
//go:noescape
|
||||
func memmove(to, from unsafe.Pointer, n uintptr)
|
||||
|
||||
//go:linkname mallocgc runtime.mallocgc
|
||||
//go:noescape
|
||||
func mallocgc(size uintptr, typ unsafe.Pointer, needzero bool) unsafe.Pointer
|
||||
@@ -1227,6 +1319,10 @@ func mapiterinit(typ unsafe.Pointer, m unsafe.Pointer, it unsafe.Pointer)
|
||||
//go:noescape
|
||||
func mapiternext(it unsafe.Pointer) (key unsafe.Pointer)
|
||||
|
||||
//go:linkname mapdelete runtime.mapdelete
|
||||
//go:noescape
|
||||
func mapdelete(typ unsafe.Pointer, m unsafe.Pointer, key unsafe.Pointer)
|
||||
|
||||
//go:linkname mapassign runtime.mapassign
|
||||
//go:noescape
|
||||
func mapassign(typ unsafe.Pointer, m unsafe.Pointer, key unsafe.Pointer) unsafe.Pointer
|
||||
@@ -1235,10 +1331,6 @@ func mapassign(typ unsafe.Pointer, m unsafe.Pointer, key unsafe.Pointer) unsafe.
|
||||
//go:noescape
|
||||
func mapaccess2(typ unsafe.Pointer, m unsafe.Pointer, key unsafe.Pointer) (val unsafe.Pointer, ok bool)
|
||||
|
||||
//go:linkname makemap runtime.makemap
|
||||
//go:noescape
|
||||
func makemap(typ unsafe.Pointer, size int, h unsafe.Pointer) unsafe.Pointer
|
||||
|
||||
// reflect.typed{memmove, memclr, slicecopy} will handle checking if the type has pointers or not,
|
||||
// and if a writeBarrier is needed, before delegating to the right method in the runtime.
|
||||
//
|
||||
|
||||
111
vendor/github.com/ugorji/go/codec/helper_unsafe_compiler_gc.go
generated
vendored
111
vendor/github.com/ugorji/go/codec/helper_unsafe_compiler_gc.go
generated
vendored
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT license found in the LICENSE file.
|
||||
|
||||
//go:build !safe && !codec.safe && !appengine && go1.9 && gc
|
||||
// +build !safe,!codec.safe,!appengine,go1.9,gc
|
||||
|
||||
package codec
|
||||
|
||||
@@ -23,67 +24,8 @@ const (
|
||||
mapMaxElemSize = 128
|
||||
)
|
||||
|
||||
type mapKeyFastKind uint8
|
||||
|
||||
const (
|
||||
mapKeyFastKindAny = iota + 1
|
||||
mapKeyFastKind32
|
||||
mapKeyFastKind32ptr
|
||||
mapKeyFastKind64
|
||||
mapKeyFastKind64ptr
|
||||
mapKeyFastKindStr
|
||||
)
|
||||
|
||||
var mapKeyFastKindVals [32]mapKeyFastKind
|
||||
|
||||
type mapReqParams struct {
|
||||
kfast mapKeyFastKind
|
||||
ref bool
|
||||
indirect bool
|
||||
}
|
||||
|
||||
func getMapReqParams(ti *typeInfo) (r mapReqParams) {
|
||||
r.indirect = mapStoresElemIndirect(uintptr(ti.elemsize))
|
||||
r.ref = refBitset.isset(ti.elemkind)
|
||||
r.kfast = mapKeyFastKindFor(reflect.Kind(ti.keykind))
|
||||
return
|
||||
}
|
||||
|
||||
func init() {
|
||||
xx := func(f mapKeyFastKind, k ...reflect.Kind) {
|
||||
for _, v := range k {
|
||||
mapKeyFastKindVals[byte(v)&31] = f // 'v % 32' equal to 'v & 31'
|
||||
}
|
||||
}
|
||||
|
||||
var f mapKeyFastKind
|
||||
|
||||
f = mapKeyFastKind64
|
||||
if wordSizeBits == 32 {
|
||||
f = mapKeyFastKind32
|
||||
}
|
||||
xx(f, reflect.Int, reflect.Uint, reflect.Uintptr)
|
||||
|
||||
f = mapKeyFastKind64ptr
|
||||
if wordSizeBits == 32 {
|
||||
f = mapKeyFastKind32ptr
|
||||
}
|
||||
xx(f, reflect.Ptr)
|
||||
|
||||
xx(mapKeyFastKindStr, reflect.String)
|
||||
xx(mapKeyFastKind32, reflect.Uint32, reflect.Int32, reflect.Float32)
|
||||
xx(mapKeyFastKind64, reflect.Uint64, reflect.Int64, reflect.Float64)
|
||||
}
|
||||
|
||||
func mapKeyFastKindFor(k reflect.Kind) mapKeyFastKind {
|
||||
return mapKeyFastKindVals[k&31]
|
||||
}
|
||||
|
||||
func unsafeGrowslice(typ unsafe.Pointer, old unsafeSlice, cap, incr int) (s unsafeSlice) {
|
||||
// culled from GOROOT/runtime/slice.go
|
||||
s = rtgrowslice(old.Data, old.Cap+incr, old.Cap, incr, typ)
|
||||
s.Len = old.Len
|
||||
return
|
||||
func unsafeGrowslice(typ unsafe.Pointer, old unsafeSlice, cap, incr int) (v unsafeSlice) {
|
||||
return growslice(typ, old, cap+incr)
|
||||
}
|
||||
|
||||
// func rvType(rv reflect.Value) reflect.Type {
|
||||
@@ -101,7 +43,7 @@ func mapStoresElemIndirect(elemsize uintptr) bool {
|
||||
return elemsize > mapMaxElemSize
|
||||
}
|
||||
|
||||
func mapSet(m, k, v reflect.Value, p mapReqParams) { // valIsRef
|
||||
func mapSet(m, k, v reflect.Value, keyFastKind mapKeyFastKind, valIsIndirect, valIsRef bool) {
|
||||
var urv = (*unsafeReflectValue)(unsafe.Pointer(&k))
|
||||
var kptr = unsafeMapKVPtr(urv)
|
||||
urv = (*unsafeReflectValue)(unsafe.Pointer(&v))
|
||||
@@ -118,15 +60,14 @@ func mapSet(m, k, v reflect.Value, p mapReqParams) { // valIsRef
|
||||
// Sometimes, we got vvptr == nil when we dereferenced vvptr (if valIsIndirect).
|
||||
// Consequently, only use fastXXX functions if !valIsIndirect
|
||||
|
||||
if p.indirect {
|
||||
if valIsIndirect {
|
||||
vvptr = mapassign(urv.typ, mptr, kptr)
|
||||
// typedmemmove(vtyp, vvptr, vptr)
|
||||
// // reflect_mapassign(urv.typ, mptr, kptr, vptr)
|
||||
// return
|
||||
goto END
|
||||
typedmemmove(vtyp, vvptr, vptr)
|
||||
// reflect_mapassign(urv.typ, mptr, kptr, vptr)
|
||||
return
|
||||
}
|
||||
|
||||
switch p.kfast {
|
||||
switch keyFastKind {
|
||||
case mapKeyFastKind32:
|
||||
vvptr = mapassign_fast32(urv.typ, mptr, *(*uint32)(kptr))
|
||||
case mapKeyFastKind32ptr:
|
||||
@@ -141,14 +82,14 @@ func mapSet(m, k, v reflect.Value, p mapReqParams) { // valIsRef
|
||||
vvptr = mapassign(urv.typ, mptr, kptr)
|
||||
}
|
||||
|
||||
// if p.kfast != 0 && valIsIndirect {
|
||||
// if keyFastKind != 0 && valIsIndirect {
|
||||
// vvptr = *(*unsafe.Pointer)(vvptr)
|
||||
// }
|
||||
END:
|
||||
|
||||
typedmemmove(vtyp, vvptr, vptr)
|
||||
}
|
||||
|
||||
func mapGet(m, k, v reflect.Value, p mapReqParams) (_ reflect.Value) {
|
||||
func mapGet(m, k, v reflect.Value, keyFastKind mapKeyFastKind, valIsIndirect, valIsRef bool) (_ reflect.Value) {
|
||||
var urv = (*unsafeReflectValue)(unsafe.Pointer(&k))
|
||||
var kptr = unsafeMapKVPtr(urv)
|
||||
urv = (*unsafeReflectValue)(unsafe.Pointer(&m))
|
||||
@@ -160,7 +101,7 @@ func mapGet(m, k, v reflect.Value, p mapReqParams) (_ reflect.Value) {
|
||||
// Note that mapaccess2_fastXXX functions do not check if the value needs to be copied.
|
||||
// if they do, we should dereference the pointer and return that
|
||||
|
||||
switch p.kfast {
|
||||
switch keyFastKind {
|
||||
case mapKeyFastKind32, mapKeyFastKind32ptr:
|
||||
vvptr, ok = mapaccess2_fast32(urv.typ, mptr, *(*uint32)(kptr))
|
||||
case mapKeyFastKind64, mapKeyFastKind64ptr:
|
||||
@@ -177,9 +118,9 @@ func mapGet(m, k, v reflect.Value, p mapReqParams) (_ reflect.Value) {
|
||||
|
||||
urv = (*unsafeReflectValue)(unsafe.Pointer(&v))
|
||||
|
||||
if p.kfast != 0 && p.indirect {
|
||||
if keyFastKind != 0 && valIsIndirect {
|
||||
urv.ptr = *(*unsafe.Pointer)(vvptr)
|
||||
} else if helperUnsafeDirectAssignMapEntry || p.ref {
|
||||
} else if helperUnsafeDirectAssignMapEntry || valIsRef {
|
||||
urv.ptr = vvptr
|
||||
} else {
|
||||
typedmemmove(urv.typ, urv.ptr, vvptr)
|
||||
@@ -188,11 +129,13 @@ func mapGet(m, k, v reflect.Value, p mapReqParams) (_ reflect.Value) {
|
||||
return v
|
||||
}
|
||||
|
||||
// ----
|
||||
|
||||
//go:linkname unsafeZeroArr runtime.zeroVal
|
||||
var unsafeZeroArr [1024]byte
|
||||
|
||||
// //go:linkname rvPtrToType reflect.toType
|
||||
// //go:noescape
|
||||
// func rvPtrToType(typ unsafe.Pointer) reflect.Type
|
||||
|
||||
//go:linkname mapassign_fast32 runtime.mapassign_fast32
|
||||
//go:noescape
|
||||
func mapassign_fast32(typ unsafe.Pointer, m unsafe.Pointer, key uint32) unsafe.Pointer
|
||||
@@ -224,19 +167,3 @@ func mapaccess2_fast64(typ unsafe.Pointer, m unsafe.Pointer, key uint64) (val un
|
||||
//go:linkname mapaccess2_faststr runtime.mapaccess2_faststr
|
||||
//go:noescape
|
||||
func mapaccess2_faststr(typ unsafe.Pointer, m unsafe.Pointer, key string) (val unsafe.Pointer, ok bool)
|
||||
|
||||
//go:linkname rtgrowslice runtime.growslice
|
||||
//go:noescape
|
||||
func rtgrowslice(oldPtr unsafe.Pointer, newLen, oldCap, num int, typ unsafe.Pointer) unsafeSlice
|
||||
|
||||
// ----
|
||||
|
||||
// //go:linkname rvPtrToType reflect.toType
|
||||
// //go:noescape
|
||||
// func rvPtrToType(typ unsafe.Pointer) reflect.Type
|
||||
|
||||
// //go:linkname growslice reflect.growslice
|
||||
// //go:noescape
|
||||
// func growslice(typ unsafe.Pointer, old unsafeSlice, cap int) unsafeSlice
|
||||
|
||||
// ----
|
||||
|
||||
23
vendor/github.com/ugorji/go/codec/helper_unsafe_compiler_not_gc.go
generated
vendored
23
vendor/github.com/ugorji/go/codec/helper_unsafe_compiler_not_gc.go
generated
vendored
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a MIT license found in the LICENSE file.
|
||||
|
||||
//go:build !safe && !codec.safe && !appengine && go1.9 && !gc
|
||||
// +build !safe,!codec.safe,!appengine,go1.9,!gc
|
||||
|
||||
package codec
|
||||
|
||||
@@ -13,15 +14,6 @@ import (
|
||||
|
||||
var unsafeZeroArr [1024]byte
|
||||
|
||||
type mapReqParams struct {
|
||||
ref bool
|
||||
}
|
||||
|
||||
func getMapReqParams(ti *typeInfo) (r mapReqParams) {
|
||||
r.ref = refBitset.isset(ti.elemkind)
|
||||
return
|
||||
}
|
||||
|
||||
// runtime.growslice does not work with gccgo, failing with "growslice: cap out of range" error.
|
||||
// consequently, we just call newarray followed by typedslicecopy directly.
|
||||
|
||||
@@ -39,11 +31,18 @@ func unsafeGrowslice(typ unsafe.Pointer, old unsafeSlice, cap, incr int) (v unsa
|
||||
return
|
||||
}
|
||||
|
||||
// func unsafeNew(t reflect.Type, typ unsafe.Pointer) unsafe.Pointer {
|
||||
// rv := reflect.New(t)
|
||||
// return ((*unsafeReflectValue)(unsafe.Pointer(&rv))).ptr
|
||||
// }
|
||||
|
||||
// runtime.{mapassign_fastXXX, mapaccess2_fastXXX} are not supported in gollvm,
|
||||
// failing with "error: undefined reference" error.
|
||||
// so we just use runtime.{mapassign, mapaccess2} directly
|
||||
|
||||
func mapSet(m, k, v reflect.Value, p mapReqParams) {
|
||||
func mapStoresElemIndirect(elemsize uintptr) bool { return false }
|
||||
|
||||
func mapSet(m, k, v reflect.Value, _ mapKeyFastKind, _, valIsRef bool) {
|
||||
var urv = (*unsafeReflectValue)(unsafe.Pointer(&k))
|
||||
var kptr = unsafeMapKVPtr(urv)
|
||||
urv = (*unsafeReflectValue)(unsafe.Pointer(&v))
|
||||
@@ -57,7 +56,7 @@ func mapSet(m, k, v reflect.Value, p mapReqParams) {
|
||||
typedmemmove(vtyp, vvptr, vptr)
|
||||
}
|
||||
|
||||
func mapGet(m, k, v reflect.Value, p mapReqParams) (_ reflect.Value) {
|
||||
func mapGet(m, k, v reflect.Value, _ mapKeyFastKind, _, valIsRef bool) (_ reflect.Value) {
|
||||
var urv = (*unsafeReflectValue)(unsafe.Pointer(&k))
|
||||
var kptr = unsafeMapKVPtr(urv)
|
||||
urv = (*unsafeReflectValue)(unsafe.Pointer(&m))
|
||||
@@ -71,7 +70,7 @@ func mapGet(m, k, v reflect.Value, p mapReqParams) (_ reflect.Value) {
|
||||
|
||||
urv = (*unsafeReflectValue)(unsafe.Pointer(&v))
|
||||
|
||||
if helperUnsafeDirectAssignMapEntry || p.ref {
|
||||
if helperUnsafeDirectAssignMapEntry || valIsRef {
|
||||
urv.ptr = vvptr
|
||||
} else {
|
||||
typedmemmove(urv.typ, urv.ptr, vvptr)
|
||||
|
||||
1334
vendor/github.com/ugorji/go/codec/json.go
generated
vendored
1334
vendor/github.com/ugorji/go/codec/json.go
generated
vendored
File diff suppressed because it is too large
Load Diff
954
vendor/github.com/ugorji/go/codec/msgpack.go
generated
vendored
954
vendor/github.com/ugorji/go/codec/msgpack.go
generated
vendored
File diff suppressed because it is too large
Load Diff
1041
vendor/github.com/ugorji/go/codec/reader.go
generated
vendored
1041
vendor/github.com/ugorji/go/codec/reader.go
generated
vendored
File diff suppressed because it is too large
Load Diff
88
vendor/github.com/ugorji/go/codec/rpc.go
generated
vendored
88
vendor/github.com/ugorji/go/codec/rpc.go
generated
vendored
@@ -4,11 +4,10 @@
|
||||
package codec
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"net/rpc"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -29,44 +28,57 @@ type RPCOptions struct {
|
||||
// RPCNoBuffer configures whether we attempt to buffer reads and writes during RPC calls.
|
||||
//
|
||||
// Set RPCNoBuffer=true to turn buffering off.
|
||||
//
|
||||
// Buffering can still be done if buffered connections are passed in, or
|
||||
// buffering is configured on the handle.
|
||||
//
|
||||
// Deprecated: Buffering should be configured at the Handle or by using a buffer Reader.
|
||||
// Setting this has no effect anymore (after v1.2.12 - authored 2025-05-06)
|
||||
RPCNoBuffer bool
|
||||
}
|
||||
|
||||
// rpcCodec defines the struct members and common methods.
|
||||
type rpcCodec struct {
|
||||
c io.Closer
|
||||
r io.Reader
|
||||
w io.Writer
|
||||
f ioFlusher
|
||||
nc net.Conn
|
||||
c io.Closer
|
||||
r io.Reader
|
||||
w io.Writer
|
||||
f ioFlusher
|
||||
|
||||
dec *Decoder
|
||||
enc *Encoder
|
||||
h Handle
|
||||
|
||||
cls atomic.Pointer[clsErr]
|
||||
cls atomicClsErr
|
||||
}
|
||||
|
||||
func newRPCCodec(conn io.ReadWriteCloser, h Handle) *rpcCodec {
|
||||
nc, _ := conn.(net.Conn)
|
||||
f, _ := conn.(ioFlusher)
|
||||
rc := &rpcCodec{
|
||||
h: h,
|
||||
c: conn,
|
||||
w: conn,
|
||||
r: conn,
|
||||
f: f,
|
||||
nc: nc,
|
||||
enc: NewEncoder(conn, h),
|
||||
dec: NewDecoder(conn, h),
|
||||
func newRPCCodec(conn io.ReadWriteCloser, h Handle) rpcCodec {
|
||||
return newRPCCodec2(conn, conn, conn, h)
|
||||
}
|
||||
|
||||
func newRPCCodec2(r io.Reader, w io.Writer, c io.Closer, h Handle) rpcCodec {
|
||||
bh := h.getBasicHandle()
|
||||
// if the writer can flush, ensure we leverage it, else
|
||||
// we may hang waiting on read if write isn't flushed.
|
||||
// var f ioFlusher
|
||||
f, ok := w.(ioFlusher)
|
||||
if !bh.RPCNoBuffer {
|
||||
if bh.WriterBufferSize <= 0 {
|
||||
if !ok { // a flusher means there's already a buffer
|
||||
bw := bufio.NewWriter(w)
|
||||
f, w = bw, bw
|
||||
}
|
||||
}
|
||||
if bh.ReaderBufferSize <= 0 {
|
||||
if _, ok = w.(ioBuffered); !ok {
|
||||
r = bufio.NewReader(r)
|
||||
}
|
||||
}
|
||||
}
|
||||
return rpcCodec{
|
||||
c: c,
|
||||
w: w,
|
||||
r: r,
|
||||
f: f,
|
||||
h: h,
|
||||
enc: NewEncoder(w, h),
|
||||
dec: NewDecoder(r, h),
|
||||
}
|
||||
rc.cls.Store(new(clsErr))
|
||||
return rc
|
||||
}
|
||||
|
||||
func (c *rpcCodec) write(obj ...interface{}) (err error) {
|
||||
@@ -104,16 +116,10 @@ func (c *rpcCodec) write(obj ...interface{}) (err error) {
|
||||
func (c *rpcCodec) read(obj interface{}) (err error) {
|
||||
err = c.ready()
|
||||
if err == nil {
|
||||
// Setting ReadDeadline should not be necessary,
|
||||
// especially since it only works for net.Conn (not generic ioReadCloser).
|
||||
// if c.nc != nil {
|
||||
// c.nc.SetReadDeadline(time.Now().Add(1 * time.Second))
|
||||
// }
|
||||
|
||||
// Note: If nil is passed in, we should read and discard
|
||||
//If nil is passed in, we should read and discard
|
||||
if obj == nil {
|
||||
// return c.dec.Decode(&obj)
|
||||
err = panicToErr(c.dec, func() { c.dec.swallow() })
|
||||
err = c.dec.swallowErr()
|
||||
} else {
|
||||
err = c.dec.Decode(obj)
|
||||
}
|
||||
@@ -123,11 +129,11 @@ func (c *rpcCodec) read(obj interface{}) (err error) {
|
||||
|
||||
func (c *rpcCodec) Close() (err error) {
|
||||
if c.c != nil {
|
||||
cls := c.cls.Load()
|
||||
cls := c.cls.load()
|
||||
if !cls.closed {
|
||||
// writing to same pointer could lead to a data race (always make new one)
|
||||
cls = &clsErr{closed: true, err: c.c.Close()}
|
||||
c.cls.Store(cls)
|
||||
cls.err = c.c.Close()
|
||||
cls.closed = true
|
||||
c.cls.store(cls)
|
||||
}
|
||||
err = cls.err
|
||||
}
|
||||
@@ -138,8 +144,8 @@ func (c *rpcCodec) ready() (err error) {
|
||||
if c.c == nil {
|
||||
err = errRpcNoConn
|
||||
} else {
|
||||
cls := c.cls.Load()
|
||||
if cls != nil && cls.closed {
|
||||
cls := c.cls.load()
|
||||
if cls.closed {
|
||||
if err = cls.err; err == nil {
|
||||
err = errRpcIsClosed
|
||||
}
|
||||
@@ -155,7 +161,7 @@ func (c *rpcCodec) ReadResponseBody(body interface{}) error {
|
||||
// -------------------------------------
|
||||
|
||||
type goRpcCodec struct {
|
||||
*rpcCodec
|
||||
rpcCodec
|
||||
}
|
||||
|
||||
func (c *goRpcCodec) WriteRequest(r *rpc.Request, body interface{}) error {
|
||||
|
||||
595
vendor/github.com/ugorji/go/codec/simple.go
generated
vendored
595
vendor/github.com/ugorji/go/codec/simple.go
generated
vendored
@@ -1,65 +1,111 @@
|
||||
//go:build notmono || codec.notmono
|
||||
|
||||
// Copyright (c) 2012-2020 Ugorji Nwoke. All rights reserved.
|
||||
// Use of this source code is governed by a MIT license found in the LICENSE file.
|
||||
|
||||
package codec
|
||||
|
||||
import (
|
||||
"io"
|
||||
"math"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
type simpleEncDriver[T encWriter] struct {
|
||||
const (
|
||||
_ uint8 = iota
|
||||
simpleVdNil = 1
|
||||
simpleVdFalse = 2
|
||||
simpleVdTrue = 3
|
||||
simpleVdFloat32 = 4
|
||||
simpleVdFloat64 = 5
|
||||
|
||||
// each lasts for 4 (ie n, n+1, n+2, n+3)
|
||||
simpleVdPosInt = 8
|
||||
simpleVdNegInt = 12
|
||||
|
||||
simpleVdTime = 24
|
||||
|
||||
// containers: each lasts for 4 (ie n, n+1, n+2, ... n+7)
|
||||
simpleVdString = 216
|
||||
simpleVdByteArray = 224
|
||||
simpleVdArray = 232
|
||||
simpleVdMap = 240
|
||||
simpleVdExt = 248
|
||||
)
|
||||
|
||||
var simpledescNames = map[byte]string{
|
||||
simpleVdNil: "null",
|
||||
simpleVdFalse: "false",
|
||||
simpleVdTrue: "true",
|
||||
simpleVdFloat32: "float32",
|
||||
simpleVdFloat64: "float64",
|
||||
|
||||
simpleVdPosInt: "+int",
|
||||
simpleVdNegInt: "-int",
|
||||
|
||||
simpleVdTime: "time",
|
||||
|
||||
simpleVdString: "string",
|
||||
simpleVdByteArray: "binary",
|
||||
simpleVdArray: "array",
|
||||
simpleVdMap: "map",
|
||||
simpleVdExt: "ext",
|
||||
}
|
||||
|
||||
func simpledesc(bd byte) (s string) {
|
||||
s = simpledescNames[bd]
|
||||
if s == "" {
|
||||
s = "unknown"
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type simpleEncDriver struct {
|
||||
noBuiltInTypes
|
||||
encDriverNoopContainerWriter
|
||||
encDriverNoState
|
||||
encDriverContainerNoTrackerT
|
||||
encInit2er
|
||||
|
||||
h *SimpleHandle
|
||||
e *encoderBase
|
||||
// b [8]byte
|
||||
w T
|
||||
e Encoder
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver[T]) EncodeNil() {
|
||||
e.w.writen1(simpleVdNil)
|
||||
func (e *simpleEncDriver) encoder() *Encoder {
|
||||
return &e.e
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver[T]) EncodeBool(b bool) {
|
||||
func (e *simpleEncDriver) EncodeNil() {
|
||||
e.e.encWr.writen1(simpleVdNil)
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver) EncodeBool(b bool) {
|
||||
if e.h.EncZeroValuesAsNil && e.e.c != containerMapKey && !b {
|
||||
e.EncodeNil()
|
||||
return
|
||||
}
|
||||
if b {
|
||||
e.w.writen1(simpleVdTrue)
|
||||
e.e.encWr.writen1(simpleVdTrue)
|
||||
} else {
|
||||
e.w.writen1(simpleVdFalse)
|
||||
e.e.encWr.writen1(simpleVdFalse)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver[T]) EncodeFloat32(f float32) {
|
||||
func (e *simpleEncDriver) EncodeFloat32(f float32) {
|
||||
if e.h.EncZeroValuesAsNil && e.e.c != containerMapKey && f == 0.0 {
|
||||
e.EncodeNil()
|
||||
return
|
||||
}
|
||||
e.w.writen1(simpleVdFloat32)
|
||||
e.w.writen4(bigen.PutUint32(math.Float32bits(f)))
|
||||
e.e.encWr.writen1(simpleVdFloat32)
|
||||
bigen.writeUint32(e.e.w(), math.Float32bits(f))
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver[T]) EncodeFloat64(f float64) {
|
||||
func (e *simpleEncDriver) EncodeFloat64(f float64) {
|
||||
if e.h.EncZeroValuesAsNil && e.e.c != containerMapKey && f == 0.0 {
|
||||
e.EncodeNil()
|
||||
return
|
||||
}
|
||||
e.w.writen1(simpleVdFloat64)
|
||||
e.w.writen8(bigen.PutUint64(math.Float64bits(f)))
|
||||
e.e.encWr.writen1(simpleVdFloat64)
|
||||
bigen.writeUint64(e.e.w(), math.Float64bits(f))
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver[T]) EncodeInt(v int64) {
|
||||
func (e *simpleEncDriver) EncodeInt(v int64) {
|
||||
if v < 0 {
|
||||
e.encUint(uint64(-v), simpleVdNegInt)
|
||||
} else {
|
||||
@@ -67,62 +113,62 @@ func (e *simpleEncDriver[T]) EncodeInt(v int64) {
|
||||
}
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver[T]) EncodeUint(v uint64) {
|
||||
func (e *simpleEncDriver) EncodeUint(v uint64) {
|
||||
e.encUint(v, simpleVdPosInt)
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver[T]) encUint(v uint64, bd uint8) {
|
||||
func (e *simpleEncDriver) encUint(v uint64, bd uint8) {
|
||||
if e.h.EncZeroValuesAsNil && e.e.c != containerMapKey && v == 0 {
|
||||
e.EncodeNil()
|
||||
return
|
||||
}
|
||||
if v <= math.MaxUint8 {
|
||||
e.w.writen2(bd, uint8(v))
|
||||
e.e.encWr.writen2(bd, uint8(v))
|
||||
} else if v <= math.MaxUint16 {
|
||||
e.w.writen1(bd + 1)
|
||||
e.w.writen2(bigen.PutUint16(uint16(v)))
|
||||
e.e.encWr.writen1(bd + 1)
|
||||
bigen.writeUint16(e.e.w(), uint16(v))
|
||||
} else if v <= math.MaxUint32 {
|
||||
e.w.writen1(bd + 2)
|
||||
e.w.writen4(bigen.PutUint32(uint32(v)))
|
||||
e.e.encWr.writen1(bd + 2)
|
||||
bigen.writeUint32(e.e.w(), uint32(v))
|
||||
} else { // if v <= math.MaxUint64 {
|
||||
e.w.writen1(bd + 3)
|
||||
e.w.writen8(bigen.PutUint64(v))
|
||||
e.e.encWr.writen1(bd + 3)
|
||||
bigen.writeUint64(e.e.w(), v)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver[T]) encLen(bd byte, length int) {
|
||||
func (e *simpleEncDriver) encLen(bd byte, length int) {
|
||||
if length == 0 {
|
||||
e.w.writen1(bd)
|
||||
e.e.encWr.writen1(bd)
|
||||
} else if length <= math.MaxUint8 {
|
||||
e.w.writen1(bd + 1)
|
||||
e.w.writen1(uint8(length))
|
||||
e.e.encWr.writen1(bd + 1)
|
||||
e.e.encWr.writen1(uint8(length))
|
||||
} else if length <= math.MaxUint16 {
|
||||
e.w.writen1(bd + 2)
|
||||
e.w.writen2(bigen.PutUint16(uint16(length)))
|
||||
e.e.encWr.writen1(bd + 2)
|
||||
bigen.writeUint16(e.e.w(), uint16(length))
|
||||
} else if int64(length) <= math.MaxUint32 {
|
||||
e.w.writen1(bd + 3)
|
||||
e.w.writen4(bigen.PutUint32(uint32(length)))
|
||||
e.e.encWr.writen1(bd + 3)
|
||||
bigen.writeUint32(e.e.w(), uint32(length))
|
||||
} else {
|
||||
e.w.writen1(bd + 4)
|
||||
e.w.writen8(bigen.PutUint64(uint64(length)))
|
||||
e.e.encWr.writen1(bd + 4)
|
||||
bigen.writeUint64(e.e.w(), uint64(length))
|
||||
}
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver[T]) EncodeExt(v interface{}, basetype reflect.Type, xtag uint64, ext Ext) {
|
||||
func (e *simpleEncDriver) EncodeExt(v interface{}, basetype reflect.Type, xtag uint64, ext Ext) {
|
||||
var bs0, bs []byte
|
||||
if ext == SelfExt {
|
||||
bs0 = e.e.blist.get(1024)
|
||||
bs = bs0
|
||||
sideEncode(e.h, &e.h.sideEncPool, func(se encoderI) { oneOffEncode(se, v, &bs, basetype, true) })
|
||||
e.e.sideEncode(v, basetype, &bs)
|
||||
} else {
|
||||
bs = ext.WriteExt(v)
|
||||
}
|
||||
if bs == nil {
|
||||
e.writeNilBytes()
|
||||
e.EncodeNil()
|
||||
goto END
|
||||
}
|
||||
e.encodeExtPreamble(uint8(xtag), len(bs))
|
||||
e.w.writeb(bs)
|
||||
e.e.encWr.writeb(bs)
|
||||
END:
|
||||
if ext == SelfExt {
|
||||
e.e.blist.put(bs)
|
||||
@@ -132,35 +178,25 @@ END:
|
||||
}
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver[T]) EncodeRawExt(re *RawExt) {
|
||||
func (e *simpleEncDriver) EncodeRawExt(re *RawExt) {
|
||||
e.encodeExtPreamble(uint8(re.Tag), len(re.Data))
|
||||
e.w.writeb(re.Data)
|
||||
e.e.encWr.writeb(re.Data)
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver[T]) encodeExtPreamble(xtag byte, length int) {
|
||||
func (e *simpleEncDriver) encodeExtPreamble(xtag byte, length int) {
|
||||
e.encLen(simpleVdExt, length)
|
||||
e.w.writen1(xtag)
|
||||
e.e.encWr.writen1(xtag)
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver[T]) WriteArrayStart(length int) {
|
||||
func (e *simpleEncDriver) WriteArrayStart(length int) {
|
||||
e.encLen(simpleVdArray, length)
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver[T]) WriteMapStart(length int) {
|
||||
func (e *simpleEncDriver) WriteMapStart(length int) {
|
||||
e.encLen(simpleVdMap, length)
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver[T]) WriteArrayEmpty() {
|
||||
// e.WriteArrayStart(0) = e.encLen(simpleVdArray, 0)
|
||||
e.w.writen1(simpleVdArray)
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver[T]) WriteMapEmpty() {
|
||||
// e.WriteMapStart(0) = e.encLen(simpleVdMap, 0)
|
||||
e.w.writen1(simpleVdMap)
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver[T]) EncodeString(v string) {
|
||||
func (e *simpleEncDriver) EncodeString(v string) {
|
||||
if e.h.EncZeroValuesAsNil && e.e.c != containerMapKey && v == "" {
|
||||
e.EncodeNil()
|
||||
return
|
||||
@@ -170,88 +206,57 @@ func (e *simpleEncDriver[T]) EncodeString(v string) {
|
||||
} else {
|
||||
e.encLen(simpleVdString, len(v))
|
||||
}
|
||||
e.w.writestr(v)
|
||||
e.e.encWr.writestr(v)
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver[T]) EncodeStringNoEscape4Json(v string) { e.EncodeString(v) }
|
||||
|
||||
func (e *simpleEncDriver[T]) EncodeStringBytesRaw(v []byte) {
|
||||
func (e *simpleEncDriver) EncodeStringBytesRaw(v []byte) {
|
||||
// if e.h.EncZeroValuesAsNil && e.c != containerMapKey && v == nil {
|
||||
e.encLen(simpleVdByteArray, len(v))
|
||||
e.w.writeb(v)
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver[T]) EncodeBytes(v []byte) {
|
||||
if v == nil {
|
||||
e.writeNilBytes()
|
||||
e.EncodeNil()
|
||||
return
|
||||
}
|
||||
e.EncodeStringBytesRaw(v)
|
||||
e.encLen(simpleVdByteArray, len(v))
|
||||
e.e.encWr.writeb(v)
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver[T]) encodeNilBytes() {
|
||||
b := byte(simpleVdNil)
|
||||
if e.h.NilCollectionToZeroLength {
|
||||
b = simpleVdArray
|
||||
}
|
||||
e.w.writen1(b)
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver[T]) writeNilOr(v byte) {
|
||||
if !e.h.NilCollectionToZeroLength {
|
||||
v = simpleVdNil
|
||||
}
|
||||
e.w.writen1(v)
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver[T]) writeNilArray() {
|
||||
e.writeNilOr(simpleVdArray)
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver[T]) writeNilMap() {
|
||||
e.writeNilOr(simpleVdMap)
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver[T]) writeNilBytes() {
|
||||
e.writeNilOr(simpleVdByteArray)
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver[T]) EncodeTime(t time.Time) {
|
||||
func (e *simpleEncDriver) EncodeTime(t time.Time) {
|
||||
// if e.h.EncZeroValuesAsNil && e.c != containerMapKey && t.IsZero() {
|
||||
if t.IsZero() {
|
||||
e.EncodeNil()
|
||||
return
|
||||
}
|
||||
v, err := t.MarshalBinary()
|
||||
halt.onerror(err)
|
||||
e.w.writen2(simpleVdTime, uint8(len(v)))
|
||||
e.w.writeb(v)
|
||||
e.e.onerror(err)
|
||||
e.e.encWr.writen2(simpleVdTime, uint8(len(v)))
|
||||
e.e.encWr.writeb(v)
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
|
||||
type simpleDecDriver[T decReader] struct {
|
||||
type simpleDecDriver struct {
|
||||
h *SimpleHandle
|
||||
d *decoderBase
|
||||
r T
|
||||
|
||||
bdAndBdread
|
||||
// bytes bool
|
||||
|
||||
_ bool
|
||||
noBuiltInTypes
|
||||
// decDriverNoopNumberHelper
|
||||
decDriverNoopContainerReader
|
||||
decInit2er
|
||||
|
||||
// ds interface{} // must be *decoder[simpleDecDriverM[bytes...]]
|
||||
decDriverNoopNumberHelper
|
||||
d Decoder
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver[T]) readNextBd() {
|
||||
d.bd = d.r.readn1()
|
||||
func (d *simpleDecDriver) decoder() *Decoder {
|
||||
return &d.d
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver) descBd() string {
|
||||
return sprintf("%v (%s)", d.bd, simpledesc(d.bd))
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver) readNextBd() {
|
||||
d.bd = d.d.decRd.readn1()
|
||||
d.bdRead = true
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver[T]) advanceNil() (null bool) {
|
||||
func (d *simpleDecDriver) advanceNil() (null bool) {
|
||||
if !d.bdRead {
|
||||
d.readNextBd()
|
||||
}
|
||||
@@ -262,7 +267,7 @@ func (d *simpleDecDriver[T]) advanceNil() (null bool) {
|
||||
return
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver[T]) ContainerType() (vt valueType) {
|
||||
func (d *simpleDecDriver) ContainerType() (vt valueType) {
|
||||
if !d.bdRead {
|
||||
d.readNextBd()
|
||||
}
|
||||
@@ -286,90 +291,88 @@ func (d *simpleDecDriver[T]) ContainerType() (vt valueType) {
|
||||
return valueTypeUnset
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver[T]) TryNil() bool {
|
||||
func (d *simpleDecDriver) TryNil() bool {
|
||||
return d.advanceNil()
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver[T]) decFloat() (f float64, ok bool) {
|
||||
func (d *simpleDecDriver) decFloat() (f float64, ok bool) {
|
||||
ok = true
|
||||
switch d.bd {
|
||||
case simpleVdFloat32:
|
||||
f = float64(math.Float32frombits(bigen.Uint32(d.r.readn4())))
|
||||
f = float64(math.Float32frombits(bigen.Uint32(d.d.decRd.readn4())))
|
||||
case simpleVdFloat64:
|
||||
f = math.Float64frombits(bigen.Uint64(d.r.readn8()))
|
||||
f = math.Float64frombits(bigen.Uint64(d.d.decRd.readn8()))
|
||||
default:
|
||||
ok = false
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver[T]) decInteger() (ui uint64, neg, ok bool) {
|
||||
func (d *simpleDecDriver) decInteger() (ui uint64, neg, ok bool) {
|
||||
ok = true
|
||||
switch d.bd {
|
||||
case simpleVdPosInt:
|
||||
ui = uint64(d.r.readn1())
|
||||
ui = uint64(d.d.decRd.readn1())
|
||||
case simpleVdPosInt + 1:
|
||||
ui = uint64(bigen.Uint16(d.r.readn2()))
|
||||
ui = uint64(bigen.Uint16(d.d.decRd.readn2()))
|
||||
case simpleVdPosInt + 2:
|
||||
ui = uint64(bigen.Uint32(d.r.readn4()))
|
||||
ui = uint64(bigen.Uint32(d.d.decRd.readn4()))
|
||||
case simpleVdPosInt + 3:
|
||||
ui = uint64(bigen.Uint64(d.r.readn8()))
|
||||
ui = uint64(bigen.Uint64(d.d.decRd.readn8()))
|
||||
case simpleVdNegInt:
|
||||
ui = uint64(d.r.readn1())
|
||||
ui = uint64(d.d.decRd.readn1())
|
||||
neg = true
|
||||
case simpleVdNegInt + 1:
|
||||
ui = uint64(bigen.Uint16(d.r.readn2()))
|
||||
ui = uint64(bigen.Uint16(d.d.decRd.readn2()))
|
||||
neg = true
|
||||
case simpleVdNegInt + 2:
|
||||
ui = uint64(bigen.Uint32(d.r.readn4()))
|
||||
ui = uint64(bigen.Uint32(d.d.decRd.readn4()))
|
||||
neg = true
|
||||
case simpleVdNegInt + 3:
|
||||
ui = uint64(bigen.Uint64(d.r.readn8()))
|
||||
ui = uint64(bigen.Uint64(d.d.decRd.readn8()))
|
||||
neg = true
|
||||
default:
|
||||
ok = false
|
||||
// halt.errorf("integer only valid from pos/neg integer1..8. Invalid descriptor: %v", d.bd)
|
||||
// d.d.errorf("integer only valid from pos/neg integer1..8. Invalid descriptor: %v", d.bd)
|
||||
}
|
||||
// DO NOT do this check below, because callers may only want the unsigned value:
|
||||
//
|
||||
// if ui > math.MaxInt64 {
|
||||
// halt.errorf("decIntAny: Integer out of range for signed int64: %v", ui)
|
||||
// d.d.errorf("decIntAny: Integer out of range for signed int64: %v", ui)
|
||||
// return
|
||||
// }
|
||||
return
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver[T]) DecodeInt64() (i int64) {
|
||||
func (d *simpleDecDriver) DecodeInt64() (i int64) {
|
||||
if d.advanceNil() {
|
||||
return
|
||||
}
|
||||
v1, v2, v3 := d.decInteger()
|
||||
i = decNegintPosintFloatNumberHelper{d}.int64(v1, v2, v3, false)
|
||||
i = decNegintPosintFloatNumberHelper{&d.d}.int64(d.decInteger())
|
||||
d.bdRead = false
|
||||
return
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver[T]) DecodeUint64() (ui uint64) {
|
||||
func (d *simpleDecDriver) DecodeUint64() (ui uint64) {
|
||||
if d.advanceNil() {
|
||||
return
|
||||
}
|
||||
ui = decNegintPosintFloatNumberHelper{d}.uint64(d.decInteger())
|
||||
ui = decNegintPosintFloatNumberHelper{&d.d}.uint64(d.decInteger())
|
||||
d.bdRead = false
|
||||
return
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver[T]) DecodeFloat64() (f float64) {
|
||||
func (d *simpleDecDriver) DecodeFloat64() (f float64) {
|
||||
if d.advanceNil() {
|
||||
return
|
||||
}
|
||||
v1, v2 := d.decFloat()
|
||||
f = decNegintPosintFloatNumberHelper{d}.float64(v1, v2, false)
|
||||
f = decNegintPosintFloatNumberHelper{&d.d}.float64(d.decFloat())
|
||||
d.bdRead = false
|
||||
return
|
||||
}
|
||||
|
||||
// bool can be decoded from bool only (single byte).
|
||||
func (d *simpleDecDriver[T]) DecodeBool() (b bool) {
|
||||
func (d *simpleDecDriver) DecodeBool() (b bool) {
|
||||
if d.advanceNil() {
|
||||
return
|
||||
}
|
||||
@@ -377,13 +380,13 @@ func (d *simpleDecDriver[T]) DecodeBool() (b bool) {
|
||||
} else if d.bd == simpleVdTrue {
|
||||
b = true
|
||||
} else {
|
||||
halt.errorf("cannot decode bool - %s: %x", msgBadDesc, d.bd)
|
||||
d.d.errorf("cannot decode bool - %s: %x", msgBadDesc, d.bd)
|
||||
}
|
||||
d.bdRead = false
|
||||
return
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver[T]) ReadMapStart() (length int) {
|
||||
func (d *simpleDecDriver) ReadMapStart() (length int) {
|
||||
if d.advanceNil() {
|
||||
return containerLenNil
|
||||
}
|
||||
@@ -391,7 +394,7 @@ func (d *simpleDecDriver[T]) ReadMapStart() (length int) {
|
||||
return d.decLen()
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver[T]) ReadArrayStart() (length int) {
|
||||
func (d *simpleDecDriver) ReadArrayStart() (length int) {
|
||||
if d.advanceNil() {
|
||||
return containerLenNil
|
||||
}
|
||||
@@ -399,128 +402,131 @@ func (d *simpleDecDriver[T]) ReadArrayStart() (length int) {
|
||||
return d.decLen()
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver[T]) uint2Len(ui uint64) int {
|
||||
func (d *simpleDecDriver) uint2Len(ui uint64) int {
|
||||
if chkOvf.Uint(ui, intBitsize) {
|
||||
halt.errorf("overflow integer: %v", ui)
|
||||
d.d.errorf("overflow integer: %v", ui)
|
||||
}
|
||||
return int(ui)
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver[T]) decLen() int {
|
||||
func (d *simpleDecDriver) decLen() int {
|
||||
switch d.bd & 7 { // d.bd % 8 {
|
||||
case 0:
|
||||
return 0
|
||||
case 1:
|
||||
return int(d.r.readn1())
|
||||
return int(d.d.decRd.readn1())
|
||||
case 2:
|
||||
return int(bigen.Uint16(d.r.readn2()))
|
||||
return int(bigen.Uint16(d.d.decRd.readn2()))
|
||||
case 3:
|
||||
return d.uint2Len(uint64(bigen.Uint32(d.r.readn4())))
|
||||
return d.uint2Len(uint64(bigen.Uint32(d.d.decRd.readn4())))
|
||||
case 4:
|
||||
return d.uint2Len(bigen.Uint64(d.r.readn8()))
|
||||
return d.uint2Len(bigen.Uint64(d.d.decRd.readn8()))
|
||||
}
|
||||
halt.errorf("cannot read length: bd%%8 must be in range 0..4. Got: %d", d.bd%8)
|
||||
d.d.errorf("cannot read length: bd%%8 must be in range 0..4. Got: %d", d.bd%8)
|
||||
return -1
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver[T]) DecodeStringAsBytes() ([]byte, dBytesAttachState) {
|
||||
return d.DecodeBytes()
|
||||
func (d *simpleDecDriver) DecodeStringAsBytes() (s []byte) {
|
||||
return d.DecodeBytes(nil)
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver[T]) DecodeBytes() (bs []byte, state dBytesAttachState) {
|
||||
func (d *simpleDecDriver) DecodeBytes(bs []byte) (bsOut []byte) {
|
||||
d.d.decByteState = decByteStateNone
|
||||
if d.advanceNil() {
|
||||
return
|
||||
}
|
||||
var cond bool
|
||||
// check if an "array" of uint8's (see ContainerType for how to infer if an array)
|
||||
if d.bd >= simpleVdArray && d.bd <= simpleVdArray+4 {
|
||||
if d.bd >= simpleVdArray && d.bd <= simpleVdMap+4 {
|
||||
if bs == nil {
|
||||
d.d.decByteState = decByteStateReuseBuf
|
||||
bs = d.d.b[:]
|
||||
}
|
||||
slen := d.ReadArrayStart()
|
||||
bs, cond = usableByteSlice(d.d.buf, slen)
|
||||
var changed bool
|
||||
if bs, changed = usableByteSlice(bs, slen); changed {
|
||||
d.d.decByteState = decByteStateNone
|
||||
}
|
||||
for i := 0; i < len(bs); i++ {
|
||||
bs[i] = uint8(chkOvf.UintV(d.DecodeUint64(), 8))
|
||||
}
|
||||
for i := len(bs); i < slen; i++ {
|
||||
bs = append(bs, uint8(chkOvf.UintV(d.DecodeUint64(), 8)))
|
||||
}
|
||||
if cond {
|
||||
d.d.buf = bs
|
||||
}
|
||||
state = dBytesAttachBuffer
|
||||
|
||||
return
|
||||
return bs
|
||||
}
|
||||
|
||||
clen := d.decLen()
|
||||
d.bdRead = false
|
||||
bs, cond = d.r.readxb(uint(clen))
|
||||
state = d.d.attachState(cond)
|
||||
return
|
||||
if d.d.zerocopy() {
|
||||
d.d.decByteState = decByteStateZerocopy
|
||||
return d.d.decRd.rb.readx(uint(clen))
|
||||
}
|
||||
if bs == nil {
|
||||
d.d.decByteState = decByteStateReuseBuf
|
||||
bs = d.d.b[:]
|
||||
}
|
||||
return decByteSlice(d.d.r(), clen, d.d.h.MaxInitLen, bs)
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver[T]) DecodeTime() (t time.Time) {
|
||||
func (d *simpleDecDriver) DecodeTime() (t time.Time) {
|
||||
if d.advanceNil() {
|
||||
return
|
||||
}
|
||||
if d.bd != simpleVdTime {
|
||||
halt.errorf("invalid descriptor for time.Time - expect 0x%x, received 0x%x", simpleVdTime, d.bd)
|
||||
d.d.errorf("invalid descriptor for time.Time - expect 0x%x, received 0x%x", simpleVdTime, d.bd)
|
||||
}
|
||||
d.bdRead = false
|
||||
clen := uint(d.r.readn1())
|
||||
b := d.r.readx(clen)
|
||||
halt.onerror((&t).UnmarshalBinary(b))
|
||||
clen := uint(d.d.decRd.readn1())
|
||||
b := d.d.decRd.readx(clen)
|
||||
d.d.onerror((&t).UnmarshalBinary(b))
|
||||
return
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver[T]) DecodeExt(rv interface{}, basetype reflect.Type, xtag uint64, ext Ext) {
|
||||
xbs, _, _, ok := d.decodeExtV(ext != nil, xtag)
|
||||
if !ok {
|
||||
func (d *simpleDecDriver) DecodeExt(rv interface{}, basetype reflect.Type, xtag uint64, ext Ext) {
|
||||
if xtag > 0xff {
|
||||
d.d.errorf("ext: tag must be <= 0xff; got: %v", xtag)
|
||||
}
|
||||
if d.advanceNil() {
|
||||
return
|
||||
}
|
||||
if ext == SelfExt {
|
||||
sideDecode(d.h, &d.h.sideDecPool, func(sd decoderI) { oneOffDecode(sd, rv, xbs, basetype, true) })
|
||||
xbs, realxtag1, zerocopy := d.decodeExtV(ext != nil, uint8(xtag))
|
||||
realxtag := uint64(realxtag1)
|
||||
if ext == nil {
|
||||
re := rv.(*RawExt)
|
||||
re.Tag = realxtag
|
||||
re.setData(xbs, zerocopy)
|
||||
} else if ext == SelfExt {
|
||||
d.d.sideDecode(rv, basetype, xbs)
|
||||
} else {
|
||||
ext.ReadExt(rv, xbs)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver[T]) DecodeRawExt(re *RawExt) {
|
||||
xbs, realxtag, state, ok := d.decodeExtV(false, 0)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
re.Tag = uint64(realxtag)
|
||||
re.setData(xbs, state >= dBytesAttachViewZerocopy)
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver[T]) decodeExtV(verifyTag bool, xtagIn uint64) (xbs []byte, xtag byte, bstate dBytesAttachState, ok bool) {
|
||||
if xtagIn > 0xff {
|
||||
halt.errorf("ext: tag must be <= 0xff; got: %v", xtagIn)
|
||||
}
|
||||
if d.advanceNil() {
|
||||
return
|
||||
}
|
||||
tag := uint8(xtagIn)
|
||||
func (d *simpleDecDriver) decodeExtV(verifyTag bool, tag byte) (xbs []byte, xtag byte, zerocopy bool) {
|
||||
switch d.bd {
|
||||
case simpleVdExt, simpleVdExt + 1, simpleVdExt + 2, simpleVdExt + 3, simpleVdExt + 4:
|
||||
l := d.decLen()
|
||||
xtag = d.r.readn1()
|
||||
xtag = d.d.decRd.readn1()
|
||||
if verifyTag && xtag != tag {
|
||||
halt.errorf("wrong extension tag. Got %b. Expecting: %v", xtag, tag)
|
||||
d.d.errorf("wrong extension tag. Got %b. Expecting: %v", xtag, tag)
|
||||
}
|
||||
if d.d.bytes {
|
||||
xbs = d.d.decRd.rb.readx(uint(l))
|
||||
zerocopy = true
|
||||
} else {
|
||||
xbs = decByteSlice(d.d.r(), l, d.d.h.MaxInitLen, d.d.b[:])
|
||||
}
|
||||
xbs, ok = d.r.readxb(uint(l))
|
||||
bstate = d.d.attachState(ok)
|
||||
case simpleVdByteArray, simpleVdByteArray + 1,
|
||||
simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
|
||||
xbs, bstate = d.DecodeBytes()
|
||||
xbs = d.DecodeBytes(nil)
|
||||
default:
|
||||
halt.errorf("ext - %s - expecting extensions/bytearray, got: 0x%x", msgBadDesc, d.bd)
|
||||
d.d.errorf("ext - %s - expecting extensions/bytearray, got: 0x%x", msgBadDesc, d.bd)
|
||||
}
|
||||
d.bdRead = false
|
||||
ok = true
|
||||
return
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver[T]) DecodeNaked() {
|
||||
func (d *simpleDecDriver) DecodeNaked() {
|
||||
if !d.bdRead {
|
||||
d.readNextBd()
|
||||
}
|
||||
@@ -560,20 +566,19 @@ func (d *simpleDecDriver[T]) DecodeNaked() {
|
||||
case simpleVdString, simpleVdString + 1,
|
||||
simpleVdString + 2, simpleVdString + 3, simpleVdString + 4:
|
||||
n.v = valueTypeString
|
||||
n.s = d.d.detach2Str(d.DecodeStringAsBytes())
|
||||
n.s = d.d.stringZC(d.DecodeStringAsBytes())
|
||||
case simpleVdByteArray, simpleVdByteArray + 1,
|
||||
simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
|
||||
d.d.fauxUnionReadRawBytes(d, false, d.h.RawToString) //, d.h.ZeroCopy)
|
||||
d.d.fauxUnionReadRawBytes(false)
|
||||
case simpleVdExt, simpleVdExt + 1, simpleVdExt + 2, simpleVdExt + 3, simpleVdExt + 4:
|
||||
n.v = valueTypeExt
|
||||
l := d.decLen()
|
||||
n.u = uint64(d.r.readn1())
|
||||
n.l = d.r.readx(uint(l))
|
||||
// MARKER: not necessary to detach for extensions
|
||||
// var useBuf bool
|
||||
// n.l, useBuf = d.r.readxb(uint(l))
|
||||
// n.a = d.d.attachState(useBuf)
|
||||
// n.l = d.d.detach2Bytes(n.l, nil, n.a)
|
||||
n.u = uint64(d.d.decRd.readn1())
|
||||
if d.d.bytes {
|
||||
n.l = d.d.decRd.rb.readx(uint(l))
|
||||
} else {
|
||||
n.l = decByteSlice(d.d.r(), l, d.d.h.MaxInitLen, d.d.b[:])
|
||||
}
|
||||
case simpleVdArray, simpleVdArray + 1, simpleVdArray + 2,
|
||||
simpleVdArray + 3, simpleVdArray + 4:
|
||||
n.v = valueTypeArray
|
||||
@@ -582,7 +587,7 @@ func (d *simpleDecDriver[T]) DecodeNaked() {
|
||||
n.v = valueTypeMap
|
||||
decodeFurther = true
|
||||
default:
|
||||
halt.errorf("cannot infer value - %s 0x%x", msgBadDesc, d.bd)
|
||||
d.d.errorf("cannot infer value - %s 0x%x", msgBadDesc, d.bd)
|
||||
}
|
||||
|
||||
if !decodeFurther {
|
||||
@@ -590,18 +595,32 @@ func (d *simpleDecDriver[T]) DecodeNaked() {
|
||||
}
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver[T]) nextValueBytes() (v []byte) {
|
||||
func (d *simpleDecDriver) nextValueBytes(v0 []byte) (v []byte) {
|
||||
if !d.bdRead {
|
||||
d.readNextBd()
|
||||
}
|
||||
d.r.startRecording()
|
||||
d.nextValueBytesBdReadR()
|
||||
v = d.r.stopRecording()
|
||||
v = v0
|
||||
var h = decNextValueBytesHelper{d: &d.d}
|
||||
var cursor = d.d.rb.c - 1
|
||||
h.append1(&v, d.bd)
|
||||
v = d.nextValueBytesBdReadR(v)
|
||||
d.bdRead = false
|
||||
h.bytesRdV(&v, cursor)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver[T]) nextValueBytesBdReadR() {
|
||||
func (d *simpleDecDriver) nextValueBytesR(v0 []byte) (v []byte) {
|
||||
d.readNextBd()
|
||||
v = v0
|
||||
var h = decNextValueBytesHelper{d: &d.d}
|
||||
h.append1(&v, d.bd)
|
||||
return d.nextValueBytesBdReadR(v)
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver) nextValueBytesBdReadR(v0 []byte) (v []byte) {
|
||||
v = v0
|
||||
var h = decNextValueBytesHelper{d: &d.d}
|
||||
|
||||
c := d.bd
|
||||
|
||||
var length uint
|
||||
@@ -610,33 +629,38 @@ func (d *simpleDecDriver[T]) nextValueBytesBdReadR() {
|
||||
case simpleVdNil, simpleVdFalse, simpleVdTrue, simpleVdString, simpleVdByteArray:
|
||||
// pass
|
||||
case simpleVdPosInt, simpleVdNegInt:
|
||||
d.r.readn1()
|
||||
h.append1(&v, d.d.decRd.readn1())
|
||||
case simpleVdPosInt + 1, simpleVdNegInt + 1:
|
||||
d.r.skip(2)
|
||||
h.appendN(&v, d.d.decRd.readx(2)...)
|
||||
case simpleVdPosInt + 2, simpleVdNegInt + 2, simpleVdFloat32:
|
||||
d.r.skip(4)
|
||||
h.appendN(&v, d.d.decRd.readx(4)...)
|
||||
case simpleVdPosInt + 3, simpleVdNegInt + 3, simpleVdFloat64:
|
||||
d.r.skip(8)
|
||||
h.appendN(&v, d.d.decRd.readx(8)...)
|
||||
case simpleVdTime:
|
||||
c = d.r.readn1()
|
||||
d.r.skip(uint(c))
|
||||
c = d.d.decRd.readn1()
|
||||
h.append1(&v, c)
|
||||
h.appendN(&v, d.d.decRd.readx(uint(c))...)
|
||||
|
||||
default:
|
||||
switch c & 7 { // c % 8 {
|
||||
case 0:
|
||||
length = 0
|
||||
case 1:
|
||||
b := d.r.readn1()
|
||||
b := d.d.decRd.readn1()
|
||||
length = uint(b)
|
||||
h.append1(&v, b)
|
||||
case 2:
|
||||
x := d.r.readn2()
|
||||
x := d.d.decRd.readn2()
|
||||
length = uint(bigen.Uint16(x))
|
||||
h.appendN(&v, x[:]...)
|
||||
case 3:
|
||||
x := d.r.readn4()
|
||||
x := d.d.decRd.readn4()
|
||||
length = uint(bigen.Uint32(x))
|
||||
h.appendN(&v, x[:]...)
|
||||
case 4:
|
||||
x := d.r.readn8()
|
||||
x := d.d.decRd.readn8()
|
||||
length = uint(bigen.Uint64(x))
|
||||
h.appendN(&v, x[:]...)
|
||||
}
|
||||
|
||||
bExt := c >= simpleVdExt && c <= simpleVdExt+7
|
||||
@@ -646,11 +670,11 @@ func (d *simpleDecDriver[T]) nextValueBytesBdReadR() {
|
||||
bMap := c >= simpleVdMap && c <= simpleVdMap+7
|
||||
|
||||
if !(bExt || bStr || bByteArray || bArray || bMap) {
|
||||
halt.errorf("cannot infer value - %s 0x%x", msgBadDesc, c)
|
||||
d.d.errorf("cannot infer value - %s 0x%x", msgBadDesc, c)
|
||||
}
|
||||
|
||||
if bExt {
|
||||
d.r.readn1() // tag
|
||||
h.append1(&v, d.d.decRd.readn1()) // tag
|
||||
}
|
||||
|
||||
if length == 0 {
|
||||
@@ -659,91 +683,68 @@ func (d *simpleDecDriver[T]) nextValueBytesBdReadR() {
|
||||
|
||||
if bArray {
|
||||
for i := uint(0); i < length; i++ {
|
||||
d.readNextBd()
|
||||
d.nextValueBytesBdReadR()
|
||||
v = d.nextValueBytesR(v)
|
||||
}
|
||||
} else if bMap {
|
||||
for i := uint(0); i < length; i++ {
|
||||
d.readNextBd()
|
||||
d.nextValueBytesBdReadR()
|
||||
d.readNextBd()
|
||||
d.nextValueBytesBdReadR()
|
||||
v = d.nextValueBytesR(v)
|
||||
v = d.nextValueBytesR(v)
|
||||
}
|
||||
} else {
|
||||
d.r.skip(length)
|
||||
h.appendN(&v, d.d.decRd.readx(length)...)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ----
|
||||
//------------------------------------
|
||||
|
||||
// SimpleHandle is a Handle for a very simple encoding format.
|
||||
//
|
||||
// The following below are similar across all format files (except for the format name).
|
||||
// simple is a simplistic codec similar to binc, but not as compact.
|
||||
// - Encoding of a value is always preceded by the descriptor byte (bd)
|
||||
// - True, false, nil are encoded fully in 1 byte (the descriptor)
|
||||
// - Integers (intXXX, uintXXX) are encoded in 1, 2, 4 or 8 bytes (plus a descriptor byte).
|
||||
// There are positive (uintXXX and intXXX >= 0) and negative (intXXX < 0) integers.
|
||||
// - Floats are encoded in 4 or 8 bytes (plus a descriptor byte)
|
||||
// - Length of containers (strings, bytes, array, map, extensions)
|
||||
// are encoded in 0, 1, 2, 4 or 8 bytes.
|
||||
// Zero-length containers have no length encoded.
|
||||
// For others, the number of bytes is given by pow(2, bd%3)
|
||||
// - maps are encoded as [bd] [length] [[key][value]]...
|
||||
// - arrays are encoded as [bd] [length] [value]...
|
||||
// - extensions are encoded as [bd] [length] [tag] [byte]...
|
||||
// - strings/bytearrays are encoded as [bd] [length] [byte]...
|
||||
// - time.Time are encoded as [bd] [length] [byte]...
|
||||
//
|
||||
// We keep them together here, so that we can easily copy and compare.
|
||||
|
||||
// ----
|
||||
|
||||
func (d *simpleEncDriver[T]) init(hh Handle, shared *encoderBase, enc encoderI) (fp interface{}) {
|
||||
callMake(&d.w)
|
||||
d.h = hh.(*SimpleHandle)
|
||||
d.e = shared
|
||||
if shared.bytes {
|
||||
fp = simpleFpEncBytes
|
||||
} else {
|
||||
fp = simpleFpEncIO
|
||||
}
|
||||
// d.w.init()
|
||||
d.init2(enc)
|
||||
return
|
||||
// The full spec will be published soon.
|
||||
type SimpleHandle struct {
|
||||
binaryEncodingType
|
||||
BasicHandle
|
||||
// EncZeroValuesAsNil says to encode zero values for numbers, bool, string, etc as nil
|
||||
EncZeroValuesAsNil bool
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver[T]) writeBytesAsis(b []byte) { e.w.writeb(b) }
|
||||
// Name returns the name of the handle: simple
|
||||
func (h *SimpleHandle) Name() string { return "simple" }
|
||||
|
||||
func (e *simpleEncDriver[T]) writerEnd() { e.w.end() }
|
||||
func (h *SimpleHandle) desc(bd byte) string { return simpledesc(bd) }
|
||||
|
||||
func (e *simpleEncDriver[T]) resetOutBytes(out *[]byte) {
|
||||
e.w.resetBytes(*out, out)
|
||||
func (h *SimpleHandle) newEncDriver() encDriver {
|
||||
var e = &simpleEncDriver{h: h}
|
||||
e.e.e = e
|
||||
e.e.init(h)
|
||||
e.reset()
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver[T]) resetOutIO(out io.Writer) {
|
||||
e.w.resetIO(out, e.h.WriterBufferSize, &e.e.blist)
|
||||
func (h *SimpleHandle) newDecDriver() decDriver {
|
||||
d := &simpleDecDriver{h: h}
|
||||
d.d.d = d
|
||||
d.d.init(h)
|
||||
d.reset()
|
||||
return d
|
||||
}
|
||||
|
||||
// ----
|
||||
|
||||
func (d *simpleDecDriver[T]) init(hh Handle, shared *decoderBase, dec decoderI) (fp interface{}) {
|
||||
callMake(&d.r)
|
||||
d.h = hh.(*SimpleHandle)
|
||||
d.d = shared
|
||||
if shared.bytes {
|
||||
fp = simpleFpDecBytes
|
||||
} else {
|
||||
fp = simpleFpDecIO
|
||||
}
|
||||
// d.r.init()
|
||||
d.init2(dec)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver[T]) NumBytesRead() int {
|
||||
return int(d.r.numread())
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver[T]) resetInBytes(in []byte) {
|
||||
d.r.resetBytes(in)
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver[T]) resetInIO(r io.Reader) {
|
||||
d.r.resetIO(r, d.h.ReaderBufferSize, d.h.MaxInitLen, &d.d.blist)
|
||||
}
|
||||
|
||||
// ---- (custom stanza)
|
||||
|
||||
func (d *simpleDecDriver[T]) descBd() string {
|
||||
return sprintf("%v (%s)", d.bd, simpledesc(d.bd))
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver[T]) DecodeFloat32() (f float32) {
|
||||
return float32(chkOvf.Float32V(d.DecodeFloat64()))
|
||||
}
|
||||
var _ decDriver = (*simpleDecDriver)(nil)
|
||||
var _ encDriver = (*simpleEncDriver)(nil)
|
||||
|
||||
167
vendor/github.com/ugorji/go/codec/writer.go
generated
vendored
167
vendor/github.com/ugorji/go/codec/writer.go
generated
vendored
@@ -3,14 +3,10 @@
|
||||
|
||||
package codec
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
const maxConsecutiveEmptyWrites = 16 // 2 is sufficient, 16 is enough, 64 is optimal
|
||||
import "io"
|
||||
|
||||
// encWriter abstracts writing to a byte array or to an io.Writer.
|
||||
type encWriterI interface {
|
||||
type encWriter interface {
|
||||
writeb([]byte)
|
||||
writestr(string)
|
||||
writeqstr(string) // write string wrapped in quotes ie "..."
|
||||
@@ -21,11 +17,7 @@ type encWriterI interface {
|
||||
writen4([4]byte)
|
||||
writen8([8]byte)
|
||||
|
||||
// isBytes() bool
|
||||
end()
|
||||
|
||||
resetIO(w io.Writer, bufsize int, blist *bytesFreeList)
|
||||
resetBytes(in []byte, out *[]byte)
|
||||
}
|
||||
|
||||
// ---------------------------------------------
|
||||
@@ -40,18 +32,16 @@ type bufioEncWriter struct {
|
||||
b [16]byte // scratch buffer and padding (cache-aligned)
|
||||
}
|
||||
|
||||
// MARKER: use setByteAt/byteAt to elide the bounds-checks
|
||||
// when we are sure that we don't go beyond the bounds.
|
||||
|
||||
func (z *bufioEncWriter) resetBytes(in []byte, out *[]byte) {
|
||||
halt.errorStr("resetBytes is unsupported by bufioEncWriter")
|
||||
}
|
||||
|
||||
func (z *bufioEncWriter) resetIO(w io.Writer, bufsize int, blist *bytesFreeList) {
|
||||
func (z *bufioEncWriter) reset(w io.Writer, bufsize int, blist *bytesFreelist) {
|
||||
z.w = w
|
||||
z.n = 0
|
||||
// use minimum bufsize of 16, matching the array z.b and accomodating writen methods (where n <= 8)
|
||||
bufsize = max(16, bufsize) // max(byteBufSize, bufsize)
|
||||
if bufsize <= 0 {
|
||||
bufsize = defEncByteBufSize
|
||||
}
|
||||
// bufsize must be >= 8, to accomodate writen methods (where n <= 8)
|
||||
if bufsize <= 8 {
|
||||
bufsize = 8
|
||||
}
|
||||
if cap(z.buf) < bufsize {
|
||||
if len(z.buf) > 0 && &z.buf[0] != &z.b[0] {
|
||||
blist.put(z.buf)
|
||||
@@ -66,19 +56,17 @@ func (z *bufioEncWriter) resetIO(w io.Writer, bufsize int, blist *bytesFreeList)
|
||||
}
|
||||
|
||||
func (z *bufioEncWriter) flushErr() (err error) {
|
||||
var n int
|
||||
for i := maxConsecutiveEmptyReads; i > 0; i-- {
|
||||
n, err = z.w.Write(z.buf[:z.n])
|
||||
z.n -= n
|
||||
if z.n == 0 || err != nil {
|
||||
return
|
||||
n, err := z.w.Write(z.buf[:z.n])
|
||||
z.n -= n
|
||||
if z.n > 0 {
|
||||
if err == nil {
|
||||
err = io.ErrShortWrite
|
||||
}
|
||||
// at this point: z.n > 0 && err == nil
|
||||
if n > 0 {
|
||||
copy(z.buf, z.buf[n:z.n+n])
|
||||
}
|
||||
}
|
||||
return io.ErrShortWrite // OR io.ErrNoProgress: not enough (or no) data written
|
||||
return err
|
||||
}
|
||||
|
||||
func (z *bufioEncWriter) flush() {
|
||||
@@ -143,7 +131,6 @@ func (z *bufioEncWriter) writen1(b1 byte) {
|
||||
// z.buf[z.n] = b1
|
||||
z.n++
|
||||
}
|
||||
|
||||
func (z *bufioEncWriter) writen2(b1, b2 byte) {
|
||||
if 2 > len(z.buf)-z.n {
|
||||
z.flush()
|
||||
@@ -182,14 +169,8 @@ func (z *bufioEncWriter) endErr() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (z *bufioEncWriter) end() {
|
||||
halt.onerror(z.endErr())
|
||||
}
|
||||
|
||||
// ---------------------------------------------
|
||||
|
||||
var bytesEncAppenderDefOut = []byte{}
|
||||
|
||||
// bytesEncAppender implements encWriter and can write to an byte slice.
|
||||
type bytesEncAppender struct {
|
||||
b []byte
|
||||
@@ -222,18 +203,122 @@ func (z *bytesEncAppender) writen4(b [4]byte) {
|
||||
|
||||
func (z *bytesEncAppender) writen8(b [8]byte) {
|
||||
z.b = append(z.b, b[:]...)
|
||||
// z.b = append(z.b, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7])
|
||||
// z.b = append(z.b, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]) // prevents inlining encWr.writen4
|
||||
}
|
||||
|
||||
func (z *bytesEncAppender) end() {
|
||||
func (z *bytesEncAppender) endErr() error {
|
||||
*(z.out) = z.b
|
||||
return nil
|
||||
}
|
||||
|
||||
func (z *bytesEncAppender) resetBytes(in []byte, out *[]byte) {
|
||||
func (z *bytesEncAppender) reset(in []byte, out *[]byte) {
|
||||
z.b = in[:0]
|
||||
z.out = out
|
||||
}
|
||||
|
||||
func (z *bytesEncAppender) resetIO(w io.Writer, bufsize int, blist *bytesFreeList) {
|
||||
halt.errorStr("resetIO is unsupported by bytesEncAppender")
|
||||
// --------------------------------------------------
|
||||
|
||||
type encWr struct {
|
||||
wb bytesEncAppender
|
||||
wf *bufioEncWriter
|
||||
|
||||
bytes bool // encoding to []byte
|
||||
|
||||
// MARKER: these fields below should belong directly in Encoder.
|
||||
// we pack them here for space efficiency and cache-line optimization.
|
||||
|
||||
js bool // is json encoder?
|
||||
be bool // is binary encoder?
|
||||
|
||||
c containerState
|
||||
|
||||
calls uint16
|
||||
seq uint16 // sequencer (e.g. used by binc for symbols, etc)
|
||||
}
|
||||
|
||||
// MARKER: manually inline bytesEncAppender.writenx/writeqstr methods,
|
||||
// as calling them causes encWr.writenx/writeqstr methods to not be inlined (cost > 80).
|
||||
//
|
||||
// i.e. e.g. instead of writing z.wb.writen2(b1, b2), use z.wb.b = append(z.wb.b, b1, b2)
|
||||
|
||||
func (z *encWr) writeb(s []byte) {
|
||||
if z.bytes {
|
||||
z.wb.writeb(s)
|
||||
} else {
|
||||
z.wf.writeb(s)
|
||||
}
|
||||
}
|
||||
func (z *encWr) writestr(s string) {
|
||||
if z.bytes {
|
||||
z.wb.writestr(s)
|
||||
} else {
|
||||
z.wf.writestr(s)
|
||||
}
|
||||
}
|
||||
|
||||
// MARKER: Add WriteStr to be called directly by generated code without a genHelper forwarding function.
|
||||
// Go's inlining model adds cost for forwarding functions, preventing inlining (cost goes above 80 budget).
|
||||
|
||||
func (z *encWr) WriteStr(s string) {
|
||||
if z.bytes {
|
||||
z.wb.writestr(s)
|
||||
} else {
|
||||
z.wf.writestr(s)
|
||||
}
|
||||
}
|
||||
|
||||
func (z *encWr) writen1(b1 byte) {
|
||||
if z.bytes {
|
||||
z.wb.writen1(b1)
|
||||
} else {
|
||||
z.wf.writen1(b1)
|
||||
}
|
||||
}
|
||||
|
||||
func (z *encWr) writen2(b1, b2 byte) {
|
||||
if z.bytes {
|
||||
// MARKER: z.wb.writen2(b1, b2)
|
||||
z.wb.b = append(z.wb.b, b1, b2)
|
||||
} else {
|
||||
z.wf.writen2(b1, b2)
|
||||
}
|
||||
}
|
||||
|
||||
func (z *encWr) writen4(b [4]byte) {
|
||||
if z.bytes {
|
||||
// MARKER: z.wb.writen4(b1, b2, b3, b4)
|
||||
z.wb.b = append(z.wb.b, b[:]...)
|
||||
// z.wb.writen4(b)
|
||||
} else {
|
||||
z.wf.writen4(b)
|
||||
}
|
||||
}
|
||||
func (z *encWr) writen8(b [8]byte) {
|
||||
if z.bytes {
|
||||
// z.wb.b = append(z.wb.b, b[:]...)
|
||||
z.wb.writen8(b)
|
||||
} else {
|
||||
z.wf.writen8(b)
|
||||
}
|
||||
}
|
||||
|
||||
func (z *encWr) writeqstr(s string) {
|
||||
if z.bytes {
|
||||
// MARKER: z.wb.writeqstr(s)
|
||||
z.wb.b = append(append(append(z.wb.b, '"'), s...), '"')
|
||||
} else {
|
||||
z.wf.writeqstr(s)
|
||||
}
|
||||
}
|
||||
|
||||
func (z *encWr) endErr() error {
|
||||
if z.bytes {
|
||||
return z.wb.endErr()
|
||||
}
|
||||
return z.wf.endErr()
|
||||
}
|
||||
|
||||
func (z *encWr) end() {
|
||||
halt.onerror(z.endErr())
|
||||
}
|
||||
|
||||
var _ encWriter = (*encWr)(nil)
|
||||
|
||||
Reference in New Issue
Block a user