get packer plugin sdk version 0.0.12 (#10612)
This commit is contained in:
parent
37769c2b95
commit
915372c73d
3
go.mod
3
go.mod
|
@ -50,7 +50,7 @@ require (
|
|||
github.com/hashicorp/go-uuid v1.0.2
|
||||
github.com/hashicorp/go-version v1.2.0
|
||||
github.com/hashicorp/hcl/v2 v2.8.0
|
||||
github.com/hashicorp/packer-plugin-sdk v0.0.11
|
||||
github.com/hashicorp/packer-plugin-sdk v0.0.12
|
||||
github.com/hashicorp/vault/api v1.0.4
|
||||
github.com/hetznercloud/hcloud-go v1.15.1
|
||||
github.com/hyperonecom/h1-client-go v0.0.0-20191203060043-b46280e4c4a4
|
||||
|
@ -76,7 +76,6 @@ require (
|
|||
github.com/profitbricks/profitbricks-sdk-go v4.0.2+incompatible
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.7
|
||||
github.com/shirou/gopsutil v2.18.12+incompatible
|
||||
github.com/smartystreets/goconvey v1.6.4 // indirect
|
||||
github.com/stretchr/testify v1.6.1
|
||||
github.com/tencentcloud/tencentcloud-sdk-go v3.0.222+incompatible
|
||||
github.com/ucloud/ucloud-sdk-go v0.16.3
|
||||
|
|
7
go.sum
7
go.sum
|
@ -393,6 +393,7 @@ github.com/hashicorp/packer v1.6.7-0.20210112155033-1bc89e34714f/go.mod h1:sKsux
|
|||
github.com/hashicorp/packer v1.6.7-0.20210120105538-140685fb4f8b/go.mod h1:Yaw0q8brThFN2PKMWMRcuhQBuwPVDJRHHioNuMJTS7Q=
|
||||
github.com/hashicorp/packer v1.6.7-0.20210125170305-539638b0f951/go.mod h1:Z3eunaxVQ3XgQ+rW7TEH0T/PRQzCUSyCBUTkm/VL7io=
|
||||
github.com/hashicorp/packer v1.6.7-0.20210126105722-aef4ced967ec/go.mod h1:2+Vo/c/fA+TD9yFc/h9jQMFm4yG+IymQIr0OdJJOPiE=
|
||||
github.com/hashicorp/packer v1.6.7-0.20210208125835-f616955ebcb6/go.mod h1:7f5ZpTTRG53rQ58BcTADuTnpiBcB3wapuxl4sF2sGMM=
|
||||
github.com/hashicorp/packer-plugin-sdk v0.0.6 h1:BN2G4APXSMvDURFdnk+6DspwsU83pZeMsbEur7NmGsA=
|
||||
github.com/hashicorp/packer-plugin-sdk v0.0.6/go.mod h1:Nvh28f+Jmpp2rcaN79bULTouNkGNDRfHckhHKTAXtyU=
|
||||
github.com/hashicorp/packer-plugin-sdk v0.0.6/go.mod h1:Nvh28f+Jmpp2rcaN79bULTouNkGNDRfHckhHKTAXtyU=
|
||||
|
@ -405,6 +406,8 @@ github.com/hashicorp/packer-plugin-sdk v0.0.10-0.20210126105622-8e1648006d93 h1:
|
|||
github.com/hashicorp/packer-plugin-sdk v0.0.10-0.20210126105622-8e1648006d93/go.mod h1:AtWQLNfpn7cgH2SmZ1PTedwqNOhiPvzcuKfH5sDvIQ0=
|
||||
github.com/hashicorp/packer-plugin-sdk v0.0.11 h1:nUurEGaJtpVDyg94bKC2xOXWf1TqQ+++GovFUnP5REI=
|
||||
github.com/hashicorp/packer-plugin-sdk v0.0.11/go.mod h1:GNb0WNs7zibb8vzUZce1As64z2AW0FEMwhe2J7/NW5I=
|
||||
github.com/hashicorp/packer-plugin-sdk v0.0.12 h1:eagxsrborfhc0E8zvDVCiRE9pQkjBw/6jm23jp0D8RU=
|
||||
github.com/hashicorp/packer-plugin-sdk v0.0.12/go.mod h1:hs82OYeufirGG6KRENMpjBWomnIlte99X6wXAPThJ5I=
|
||||
github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hashicorp/serf v0.9.2 h1:yJoyfZXo4Pk2p/M/viW+YLibBFiIbKoP79gu7kDAFP0=
|
||||
|
@ -638,6 +641,10 @@ github.com/ufilesdk-dev/ufile-gosdk v0.0.0-20190830075812-b4dbc4ef43a6 h1:FAWNiq
|
|||
github.com/ufilesdk-dev/ufile-gosdk v0.0.0-20190830075812-b4dbc4ef43a6/go.mod h1:R5FMQxkQ+QK/9Vz+jfnJP4rZIktYrRcWmuAnbOSkROI=
|
||||
github.com/ugorji/go v0.0.0-20151218193438-646ae4a518c1 h1:U6ufy3mLDgg9RYupntOvAF7xCmNNquyKaYaaVHo1Nnk=
|
||||
github.com/ugorji/go v0.0.0-20151218193438-646ae4a518c1/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
|
||||
github.com/ugorji/go v1.2.4 h1:cTciPbZ/VSOzCLKclmssnfQ/jyoVyOcJ3aoJyUV1Urc=
|
||||
github.com/ugorji/go v1.2.4/go.mod h1:EuaSCk8iZMdIspsu6HXH7X2UGKw1ezO4wCfGszGmmo4=
|
||||
github.com/ugorji/go/codec v1.2.4 h1:C5VurWRRCKjuENsbM6GYVw8W++WVW9rSxoACKIvxzz8=
|
||||
github.com/ugorji/go/codec v1.2.4/go.mod h1:bWBu1+kIRWcF8uMklKaJrR6fTWQOwAlrIzX22pHwryA=
|
||||
github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok=
|
||||
github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
|
||||
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
|
||||
|
|
|
@ -44,8 +44,7 @@ func newClientWithMux(mux *muxBroker, streamId uint32) (*Client, error) {
|
|||
}
|
||||
|
||||
h := &codec.MsgpackHandle{
|
||||
RawToString: true,
|
||||
WriteExt: true,
|
||||
WriteExt: true,
|
||||
}
|
||||
clientCodec := codec.GoRpc.ClientCodec(clientConn, h)
|
||||
|
||||
|
|
|
@ -153,8 +153,7 @@ func (s *PluginServer) Serve() {
|
|||
defer stream.Close()
|
||||
|
||||
h := &codec.MsgpackHandle{
|
||||
RawToString: true,
|
||||
WriteExt: true,
|
||||
WriteExt: true,
|
||||
}
|
||||
rpcCodec := codec.GoRpc.ServerCodec(stream, h)
|
||||
s.server.ServeCodec(rpcCodec)
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
|
||||
// Use of this source code is governed by a MIT license found in the LICENSE file.
|
||||
|
||||
package codec // import "github.com/ugorji/go/codec"
|
||||
|
||||
// This establishes that this package must be imported as github.com/ugorji/go/codec.
|
||||
// It makes forking easier, and plays well with pre-module releases of go.
|
2
vendor/github.com/ugorji/go/LICENSE → vendor/github.com/ugorji/go/codec/LICENSE
generated
vendored
2
vendor/github.com/ugorji/go/LICENSE → vendor/github.com/ugorji/go/codec/LICENSE
generated
vendored
|
@ -1,6 +1,6 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2012-2015 Ugorji Nwoke.
|
||||
Copyright (c) 2012-2020 Ugorji Nwoke.
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
@ -1,7 +1,7 @@
|
|||
# Codec
|
||||
# Package Documentation for github.com/ugorji/go/codec
|
||||
|
||||
High Performance, Feature-Rich Idiomatic Go codec/encoding library for
|
||||
binc, msgpack, cbor, json.
|
||||
Package codec provides a High Performance, Feature-Rich Idiomatic Go 1.4+
|
||||
codec/encoding library for binc, msgpack, cbor, json.
|
||||
|
||||
Supported Serialization formats are:
|
||||
|
||||
|
@ -11,36 +11,31 @@ Supported Serialization formats are:
|
|||
- json: http://json.org http://tools.ietf.org/html/rfc7159
|
||||
- simple:
|
||||
|
||||
To install:
|
||||
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 i.e. 'go install -tags=safe ...'.
|
||||
|
||||
go get github.com/ugorji/go/codec
|
||||
This library works with both the standard `gc` and the `gccgo` compilers.
|
||||
|
||||
This package understands the `unsafe` tag, to allow using unsafe semantics:
|
||||
For detailed usage information, read the primer at
|
||||
http://ugorji.net/blog/go-codec-primer .
|
||||
|
||||
- When decoding into a struct, you need to read the field name as a string
|
||||
so you can find the struct field it is mapped to.
|
||||
Using `unsafe` will bypass the allocation and copying overhead of `[]byte->string` conversion.
|
||||
|
||||
To use it, you must pass the `unsafe` tag during install:
|
||||
|
||||
```
|
||||
go install -tags=unsafe github.com/ugorji/go/codec
|
||||
```
|
||||
|
||||
Online documentation: http://godoc.org/github.com/ugorji/go/codec
|
||||
Detailed Usage/How-to Primer: http://ugorji.net/blog/go-codec-primer
|
||||
|
||||
The idiomatic Go support is as seen in other encoding packages in
|
||||
the standard library (ie json, xml, gob, etc).
|
||||
The idiomatic Go support is as seen in other encoding packages in the
|
||||
standard library (ie json, xml, gob, etc).
|
||||
|
||||
Rich Feature Set includes:
|
||||
|
||||
- Simple but extremely powerful and feature-rich API
|
||||
- Support for go 1.4 and above, while selectively using newer APIs for later releases
|
||||
- Excellent code coverage ( > 90% )
|
||||
- Very High Performance.
|
||||
Our extensive benchmarks show us outperforming Gob, Json, Bson, etc by 2-4X.
|
||||
- Multiple conversions:
|
||||
Package coerces types where appropriate
|
||||
e.g. decode an int in the stream into a float, etc.
|
||||
- Careful selected use of 'unsafe' for targeted performance gains.
|
||||
- 100% safe mode supported, where 'unsafe' is not used at all.
|
||||
- Lock-free (sans mutex) concurrency for scaling to 100's of cores
|
||||
- In-place updates during decode, with option to zero value in maps and slices prior to decode
|
||||
- Coerce types where appropriate
|
||||
e.g. decode an int in the stream into a float, decode numbers from formatted strings, etc
|
||||
- Corner Cases:
|
||||
Overflows, nil maps/slices, nil values in streams are handled correctly
|
||||
- Standard field renaming via tags
|
||||
|
@ -49,13 +44,19 @@ Rich Feature Set includes:
|
|||
(struct, slice, map, primitives, pointers, interface{}, etc)
|
||||
- Extensions to support efficient encoding/decoding of any named types
|
||||
- Support encoding.(Binary|Text)(M|Unm)arshaler interfaces
|
||||
- Support using existence of `IsZero() bool` to determine if a value is a zero value.
|
||||
Analogous to time.Time.IsZero() bool.
|
||||
- Decoding without a schema (into a interface{}).
|
||||
Includes Options to configure what specific map or slice type to use
|
||||
when decoding an encoded list or map into a nil interface{}
|
||||
- Mapping a non-interface type to an interface, so we can decode appropriately
|
||||
into any interface type with a correctly configured non-interface value.
|
||||
- Encode a struct as an array, and decode struct from an array in the data stream
|
||||
- Option to encode struct keys as numbers (instead of strings)
|
||||
(to support structured streams with fields encoded as numeric codes)
|
||||
- Comprehensive support for anonymous fields
|
||||
- Fast (no-reflection) encoding/decoding of common maps and slices
|
||||
- Code-generation for faster performance.
|
||||
- Code-generation for faster performance, supported in go 1.6+
|
||||
- Support binary (e.g. messagepack, cbor) and text (e.g. json) formats
|
||||
- Support indefinite-length formats to enable true streaming
|
||||
(for formats which support it e.g. json, cbor)
|
||||
|
@ -65,42 +66,88 @@ Rich Feature Set includes:
|
|||
- Never silently skip data when decoding.
|
||||
User decides whether to return an error or silently skip data when keys or indexes
|
||||
in the data stream do not map to fields in the struct.
|
||||
- Detect and error when encoding a cyclic reference (instead of stack overflow shutdown)
|
||||
- Encode/Decode from/to chan types (for iterative streaming support)
|
||||
- Drop-in replacement for encoding/json. `json:` key in struct tag supported.
|
||||
- Provides a RPC Server and Client Codec for net/rpc communication protocol.
|
||||
- Handle unique idiosynchracies of codecs e.g.
|
||||
- Handle unique idiosyncrasies of codecs e.g.
|
||||
- For messagepack, configure how ambiguities in handling raw bytes are resolved
|
||||
- For messagepack, provide rpc server/client codec to support
|
||||
msgpack-rpc protocol defined at:
|
||||
https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md
|
||||
|
||||
|
||||
## Extension Support
|
||||
|
||||
Users can register a function to handle the encoding or decoding of
|
||||
their custom types.
|
||||
Users can register a function to handle the encoding or decoding of their
|
||||
custom types.
|
||||
|
||||
There are no restrictions on what the custom type can be. Some examples:
|
||||
|
||||
```go
|
||||
type BisSet []int
|
||||
type BitSet64 uint64
|
||||
type UUID string
|
||||
type MyStructWithUnexportedFields struct { a int; b bool; c []int; }
|
||||
type GifImage struct { ... }
|
||||
```
|
||||
|
||||
As an illustration, MyStructWithUnexportedFields would normally be encoded
|
||||
as an empty map because it has no exported fields, while UUID would be
|
||||
encoded as a string. However, with extension support, you can encode any of
|
||||
these however you like.
|
||||
|
||||
There is also seamless support provided for registering an extension (with a
|
||||
tag) but letting the encoding mechanism default to the standard way.
|
||||
|
||||
|
||||
## Custom Encoding and Decoding
|
||||
|
||||
This package maintains symmetry in the encoding and decoding halfs. We
|
||||
determine how to encode or decode by walking this decision tree
|
||||
|
||||
- is there an extension registered for the type?
|
||||
- is type a codec.Selfer?
|
||||
- is format binary, and is type a encoding.BinaryMarshaler and BinaryUnmarshaler?
|
||||
- is format specifically json, and is type a encoding/json.Marshaler and Unmarshaler?
|
||||
- is format text-based, and type an encoding.TextMarshaler and TextUnmarshaler?
|
||||
- else we use a pair of functions based on the "kind" of the type e.g. map, slice, int64, etc
|
||||
|
||||
This symmetry is important to reduce chances of issues happening because the
|
||||
encoding and decoding sides are out of sync e.g. decoded via very specific
|
||||
encoding.TextUnmarshaler but encoded via kind-specific generalized mode.
|
||||
|
||||
Consequently, if a type only defines one-half of the symmetry (e.g. it
|
||||
implements UnmarshalJSON() but not MarshalJSON() ), then that type doesn't
|
||||
satisfy the check and we will continue walking down the decision tree.
|
||||
|
||||
As an illustration, MyStructWithUnexportedFields would normally be
|
||||
encoded as an empty map because it has no exported fields, while UUID
|
||||
would be encoded as a string. However, with extension support, you can
|
||||
encode any of these however you like.
|
||||
|
||||
## RPC
|
||||
|
||||
RPC Client and Server Codecs are implemented, so the codecs can be used
|
||||
with the standard net/rpc package.
|
||||
RPC Client and Server Codecs are implemented, so the codecs can be used with
|
||||
the standard net/rpc package.
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
Typical usage model:
|
||||
The Handle is SAFE for concurrent READ, but NOT SAFE for concurrent
|
||||
modification.
|
||||
|
||||
The Encoder and Decoder are NOT safe for concurrent use.
|
||||
|
||||
Consequently, the usage model is basically:
|
||||
|
||||
- Create and initialize the Handle before any use.
|
||||
Once created, DO NOT modify it.
|
||||
- Multiple Encoders or Decoders can now use the Handle concurrently.
|
||||
They only read information off the Handle (never write).
|
||||
- However, each Encoder or Decoder MUST not be used concurrently
|
||||
- To re-use an Encoder/Decoder, call Reset(...) on it first.
|
||||
This allows you use state maintained on the Encoder/Decoder.
|
||||
|
||||
Sample usage model:
|
||||
|
||||
```go
|
||||
// create and configure Handle
|
||||
var (
|
||||
bh codec.BincHandle
|
||||
|
@ -145,4 +192,92 @@ Typical usage model:
|
|||
rpcCodec := codec.GoRpc.ClientCodec(conn, h)
|
||||
//OR rpcCodec := codec.MsgpackSpecRpc.ClientCodec(conn, h)
|
||||
client := rpc.NewClientWithCodec(rpcCodec)
|
||||
```
|
||||
|
||||
|
||||
## Running Tests
|
||||
|
||||
To run tests, use the following:
|
||||
|
||||
```
|
||||
go test
|
||||
```
|
||||
|
||||
To run the full suite of tests, use the following:
|
||||
|
||||
```
|
||||
go test -tags alltests -run Suite
|
||||
```
|
||||
|
||||
You can run the tag 'safe' to run tests or build in safe mode. e.g.
|
||||
|
||||
```
|
||||
go test -tags safe -run Json
|
||||
go test -tags "alltests safe" -run Suite
|
||||
```
|
||||
|
||||
## Running Benchmarks
|
||||
|
||||
```
|
||||
cd bench
|
||||
go test -bench . -benchmem -benchtime 1s
|
||||
```
|
||||
|
||||
Please see http://github.com/ugorji/go-codec-bench .
|
||||
|
||||
|
||||
## Caveats
|
||||
|
||||
Struct fields matching the following are ignored during encoding and
|
||||
decoding
|
||||
|
||||
- struct tag value set to -
|
||||
- func, complex numbers, unsafe pointers
|
||||
- unexported and not embedded
|
||||
- unexported and embedded and not struct kind
|
||||
- unexported and embedded pointers (from go1.10)
|
||||
|
||||
Every other field in a struct will be encoded/decoded.
|
||||
|
||||
Embedded fields are encoded as if they exist in the top-level struct, with
|
||||
some caveats. See Encode documentation.
|
||||
|
||||
## Exported Package API
|
||||
|
||||
```go
|
||||
const CborStreamBytes byte = 0x5f ...
|
||||
const GenVersion = 23
|
||||
var SelfExt = &extFailWrapper{}
|
||||
var GoRpc goRpc
|
||||
var MsgpackSpecRpc msgpackSpecRpc
|
||||
func GenHelper() (g genHelper)
|
||||
type BasicHandle struct{ ... }
|
||||
type BincHandle struct{ ... }
|
||||
type BytesExt interface{ ... }
|
||||
type CborHandle struct{ ... }
|
||||
type DecodeOptions struct{ ... }
|
||||
type Decoder struct{ ... }
|
||||
func NewDecoder(r io.Reader, h Handle) *Decoder
|
||||
func NewDecoderBytes(in []byte, h Handle) *Decoder
|
||||
func NewDecoderString(s string, h Handle) *Decoder
|
||||
type EncodeOptions struct{ ... }
|
||||
type Encoder struct{ ... }
|
||||
func NewEncoder(w io.Writer, h Handle) *Encoder
|
||||
func NewEncoderBytes(out *[]byte, h Handle) *Encoder
|
||||
type Ext interface{ ... }
|
||||
type Handle interface{ ... }
|
||||
type InterfaceExt interface{ ... }
|
||||
type JsonHandle struct{ ... }
|
||||
type MapBySlice interface{ ... }
|
||||
type MissingFielder interface{ ... }
|
||||
type MsgpackHandle struct{ ... }
|
||||
type MsgpackSpecRpcMultiArgs []interface{}
|
||||
type RPCOptions struct{ ... }
|
||||
type Raw []byte
|
||||
type RawExt struct{ ... }
|
||||
type Rpc interface{ ... }
|
||||
type Selfer interface{ ... }
|
||||
type SimpleHandle struct{ ... }
|
||||
type TypeInfos struct{ ... }
|
||||
func NewTypeInfos(tags []string) *TypeInfos
|
||||
```
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,350 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Run all the different permutations of all the tests and other things
|
||||
# This helps ensure that nothing gets broken.
|
||||
|
||||
_tests() {
|
||||
local vet="" # TODO: make it off
|
||||
local gover=$( ${gocmd} version | cut -f 3 -d ' ' )
|
||||
[[ $( ${gocmd} version ) == *"gccgo"* ]] && 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 notfastpath"
|
||||
# we test the following permutations wnich all execute different code paths as below.
|
||||
echo "TestCodecSuite: (fastpath/unsafe), (fastpath/!unsafe), (!fastpath/!unsafe), (codecgen/unsafe)"
|
||||
local nc=1 # count
|
||||
local a=( "" "safe" "notfastpath 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" "$@" &&
|
||||
${gocmd} test ${zargs[*]} ${ztestargs[*]} -vet "$vet" -tags "alltests $i" -count $nc -run "TestCodecSuite" "${c[@]}" "$@" &
|
||||
b+=("${i2// /-}.cov.out")
|
||||
[[ "$zwait" == "1" ]] && wait
|
||||
|
||||
# if [[ "$?" != 0 ]]; then return 1; fi
|
||||
done
|
||||
if [[ "$zextra" == "1" ]]; then
|
||||
[[ "$zwait" == "1" ]] && echo ">>>> TAGS: 'notfastpath x'; RUN: 'Test.*X$'"
|
||||
[[ "$zcover" == "1" ]] && c=( -coverprofile "x.cov.out" )
|
||||
${gocmd} test ${zargs[*]} ${ztestargs[*]} -vet "$vet" -tags "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.
|
||||
[[ "$zcover" == "1" ]] &&
|
||||
command -v gocovmerge &&
|
||||
gocovmerge "${b[@]}" > __merge.cov.out &&
|
||||
${gocmd} tool cover -html=__merge.cov.out
|
||||
}
|
||||
|
||||
# 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 "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 "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 gen-helper.generated.go fast-path.generated.go gen.generated.go \
|
||||
*safe.generated.go *_generated_test.go *.generated_ffjson_expose.go
|
||||
|
||||
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.
|
||||
|
||||
package codec
|
||||
|
||||
// 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
|
||||
|
||||
# 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) {}
|
||||
|
||||
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="notfastpath 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.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
|
||||
|
||||
${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
|
||||
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,!notfastpath generated,!notfastpath' -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"
|
||||
local zpkg="github.com/ugorji/go/codec"
|
||||
local returncode=1
|
||||
|
||||
# zpkg=${d##*/src/}
|
||||
# zgobase=${d%%/src/*}
|
||||
# rm -f *_generated_test.go
|
||||
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
|
||||
return $returncode
|
||||
# unset zfin zfin2 zpkg
|
||||
}
|
||||
|
||||
_make() {
|
||||
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
|
||||
}
|
||||
|
||||
_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
|
||||
|
||||
# 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
|
||||
zforce=${makeforce}
|
||||
echo "++++++++ RELEASE TEST SUITES ALL PASSED ++++++++"
|
||||
}
|
||||
|
||||
_usage() {
|
||||
# hidden args:
|
||||
# -pf [p=prebuild (f=force)]
|
||||
|
||||
cat <<EOF
|
||||
primary usage: $0
|
||||
-[tesow m n l d] -> [t=tests (e=extra, s=short, o=cover, w=wait), m=make, n=inlining diagnostics, l=mid-stack inlining, d=race detector]
|
||||
-v -> v=verbose
|
||||
EOF
|
||||
if [[ "$(type -t _usage_run)" = "function" ]]; then _usage_run ; fi
|
||||
}
|
||||
|
||||
_main() {
|
||||
if [[ -z "$1" ]]; then _usage; return 1; fi
|
||||
local x # determines the main action to run in this build
|
||||
local zforce # force
|
||||
local zcover # generate cover profile and show in browser when done
|
||||
local zwait # run tests in sequence, not parallel ie wait for one to finish before starting another
|
||||
local zextra # means run extra (python based tests, etc) during testing
|
||||
|
||||
local ztestargs=()
|
||||
local zargs=()
|
||||
local zverbose=()
|
||||
local zbenchflags=""
|
||||
|
||||
local gocmd=${MYGOCMD:-go}
|
||||
|
||||
OPTIND=1
|
||||
while getopts ":cetmnrgpfvlyzdsowxb:" flag
|
||||
do
|
||||
case "x$flag" in
|
||||
'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") ;;
|
||||
'xb') x='b'; zbenchflags=${OPTARG} ;;
|
||||
x\?) _usage; return 1 ;;
|
||||
*) x=$flag ;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND-1))
|
||||
# echo ">>>> _main: extra args: $@"
|
||||
case "x$x" in
|
||||
'xt') _tests "$@" ;;
|
||||
'xm') _make "$@" ;;
|
||||
'xr') _release "$@" ;;
|
||||
'xg') _go ;;
|
||||
'xp') _prebuild "$@" ;;
|
||||
'xc') _clean "$@" ;;
|
||||
'xx') _analyze_checks "$@" ;;
|
||||
'xy') _analyze_debug_types "$@" ;;
|
||||
'xz') _analyze_do_inlining_and_more "$@" ;;
|
||||
'xb') _bench "$@" ;;
|
||||
esac
|
||||
# unset zforce zargs zbenchflags
|
||||
}
|
||||
|
||||
[ "." = `dirname $0` ] && _main "$@"
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,13 @@
|
|||
// +build codecgen generated
|
||||
|
||||
package codec
|
||||
|
||||
// this file sets the codecgen variable to true
|
||||
// when the build tag codecgen is set.
|
||||
//
|
||||
// some tests depend on knowing whether in the context of codecgen or not.
|
||||
// For example, some tests should be skipped during codecgen e.g. missing fields tests.
|
||||
|
||||
func init() {
|
||||
codecgen = true
|
||||
}
|
|
@ -0,0 +1,454 @@
|
|||
// 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 (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Per go spec, floats are represented in memory as
|
||||
// IEEE single or double precision floating point values.
|
||||
//
|
||||
// We also looked at the source for stdlib math/modf.go,
|
||||
// reviewed https://github.com/chewxy/math32
|
||||
// and read wikipedia documents describing the formats.
|
||||
//
|
||||
// It became clear that we could easily look at the bits to determine
|
||||
// whether any fraction exists.
|
||||
|
||||
func parseFloat32(b []byte) (f float32, err error) {
|
||||
return parseFloat32_custom(b)
|
||||
}
|
||||
|
||||
func parseFloat64(b []byte) (f float64, err error) {
|
||||
return parseFloat64_custom(b)
|
||||
}
|
||||
|
||||
func parseFloat32_strconv(b []byte) (f float32, err error) {
|
||||
f64, err := strconv.ParseFloat(stringView(b), 32)
|
||||
f = float32(f64)
|
||||
return
|
||||
}
|
||||
|
||||
func parseFloat64_strconv(b []byte) (f float64, err error) {
|
||||
return strconv.ParseFloat(stringView(b), 64)
|
||||
}
|
||||
|
||||
// ------ parseFloat custom below --------
|
||||
|
||||
// JSON really supports decimal numbers in base 10 notation, with exponent support.
|
||||
//
|
||||
// We assume the following:
|
||||
// - a lot of floating point numbers in json files will have defined precision
|
||||
// (in terms of number of digits after decimal point), etc.
|
||||
// - these (referenced above) can be written in exact format.
|
||||
//
|
||||
// strconv.ParseFloat has some unnecessary overhead which we can do without
|
||||
// for the common case:
|
||||
//
|
||||
// - expensive char-by-char check to see if underscores are in right place
|
||||
// - testing for and skipping underscores
|
||||
// - check if the string matches ignorecase +/- inf, +/- infinity, nan
|
||||
// - support for base 16 (0xFFFF...)
|
||||
//
|
||||
// The functions below will try a fast-path for floats which can be decoded
|
||||
// without any loss of precision, meaning they:
|
||||
//
|
||||
// - fits within the significand bits of the 32-bits or 64-bits
|
||||
// - exponent fits within the exponent value
|
||||
// - there is no truncation (any extra numbers are all trailing zeros)
|
||||
//
|
||||
// To figure out what the values are for maxMantDigits, use this idea below:
|
||||
//
|
||||
// 2^23 = 838 8608 (between 10^ 6 and 10^ 7) (significand bits of uint32)
|
||||
// 2^32 = 42 9496 7296 (between 10^ 9 and 10^10) (full uint32)
|
||||
// 2^52 = 4503 5996 2737 0496 (between 10^15 and 10^16) (significand bits of uint64)
|
||||
// 2^64 = 1844 6744 0737 0955 1616 (between 10^19 and 10^20) (full uint64)
|
||||
//
|
||||
// Note: we only allow for up to what can comfortably fit into the significand
|
||||
// ignoring the exponent, and we only try to parse iff significand fits.
|
||||
|
||||
const (
|
||||
fMaxMultiplierForExactPow10_64 = 1e15
|
||||
fMaxMultiplierForExactPow10_32 = 1e7
|
||||
|
||||
fUint64Cutoff = (1<<64-1)/10 + 1
|
||||
// fUint32Cutoff = (1<<32-1)/10 + 1
|
||||
|
||||
fBase = 10
|
||||
)
|
||||
|
||||
const (
|
||||
thousand = 1000
|
||||
million = thousand * thousand
|
||||
billion = thousand * million
|
||||
trillion = thousand * billion
|
||||
quadrillion = thousand * trillion
|
||||
quintillion = thousand * quadrillion
|
||||
)
|
||||
|
||||
// Exact powers of 10.
|
||||
var uint64pow10 = [...]uint64{
|
||||
1, 10, 100,
|
||||
1 * thousand, 10 * thousand, 100 * thousand,
|
||||
1 * million, 10 * million, 100 * million,
|
||||
1 * billion, 10 * billion, 100 * billion,
|
||||
1 * trillion, 10 * trillion, 100 * trillion,
|
||||
1 * quadrillion, 10 * quadrillion, 100 * quadrillion,
|
||||
1 * quintillion, 10 * quintillion,
|
||||
}
|
||||
var float64pow10 = [...]float64{
|
||||
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
|
||||
1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
|
||||
1e20, 1e21, 1e22,
|
||||
}
|
||||
var float32pow10 = [...]float32{
|
||||
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10,
|
||||
}
|
||||
|
||||
type floatinfo struct {
|
||||
mantbits uint8
|
||||
|
||||
// expbits uint8 // (unused)
|
||||
// bias int16 // (unused)
|
||||
|
||||
is32bit bool
|
||||
exactPow10 int8 // Exact powers of ten are <= 10^N (32: 10, 64: 22)
|
||||
|
||||
exactInts int8 // Exact integers are <= 10^N (for non-float, set to 0)
|
||||
|
||||
// maxMantDigits int8 // 10^19 fits in uint64, while 10^9 fits in uint32
|
||||
|
||||
mantCutoffIsUint64Cutoff bool
|
||||
|
||||
mantCutoff uint64
|
||||
}
|
||||
|
||||
var fi32 = floatinfo{23, true, 10, 7, false, 1<<23 - 1}
|
||||
var fi64 = floatinfo{52, false, 22, 15, false, 1<<52 - 1}
|
||||
|
||||
var fi64u = floatinfo{0, false, 19, 0, true, fUint64Cutoff}
|
||||
var fi64i = floatinfo{0, false, 19, 0, true, fUint64Cutoff}
|
||||
|
||||
func strconvParseErr(b []byte, fn string) error {
|
||||
return &strconv.NumError{
|
||||
Func: fn,
|
||||
Err: strconv.ErrSyntax,
|
||||
Num: string(b),
|
||||
}
|
||||
}
|
||||
|
||||
func parseFloat32_reader(r readFloatResult) (f float32, fail bool) {
|
||||
f = float32(r.mantissa)
|
||||
if r.exp == 0 {
|
||||
} else if r.exp < 0 { // int / 10^k
|
||||
f /= float32pow10[uint8(-r.exp)]
|
||||
} else { // exp > 0
|
||||
if r.exp > fi32.exactPow10 {
|
||||
f *= float32pow10[r.exp-fi32.exactPow10]
|
||||
if f > fMaxMultiplierForExactPow10_32 { // exponent too large - outside range
|
||||
fail = true
|
||||
return // ok = false
|
||||
}
|
||||
f *= float32pow10[fi32.exactPow10]
|
||||
} else {
|
||||
f *= float32pow10[uint8(r.exp)]
|
||||
}
|
||||
}
|
||||
if r.neg {
|
||||
f = -f
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func parseFloat32_custom(b []byte) (f float32, err error) {
|
||||
r := readFloat(b, fi32)
|
||||
if r.bad {
|
||||
return 0, strconvParseErr(b, "ParseFloat")
|
||||
}
|
||||
if r.ok {
|
||||
f, r.bad = parseFloat32_reader(r)
|
||||
if !r.bad {
|
||||
return
|
||||
}
|
||||
}
|
||||
return parseFloat32_strconv(b)
|
||||
}
|
||||
|
||||
func parseFloat64_reader(r readFloatResult) (f float64, fail bool) {
|
||||
f = float64(r.mantissa)
|
||||
if r.exp == 0 {
|
||||
} else if r.exp < 0 { // int / 10^k
|
||||
f /= float64pow10[-uint8(r.exp)]
|
||||
} else { // exp > 0
|
||||
if r.exp > fi64.exactPow10 {
|
||||
f *= float64pow10[r.exp-fi64.exactPow10]
|
||||
if f > fMaxMultiplierForExactPow10_64 { // exponent too large - outside range
|
||||
fail = true
|
||||
return
|
||||
}
|
||||
f *= float64pow10[fi64.exactPow10]
|
||||
} else {
|
||||
f *= float64pow10[uint8(r.exp)]
|
||||
}
|
||||
}
|
||||
if r.neg {
|
||||
f = -f
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func parseFloat64_custom(b []byte) (f float64, err error) {
|
||||
r := readFloat(b, fi64)
|
||||
if r.bad {
|
||||
return 0, strconvParseErr(b, "ParseFloat")
|
||||
}
|
||||
if r.ok {
|
||||
f, r.bad = parseFloat64_reader(r)
|
||||
if !r.bad {
|
||||
return
|
||||
}
|
||||
}
|
||||
return parseFloat64_strconv(b)
|
||||
}
|
||||
|
||||
func parseUint64_simple(b []byte) (n uint64, ok bool) {
|
||||
var i int
|
||||
var n1 uint64
|
||||
var c uint8
|
||||
LOOP:
|
||||
if i < len(b) {
|
||||
c = b[i]
|
||||
// unsigned integers don't overflow well on multiplication, so check cutoff here
|
||||
// e.g. (maxUint64-5)*10 doesn't overflow well ...
|
||||
// if n >= fUint64Cutoff || !isDigitChar(b[i]) { // if c < '0' || c > '9' {
|
||||
if n >= fUint64Cutoff || c < '0' || c > '9' {
|
||||
return
|
||||
} else if c == '0' {
|
||||
n *= fBase
|
||||
} else {
|
||||
n1 = n
|
||||
n = n*fBase + uint64(c-'0')
|
||||
if n < n1 {
|
||||
return
|
||||
}
|
||||
}
|
||||
i++
|
||||
goto LOOP
|
||||
}
|
||||
ok = true
|
||||
return
|
||||
}
|
||||
|
||||
func parseUint64_reader(r readFloatResult) (f uint64, fail bool) {
|
||||
f = r.mantissa
|
||||
if r.exp == 0 {
|
||||
} else if r.exp < 0 { // int / 10^k
|
||||
if f%uint64pow10[uint8(-r.exp)] != 0 {
|
||||
fail = true
|
||||
} else {
|
||||
f /= uint64pow10[uint8(-r.exp)]
|
||||
}
|
||||
} else { // exp > 0
|
||||
f *= uint64pow10[uint8(r.exp)]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func parseInt64_reader(r readFloatResult) (v int64, fail bool) {
|
||||
if r.exp == 0 {
|
||||
} else if r.exp < 0 { // int / 10^k
|
||||
if r.mantissa%uint64pow10[uint8(-r.exp)] != 0 {
|
||||
// fail = true
|
||||
return 0, true
|
||||
}
|
||||
r.mantissa /= uint64pow10[uint8(-r.exp)]
|
||||
} else { // exp > 0
|
||||
r.mantissa *= uint64pow10[uint8(r.exp)]
|
||||
}
|
||||
if chkOvf.Uint2Int(r.mantissa, r.neg) {
|
||||
fail = true
|
||||
} else if r.neg {
|
||||
v = -int64(r.mantissa)
|
||||
} else {
|
||||
v = int64(r.mantissa)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// parseNumber will return an integer if only composed of [-]?[0-9]+
|
||||
// Else it will return a float.
|
||||
func parseNumber(b []byte, z *fauxUnion, preferSignedInt bool) (err error) {
|
||||
var ok, neg bool
|
||||
var f uint64
|
||||
|
||||
if len(b) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if b[0] == '-' {
|
||||
neg = true
|
||||
f, ok = parseUint64_simple(b[1:])
|
||||
} else {
|
||||
f, ok = parseUint64_simple(b)
|
||||
}
|
||||
|
||||
if ok {
|
||||
if neg {
|
||||
z.v = valueTypeInt
|
||||
if chkOvf.Uint2Int(f, neg) {
|
||||
return strconvParseErr(b, "ParseInt")
|
||||
}
|
||||
z.i = -int64(f)
|
||||
} else if preferSignedInt {
|
||||
z.v = valueTypeInt
|
||||
if chkOvf.Uint2Int(f, neg) {
|
||||
return strconvParseErr(b, "ParseInt")
|
||||
}
|
||||
z.i = int64(f)
|
||||
} else {
|
||||
z.v = valueTypeUint
|
||||
z.u = f
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
z.v = valueTypeFloat
|
||||
z.f, err = parseFloat64_custom(b)
|
||||
return
|
||||
}
|
||||
|
||||
type readFloatResult struct {
|
||||
mantissa uint64
|
||||
exp int8
|
||||
neg, sawdot, sawexp, trunc, bad bool
|
||||
ok bool
|
||||
_ byte // padding
|
||||
}
|
||||
|
||||
func readFloat(s []byte, y floatinfo) (r readFloatResult) {
|
||||
var i uint // uint, so that we eliminate bounds checking
|
||||
var slen = uint(len(s))
|
||||
if slen == 0 {
|
||||
// read an empty string as the zero value
|
||||
// r.bad = true
|
||||
r.ok = true
|
||||
return
|
||||
}
|
||||
|
||||
if s[0] == '-' {
|
||||
r.neg = true
|
||||
i++
|
||||
}
|
||||
|
||||
// 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 xu uint64
|
||||
|
||||
LOOP:
|
||||
for ; i < slen; i++ {
|
||||
switch s[i] {
|
||||
case '.':
|
||||
if r.sawdot {
|
||||
r.bad = true
|
||||
return
|
||||
}
|
||||
r.sawdot = true
|
||||
dp = nd
|
||||
case 'e', 'E':
|
||||
r.sawexp = true
|
||||
break LOOP
|
||||
case '0':
|
||||
if nd == 0 {
|
||||
dp--
|
||||
continue LOOP
|
||||
}
|
||||
nd++
|
||||
if r.mantissa < y.mantCutoff {
|
||||
r.mantissa *= fBase
|
||||
ndMant++
|
||||
}
|
||||
case '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
nd++
|
||||
if y.mantCutoffIsUint64Cutoff && r.mantissa < fUint64Cutoff {
|
||||
r.mantissa *= fBase
|
||||
xu = r.mantissa + uint64(s[i]-'0')
|
||||
if xu < r.mantissa {
|
||||
r.trunc = true
|
||||
return
|
||||
}
|
||||
r.mantissa = xu
|
||||
} else if r.mantissa < y.mantCutoff {
|
||||
// mantissa = (mantissa << 1) + (mantissa << 3) + uint64(c-'0')
|
||||
r.mantissa = r.mantissa*fBase + uint64(s[i]-'0')
|
||||
} else {
|
||||
r.trunc = true
|
||||
return
|
||||
}
|
||||
ndMant++
|
||||
default:
|
||||
r.bad = true
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if !r.sawdot {
|
||||
dp = nd
|
||||
}
|
||||
|
||||
if r.sawexp {
|
||||
i++
|
||||
if i < slen {
|
||||
var eneg bool
|
||||
if s[i] == '+' {
|
||||
i++
|
||||
} else if s[i] == '-' {
|
||||
i++
|
||||
eneg = true
|
||||
}
|
||||
if i < slen {
|
||||
// for exact match, exponent is 1 or 2 digits (float64: -22 to 37, float32: -1 to 17).
|
||||
// exit quick if exponent is more than 2 digits.
|
||||
if i+2 < slen {
|
||||
return
|
||||
}
|
||||
var e int8
|
||||
if s[i] < '0' || s[i] > '9' { // !isDigitChar(s[i]) { //
|
||||
r.bad = true
|
||||
return
|
||||
}
|
||||
e = int8(s[i] - '0')
|
||||
i++
|
||||
if i < slen {
|
||||
if s[i] < '0' || s[i] > '9' { // !isDigitChar(s[i]) { //
|
||||
r.bad = true
|
||||
return
|
||||
}
|
||||
e = e*fBase + int8(s[i]-'0') // (e << 1) + (e << 3) + int8(s[i]-'0')
|
||||
i++
|
||||
}
|
||||
if eneg {
|
||||
dp -= e
|
||||
} else {
|
||||
dp += e
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if r.mantissa != 0 {
|
||||
r.exp = dp - ndMant
|
||||
// do not set ok=true for cases we cannot handle
|
||||
if r.exp < -y.exactPow10 ||
|
||||
r.exp > y.exactInts+y.exactPow10 ||
|
||||
(y.mantbits != 0 && r.mantissa>>y.mantbits != 0) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
r.ok = true
|
||||
return
|
||||
}
|
File diff suppressed because it is too large
Load Diff
139
vendor/github.com/ugorji/go/codec/0doc.go → vendor/github.com/ugorji/go/codec/doc.go
generated
vendored
139
vendor/github.com/ugorji/go/codec/0doc.go → vendor/github.com/ugorji/go/codec/doc.go
generated
vendored
|
@ -1,9 +1,10 @@
|
|||
// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
|
||||
// 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.
|
||||
|
||||
/*
|
||||
High Performance, Feature-Rich Idiomatic Go codec/encoding library for
|
||||
binc, msgpack, cbor, json.
|
||||
Package codec provides a
|
||||
High Performance, Feature-Rich Idiomatic Go 1.4+ codec/encoding library
|
||||
for binc, msgpack, cbor, json.
|
||||
|
||||
Supported Serialization formats are:
|
||||
|
||||
|
@ -13,19 +14,11 @@ Supported Serialization formats are:
|
|||
- json: http://json.org http://tools.ietf.org/html/rfc7159
|
||||
- simple:
|
||||
|
||||
To install:
|
||||
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
|
||||
i.e. 'go install -tags=safe ...'.
|
||||
|
||||
go get github.com/ugorji/go/codec
|
||||
|
||||
This package understands the 'unsafe' tag, to allow using unsafe semantics:
|
||||
|
||||
- When decoding into a struct, you need to read the field name as a string
|
||||
so you can find the struct field it is mapped to.
|
||||
Using `unsafe` will bypass the allocation and copying overhead of []byte->string conversion.
|
||||
|
||||
To install using unsafe, pass the 'unsafe' tag:
|
||||
|
||||
go get -tags=unsafe github.com/ugorji/go/codec
|
||||
This library works with both the standard `gc` and the `gccgo` compilers.
|
||||
|
||||
For detailed usage information, read the primer at http://ugorji.net/blog/go-codec-primer .
|
||||
|
||||
|
@ -35,11 +28,16 @@ the standard library (ie json, xml, gob, etc).
|
|||
Rich Feature Set includes:
|
||||
|
||||
- Simple but extremely powerful and feature-rich API
|
||||
- Support for go 1.4 and above, while selectively using newer APIs for later releases
|
||||
- Excellent code coverage ( > 90% )
|
||||
- Very High Performance.
|
||||
Our extensive benchmarks show us outperforming Gob, Json, Bson, etc by 2-4X.
|
||||
- Multiple conversions:
|
||||
Package coerces types where appropriate
|
||||
e.g. decode an int in the stream into a float, etc.
|
||||
- Careful selected use of 'unsafe' for targeted performance gains.
|
||||
- 100% safe mode supported, where 'unsafe' is not used at all.
|
||||
- Lock-free (sans mutex) concurrency for scaling to 100's of cores
|
||||
- In-place updates during decode, with option to zero value in maps and slices prior to decode
|
||||
- Coerce types where appropriate
|
||||
e.g. decode an int in the stream into a float, decode numbers from formatted strings, etc
|
||||
- Corner Cases:
|
||||
Overflows, nil maps/slices, nil values in streams are handled correctly
|
||||
- Standard field renaming via tags
|
||||
|
@ -48,13 +46,19 @@ Rich Feature Set includes:
|
|||
(struct, slice, map, primitives, pointers, interface{}, etc)
|
||||
- Extensions to support efficient encoding/decoding of any named types
|
||||
- Support encoding.(Binary|Text)(M|Unm)arshaler interfaces
|
||||
- Support using existence of `IsZero() bool` to determine if a value is a zero value.
|
||||
Analogous to time.Time.IsZero() bool.
|
||||
- Decoding without a schema (into a interface{}).
|
||||
Includes Options to configure what specific map or slice type to use
|
||||
when decoding an encoded list or map into a nil interface{}
|
||||
- Mapping a non-interface type to an interface, so we can decode appropriately
|
||||
into any interface type with a correctly configured non-interface value.
|
||||
- Encode a struct as an array, and decode struct from an array in the data stream
|
||||
- Option to encode struct keys as numbers (instead of strings)
|
||||
(to support structured streams with fields encoded as numeric codes)
|
||||
- Comprehensive support for anonymous fields
|
||||
- Fast (no-reflection) encoding/decoding of common maps and slices
|
||||
- Code-generation for faster performance.
|
||||
- Code-generation for faster performance, supported in go 1.6+
|
||||
- Support binary (e.g. messagepack, cbor) and text (e.g. json) formats
|
||||
- Support indefinite-length formats to enable true streaming
|
||||
(for formats which support it e.g. json, cbor)
|
||||
|
@ -68,7 +72,7 @@ Rich Feature Set includes:
|
|||
- Encode/Decode from/to chan types (for iterative streaming support)
|
||||
- Drop-in replacement for encoding/json. `json:` key in struct tag supported.
|
||||
- Provides a RPC Server and Client Codec for net/rpc communication protocol.
|
||||
- Handle unique idiosynchracies of codecs e.g.
|
||||
- Handle unique idiosyncrasies of codecs e.g.
|
||||
- For messagepack, configure how ambiguities in handling raw bytes are resolved
|
||||
- For messagepack, provide rpc server/client codec to support
|
||||
msgpack-rpc protocol defined at:
|
||||
|
@ -92,6 +96,30 @@ encoded as an empty map because it has no exported fields, while UUID
|
|||
would be encoded as a string. However, with extension support, you can
|
||||
encode any of these however you like.
|
||||
|
||||
There is also seamless support provided for registering an extension (with a tag)
|
||||
but letting the encoding mechanism default to the standard way.
|
||||
|
||||
Custom Encoding and Decoding
|
||||
|
||||
This package maintains symmetry in the encoding and decoding halfs.
|
||||
We determine how to encode or decode by walking this decision tree
|
||||
|
||||
- is there an extension registered for the type?
|
||||
- is type a codec.Selfer?
|
||||
- is format binary, and is type a encoding.BinaryMarshaler and BinaryUnmarshaler?
|
||||
- is format specifically json, and is type a encoding/json.Marshaler and Unmarshaler?
|
||||
- is format text-based, and type an encoding.TextMarshaler and TextUnmarshaler?
|
||||
- else we use a pair of functions based on the "kind" of the type e.g. map, slice, int64, etc
|
||||
|
||||
This symmetry is important to reduce chances of issues happening because the
|
||||
encoding and decoding sides are out of sync e.g. decoded via very specific
|
||||
encoding.TextUnmarshaler but encoded via kind-specific generalized mode.
|
||||
|
||||
Consequently, if a type only defines one-half of the symmetry
|
||||
(e.g. it implements UnmarshalJSON() but not MarshalJSON() ),
|
||||
then that type doesn't satisfy the check and we will continue walking down the
|
||||
decision tree.
|
||||
|
||||
RPC
|
||||
|
||||
RPC Client and Server Codecs are implemented, so the codecs can be used
|
||||
|
@ -160,40 +188,41 @@ Sample usage model:
|
|||
//OR rpcCodec := codec.MsgpackSpecRpc.ClientCodec(conn, h)
|
||||
client := rpc.NewClientWithCodec(rpcCodec)
|
||||
|
||||
Running Tests
|
||||
|
||||
To run tests, use the following:
|
||||
|
||||
go test
|
||||
|
||||
To run the full suite of tests, use the following:
|
||||
|
||||
go test -tags alltests -run Suite
|
||||
|
||||
You can run the tag 'safe' to run tests or build in safe mode. e.g.
|
||||
|
||||
go test -tags safe -run Json
|
||||
go test -tags "alltests safe" -run Suite
|
||||
|
||||
Running Benchmarks
|
||||
|
||||
cd bench
|
||||
go test -bench . -benchmem -benchtime 1s
|
||||
|
||||
Please see http://github.com/ugorji/go-codec-bench .
|
||||
|
||||
Caveats
|
||||
|
||||
Struct fields matching the following are ignored during encoding and decoding
|
||||
- struct tag value set to -
|
||||
- func, complex numbers, unsafe pointers
|
||||
- unexported and not embedded
|
||||
- unexported and embedded and not struct kind
|
||||
- unexported and embedded pointers (from go1.10)
|
||||
|
||||
Every other field in a struct will be encoded/decoded.
|
||||
|
||||
Embedded fields are encoded as if they exist in the top-level struct,
|
||||
with some caveats. See Encode documentation.
|
||||
|
||||
*/
|
||||
package codec
|
||||
|
||||
// Benefits of go-codec:
|
||||
//
|
||||
// - encoding/json always reads whole file into memory first.
|
||||
// This makes it unsuitable for parsing very large files.
|
||||
// - encoding/xml cannot parse into a map[string]interface{}
|
||||
// I found this out on reading https://github.com/clbanning/mxj
|
||||
|
||||
// TODO:
|
||||
//
|
||||
// - optimization for codecgen:
|
||||
// if len of entity is <= 3 words, then support a value receiver for encode.
|
||||
// - (En|De)coder should store an error when it occurs.
|
||||
// Until reset, subsequent calls return that error that was stored.
|
||||
// This means that free panics must go away.
|
||||
// All errors must be raised through errorf method.
|
||||
// - Decoding using a chan is good, but incurs concurrency costs.
|
||||
// This is because there's no fast way to use a channel without it
|
||||
// having to switch goroutines constantly.
|
||||
// Callback pattern is still the best. Maybe cnsider supporting something like:
|
||||
// type X struct {
|
||||
// Name string
|
||||
// Ys []Y
|
||||
// Ys chan <- Y
|
||||
// Ys func(Y) -> call this function for each entry
|
||||
// }
|
||||
// - Consider adding a isZeroer interface { isZero() bool }
|
||||
// It is used within isEmpty, for omitEmpty support.
|
||||
// - Consider making Handle used AS-IS within the encoding/decoding session.
|
||||
// This means that we don't cache Handle information within the (En|De)coder,
|
||||
// except we really need it at Reset(...)
|
||||
// - Consider adding math/big support
|
||||
// - Consider reducing the size of the generated functions:
|
||||
// Maybe use one loop, and put the conditionals in the loop.
|
||||
// for ... { if cLen > 0 { if j == cLen { break } } else if dd.CheckBreak() { break } }
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,540 +1,554 @@
|
|||
// +build !notfastpath
|
||||
|
||||
// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
|
||||
// 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.
|
||||
|
||||
// ************************************************************
|
||||
// DO NOT EDIT.
|
||||
// THIS FILE IS AUTO-GENERATED from fast-path.go.tmpl
|
||||
// ************************************************************
|
||||
// Code generated from fast-path.go.tmpl - DO NOT EDIT.
|
||||
|
||||
package codec
|
||||
|
||||
// Fast path functions try to create a fast path encode or decode implementation
|
||||
// for common maps and slices.
|
||||
//
|
||||
// We define the functions and register then in this single file
|
||||
// We define the functions and register them in this single file
|
||||
// so as not to pollute the encode.go and decode.go, and create a dependency in there.
|
||||
// This file can be omitted without causing a build failure.
|
||||
//
|
||||
// The advantage of fast paths is:
|
||||
// - Many calls bypass reflection altogether
|
||||
// - Many calls bypass reflection altogether
|
||||
//
|
||||
// Currently support
|
||||
// - slice of all builtin types,
|
||||
// - map of all builtin types to string or interface value
|
||||
// - symetrical maps of all builtin types (e.g. str-str, uint8-uint8)
|
||||
// - slice of all builtin types (numeric, bool, string, []byte)
|
||||
// - maps of builtin types to builtin or interface{} type, EXCEPT FOR
|
||||
// keys of type uintptr, int8/16/32, uint16/32, float32/64, bool, interface{}
|
||||
// AND values of type type int8/16/32, uint16/32
|
||||
// This should provide adequate "typical" implementations.
|
||||
//
|
||||
// Note that fast track decode functions must handle values for which an address cannot be obtained.
|
||||
// For example:
|
||||
// m2 := map[string]int{}
|
||||
// p2 := []interface{}{m2}
|
||||
// // decoding into p2 will bomb if fast track functions do not treat like unaddressable.
|
||||
// m2 := map[string]int{}
|
||||
// p2 := []interface{}{m2}
|
||||
// // decoding into p2 will bomb if fast track functions do not treat like unaddressable.
|
||||
//
|
||||
|
||||
{{/*
|
||||
fastpathEncMapStringUint64R (called by fastpath...switch)
|
||||
EncMapStringUint64V (called by codecgen)
|
||||
|
||||
fastpathEncSliceBoolR: (called by fastpath...switch) (checks f.ti.mbs and calls one of them below)
|
||||
EncSliceBoolV (also called by codecgen)
|
||||
EncAsMapSliceBoolV (delegate when mapbyslice=true)
|
||||
|
||||
fastpathDecSliceIntfR (called by fastpath...switch) (calls Y or N below depending on if it can be updated)
|
||||
DecSliceIntfX (called by codecgen) (calls Y below)
|
||||
DecSliceIntfY (delegate when slice CAN be updated)
|
||||
DecSliceIntfN (delegate when slice CANNOT be updated e.g. from array or non-addressable slice)
|
||||
|
||||
fastpathDecMap...R (called by fastpath...switch) (calls L or X? below)
|
||||
DecMap...X (called by codecgen)
|
||||
DecMap...L (delegated to by both above)
|
||||
*/ -}}
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
)
|
||||
|
||||
const fastpathCheckNilFalse = false // for reflect
|
||||
const fastpathCheckNilTrue = true // for type switch
|
||||
const fastpathEnabled = true
|
||||
|
||||
{{/*
|
||||
const fastpathMapBySliceErrMsg = "mapBySlice requires even slice length, but got %v"
|
||||
*/ -}}
|
||||
|
||||
type fastpathT struct {}
|
||||
|
||||
var fastpathTV fastpathT
|
||||
|
||||
type fastpathE struct {
|
||||
rtid uintptr
|
||||
{{/* rtid uintptr */ -}}
|
||||
rt reflect.Type
|
||||
encfn func(*encFnInfo, reflect.Value)
|
||||
decfn func(*decFnInfo, reflect.Value)
|
||||
encfn func(*Encoder, *codecFnInfo, reflect.Value)
|
||||
decfn func(*Decoder, *codecFnInfo, reflect.Value)
|
||||
}
|
||||
|
||||
type fastpathA [{{ .FastpathLen }}]fastpathE
|
||||
type fastpathARtid [{{ .FastpathLen }}]uintptr
|
||||
|
||||
func (x *fastpathA) index(rtid uintptr) int {
|
||||
var fastpathAv fastpathA
|
||||
var fastpathAvRtid fastpathARtid
|
||||
|
||||
type fastpathAslice struct{}
|
||||
|
||||
func (fastpathAslice) Len() int { return {{ .FastpathLen }} }
|
||||
func (fastpathAslice) Less(i, j int) bool {
|
||||
return fastpathAvRtid[uint(i)] < fastpathAvRtid[uint(j)]
|
||||
}
|
||||
func (fastpathAslice) Swap(i, j int) {
|
||||
fastpathAvRtid[uint(i)], fastpathAvRtid[uint(j)] = fastpathAvRtid[uint(j)], fastpathAvRtid[uint(i)]
|
||||
fastpathAv[uint(i)], fastpathAv[uint(j)] = fastpathAv[uint(j)], fastpathAv[uint(i)]
|
||||
}
|
||||
|
||||
func fastpathAvIndex(rtid uintptr) int {
|
||||
// use binary search to grab the index (adapted from sort/search.go)
|
||||
h, i, j := 0, 0, {{ .FastpathLen }} // len(x)
|
||||
for i < j {
|
||||
h = i + (j-i)/2
|
||||
if x[h].rtid < rtid {
|
||||
// Note: we use goto (instead of for loop) so this can be inlined.
|
||||
// h, i, j := 0, 0, {{ .FastpathLen }}
|
||||
var h, i uint
|
||||
var j uint = {{ .FastpathLen }}
|
||||
LOOP:
|
||||
if i < j {
|
||||
h = (i + j) >> 1 // avoid overflow when computing h // h = i + (j-i)/2
|
||||
if fastpathAvRtid[h] < rtid {
|
||||
i = h + 1
|
||||
} else {
|
||||
j = h
|
||||
}
|
||||
goto LOOP
|
||||
}
|
||||
if i < {{ .FastpathLen }} && x[i].rtid == rtid {
|
||||
return i
|
||||
if i < {{ .FastpathLen }} && fastpathAvRtid[i] == rtid {
|
||||
return int(i)
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
type fastpathAslice []fastpathE
|
||||
|
||||
func (x fastpathAslice) Len() int { return len(x) }
|
||||
func (x fastpathAslice) Less(i, j int) bool { return x[i].rtid < x[j].rtid }
|
||||
func (x fastpathAslice) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||
|
||||
var fastpathAV fastpathA
|
||||
|
||||
// due to possible initialization loop error, make fastpath in an init()
|
||||
func init() {
|
||||
if !fastpathEnabled {
|
||||
return
|
||||
}
|
||||
i := 0
|
||||
fn := func(v interface{}, fe func(*encFnInfo, reflect.Value), fd func(*decFnInfo, reflect.Value)) (f fastpathE) {
|
||||
var i uint = 0
|
||||
fn := func(v interface{},
|
||||
fe func(*Encoder, *codecFnInfo, reflect.Value),
|
||||
fd func(*Decoder, *codecFnInfo, reflect.Value)) {
|
||||
xrt := reflect.TypeOf(v)
|
||||
xptr := reflect.ValueOf(xrt).Pointer()
|
||||
fastpathAV[i] = fastpathE{xptr, xrt, fe, fd}
|
||||
xptr := rt2id(xrt)
|
||||
fastpathAvRtid[i] = xptr
|
||||
fastpathAv[i] = fastpathE{xrt, fe, fd}
|
||||
i++
|
||||
return
|
||||
}
|
||||
{{/* do not register []byte in fast-path */}}
|
||||
{{range .Values}}{{if not .Primitive}}{{if not .MapKey -}}
|
||||
fn([]{{ .Elem }}(nil), (*Encoder).{{ .MethodNamePfx "fastpathEnc" false }}R, (*Decoder).{{ .MethodNamePfx "fastpathDec" false }}R)
|
||||
{{end}}{{end}}{{end}}
|
||||
|
||||
{{range .Values}}{{if not .Primitive}}{{if not .MapKey }}
|
||||
fn([]{{ .Elem }}(nil), (*encFnInfo).{{ .MethodNamePfx "fastpathEnc" false }}R, (*decFnInfo).{{ .MethodNamePfx "fastpathDec" false }}R){{end}}{{end}}{{end}}
|
||||
{{range .Values}}{{if not .Primitive}}{{if .MapKey -}}
|
||||
fn(map[{{ .MapKey }}]{{ .Elem }}(nil), (*Encoder).{{ .MethodNamePfx "fastpathEnc" false }}R, (*Decoder).{{ .MethodNamePfx "fastpathDec" false }}R)
|
||||
{{end}}{{end}}{{end}}
|
||||
|
||||
{{range .Values}}{{if not .Primitive}}{{if .MapKey }}
|
||||
fn(map[{{ .MapKey }}]{{ .Elem }}(nil), (*encFnInfo).{{ .MethodNamePfx "fastpathEnc" false }}R, (*decFnInfo).{{ .MethodNamePfx "fastpathDec" false }}R){{end}}{{end}}{{end}}
|
||||
|
||||
sort.Sort(fastpathAslice(fastpathAV[:]))
|
||||
sort.Sort(fastpathAslice{})
|
||||
}
|
||||
|
||||
// -- encode
|
||||
|
||||
// -- -- fast path type switch
|
||||
func fastpathEncodeTypeSwitch(iv interface{}, e *Encoder) bool {
|
||||
if !fastpathEnabled {
|
||||
return false
|
||||
}
|
||||
switch v := iv.(type) {
|
||||
{{range .Values}}{{if not .Primitive}}{{if not .MapKey }}
|
||||
case []{{ .Elem }}:{{else}}
|
||||
case map[{{ .MapKey }}]{{ .Elem }}:{{end}}
|
||||
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, fastpathCheckNilTrue, e){{if not .MapKey }}
|
||||
case *[]{{ .Elem }}:{{else}}
|
||||
case *map[{{ .MapKey }}]{{ .Elem }}:{{end}}
|
||||
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, fastpathCheckNilTrue, e)
|
||||
{{end}}{{end}}
|
||||
default:
|
||||
_ = v // TODO: workaround https://github.com/golang/go/issues/12927 (remove after go 1.6 release)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func fastpathEncodeTypeSwitchSlice(iv interface{}, e *Encoder) bool {
|
||||
if !fastpathEnabled {
|
||||
return false
|
||||
}
|
||||
switch v := iv.(type) {
|
||||
{{range .Values}}{{if not .Primitive}}{{if not .MapKey }}
|
||||
{{range .Values}}{{if not .Primitive}}{{if not .MapKey -}}
|
||||
case []{{ .Elem }}:
|
||||
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, fastpathCheckNilTrue, e)
|
||||
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, e)
|
||||
case *[]{{ .Elem }}:
|
||||
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, fastpathCheckNilTrue, e)
|
||||
{{end}}{{end}}{{end}}
|
||||
default:
|
||||
_ = v // TODO: workaround https://github.com/golang/go/issues/12927 (remove after go 1.6 release)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if *v == nil {
|
||||
e.e.EncodeNil()
|
||||
} else {
|
||||
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, e)
|
||||
}
|
||||
{{end}}{{end}}{{end -}}
|
||||
|
||||
func fastpathEncodeTypeSwitchMap(iv interface{}, e *Encoder) bool {
|
||||
if !fastpathEnabled {
|
||||
return false
|
||||
}
|
||||
switch v := iv.(type) {
|
||||
{{range .Values}}{{if not .Primitive}}{{if .MapKey }}
|
||||
{{range .Values}}{{if not .Primitive}}{{if .MapKey -}}
|
||||
case map[{{ .MapKey }}]{{ .Elem }}:
|
||||
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, fastpathCheckNilTrue, e)
|
||||
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, e)
|
||||
case *map[{{ .MapKey }}]{{ .Elem }}:
|
||||
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, fastpathCheckNilTrue, e)
|
||||
{{end}}{{end}}{{end}}
|
||||
if *v == nil {
|
||||
e.e.EncodeNil()
|
||||
} else {
|
||||
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, e)
|
||||
}
|
||||
{{end}}{{end}}{{end -}}
|
||||
|
||||
default:
|
||||
_ = v // TODO: workaround https://github.com/golang/go/issues/12927 (remove after go 1.6 release)
|
||||
_ = v // workaround https://github.com/golang/go/issues/12927 seen in go1.4
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// -- -- fast path functions
|
||||
{{range .Values}}{{if not .Primitive}}{{if not .MapKey }}
|
||||
|
||||
func (f *encFnInfo) {{ .MethodNamePfx "fastpathEnc" false }}R(rv reflect.Value) {
|
||||
if f.ti.mbs {
|
||||
fastpathTV.{{ .MethodNamePfx "EncAsMap" false }}V(rv.Interface().([]{{ .Elem }}), fastpathCheckNilFalse, f.e)
|
||||
{{range .Values}}{{if not .Primitive}}{{if not .MapKey -}}
|
||||
func (e *Encoder) {{ .MethodNamePfx "fastpathEnc" false }}R(f *codecFnInfo, rv reflect.Value) {
|
||||
var v []{{ .Elem }}
|
||||
if rv.Kind() == reflect.Array {
|
||||
rvGetSlice4Array(rv, &v)
|
||||
} else {
|
||||
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(rv.Interface().([]{{ .Elem }}), fastpathCheckNilFalse, f.e)
|
||||
v = rv2i(rv).([]{{ .Elem }})
|
||||
}
|
||||
if f.ti.mbs {
|
||||
fastpathTV.{{ .MethodNamePfx "EncAsMap" false }}V(v, e)
|
||||
} else {
|
||||
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, e)
|
||||
}
|
||||
}
|
||||
func (_ fastpathT) {{ .MethodNamePfx "Enc" false }}V(v []{{ .Elem }}, checkNil bool, e *Encoder) {
|
||||
ee := e.e
|
||||
cr := e.cr
|
||||
if checkNil && v == nil {
|
||||
ee.EncodeNil()
|
||||
return
|
||||
func (fastpathT) {{ .MethodNamePfx "Enc" false }}V(v []{{ .Elem }}, e *Encoder) {
|
||||
{{/* if v == nil { e.e.EncodeNil(); return } */ -}}
|
||||
{{ if eq .Elem "uint8" "byte" -}}
|
||||
e.e.EncodeStringBytesRaw(v)
|
||||
{{ else -}}
|
||||
e.arrayStart(len(v))
|
||||
for j := range v {
|
||||
e.arrayElem()
|
||||
{{ encmd .Elem "v[j]"}}
|
||||
}
|
||||
ee.EncodeArrayStart(len(v))
|
||||
for _, v2 := range v {
|
||||
if cr != nil { cr.sendContainerState(containerArrayElem) }
|
||||
{{ encmd .Elem "v2"}}
|
||||
}
|
||||
if cr != nil { cr.sendContainerState(containerArrayEnd) }{{/* ee.EncodeEnd() */}}
|
||||
e.arrayEnd()
|
||||
{{ end -}}
|
||||
}
|
||||
|
||||
func (_ fastpathT) {{ .MethodNamePfx "EncAsMap" false }}V(v []{{ .Elem }}, checkNil bool, e *Encoder) {
|
||||
ee := e.e
|
||||
cr := e.cr
|
||||
if checkNil && v == nil {
|
||||
ee.EncodeNil()
|
||||
return
|
||||
func (fastpathT) {{ .MethodNamePfx "EncAsMap" false }}V(v []{{ .Elem }}, e *Encoder) {
|
||||
{{/* if v == nil { e.e.EncodeNil() } else */ -}}
|
||||
e.haltOnMbsOddLen(len(v))
|
||||
{{/*
|
||||
if len(v)&1 != 0 { // similar to &1==1 or %2 == 1
|
||||
e.errorf(fastpathMapBySliceErrMsg, len(v))
|
||||
}
|
||||
if len(v)%2 == 1 {
|
||||
e.errorf("mapBySlice requires even slice length, but got %v", len(v))
|
||||
return
|
||||
}
|
||||
ee.EncodeMapStart(len(v) / 2)
|
||||
for j, v2 := range v {
|
||||
if cr != nil {
|
||||
if j%2 == 0 {
|
||||
cr.sendContainerState(containerMapKey)
|
||||
} else {
|
||||
cr.sendContainerState(containerMapValue)
|
||||
}
|
||||
*/ -}}
|
||||
e.mapStart(len(v) >> 1) // e.mapStart(len(v) / 2)
|
||||
for j := range v {
|
||||
if j&1 == 0 { // if j%2 == 0 {
|
||||
e.mapElemKey()
|
||||
} else {
|
||||
e.mapElemValue()
|
||||
}
|
||||
{{ encmd .Elem "v2"}}
|
||||
{{ encmd .Elem "v[j]"}}
|
||||
}
|
||||
if cr != nil { cr.sendContainerState(containerMapEnd) }
|
||||
e.mapEnd()
|
||||
}
|
||||
{{end}}{{end}}{{end -}}
|
||||
|
||||
{{end}}{{end}}{{end}}
|
||||
|
||||
{{range .Values}}{{if not .Primitive}}{{if .MapKey }}
|
||||
|
||||
func (f *encFnInfo) {{ .MethodNamePfx "fastpathEnc" false }}R(rv reflect.Value) {
|
||||
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(rv.Interface().(map[{{ .MapKey }}]{{ .Elem }}), fastpathCheckNilFalse, f.e)
|
||||
{{range .Values}}{{if not .Primitive}}{{if .MapKey -}}
|
||||
func (e *Encoder) {{ .MethodNamePfx "fastpathEnc" false }}R(f *codecFnInfo, rv reflect.Value) {
|
||||
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(rv2i(rv).(map[{{ .MapKey }}]{{ .Elem }}), e)
|
||||
}
|
||||
func (_ fastpathT) {{ .MethodNamePfx "Enc" false }}V(v map[{{ .MapKey }}]{{ .Elem }}, checkNil bool, e *Encoder) {
|
||||
ee := e.e
|
||||
cr := e.cr
|
||||
if checkNil && v == nil {
|
||||
ee.EncodeNil()
|
||||
return
|
||||
}
|
||||
ee.EncodeMapStart(len(v))
|
||||
{{if eq .MapKey "string"}}asSymbols := e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0
|
||||
{{end}}if e.h.Canonical {
|
||||
{{if eq .MapKey "interface{}"}}{{/* out of band
|
||||
*/}}var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding
|
||||
func (fastpathT) {{ .MethodNamePfx "Enc" false }}V(v map[{{ .MapKey }}]{{ .Elem }}, e *Encoder) {
|
||||
{{/* if v == nil { e.e.EncodeNil(); return } */ -}}
|
||||
e.mapStart(len(v))
|
||||
if e.h.Canonical { {{/* need to figure out .NoCanonical */}}
|
||||
{{if eq .MapKey "interface{}"}}{{/* out of band */ -}}
|
||||
var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding
|
||||
e2 := NewEncoderBytes(&mksv, e.hh)
|
||||
v2 := make([]bytesI, len(v))
|
||||
var i, l int
|
||||
var vp *bytesI {{/* put loop variables outside. seems currently needed for better perf */}}
|
||||
for k2, _ := range v {
|
||||
l = len(mksv)
|
||||
v2 := make([]bytesIntf, len(v))
|
||||
var i, l uint {{/* put loop variables outside. seems currently needed for better perf */}}
|
||||
var vp *bytesIntf
|
||||
for k2 := range v {
|
||||
l = uint(len(mksv))
|
||||
e2.MustEncode(k2)
|
||||
vp = &v2[i]
|
||||
vp.v = mksv[l:]
|
||||
vp.i = k2
|
||||
i++
|
||||
}
|
||||
sort.Sort(bytesISlice(v2))
|
||||
sort.Sort(bytesIntfSlice(v2))
|
||||
for j := range v2 {
|
||||
if cr != nil { cr.sendContainerState(containerMapKey) }
|
||||
e.mapElemKey()
|
||||
e.asis(v2[j].v)
|
||||
if cr != nil { cr.sendContainerState(containerMapValue) }
|
||||
e.mapElemValue()
|
||||
e.encode(v[v2[j].i])
|
||||
} {{else}}{{ $x := sorttype .MapKey true}}v2 := make([]{{ $x }}, len(v))
|
||||
var i int
|
||||
for k, _ := range v {
|
||||
v2[i] = {{ $x }}(k)
|
||||
var i uint
|
||||
for k := range v {
|
||||
v2[i] = {{if eq $x .MapKey}}k{{else}}{{ $x }}(k){{end}}
|
||||
i++
|
||||
}
|
||||
sort.Sort({{ sorttype .MapKey false}}(v2))
|
||||
for _, k2 := range v2 {
|
||||
if cr != nil { cr.sendContainerState(containerMapKey) }
|
||||
{{if eq .MapKey "string"}}if asSymbols {
|
||||
ee.EncodeSymbol(k2)
|
||||
} else {
|
||||
ee.EncodeString(c_UTF8, k2)
|
||||
}{{else}}{{ $y := printf "%s(k2)" .MapKey }}{{ encmd .MapKey $y }}{{end}}
|
||||
if cr != nil { cr.sendContainerState(containerMapValue) }
|
||||
{{ $y := printf "v[%s(k2)]" .MapKey }}{{ encmd .Elem $y }}
|
||||
e.mapElemKey()
|
||||
{{if eq .MapKey "string"}} e.e.EncodeString(k2) {{else}}{{ $y := printf "%s(k2)" .MapKey }}{{if eq $x .MapKey }}{{ $y = "k2" }}{{end}}{{ encmd .MapKey $y }}{{end}}
|
||||
e.mapElemValue()
|
||||
{{ $y := printf "v[%s(k2)]" .MapKey }}{{if eq $x .MapKey }}{{ $y = "v[k2]" }}{{end}}{{ encmd .Elem $y }}
|
||||
} {{end}}
|
||||
} else {
|
||||
for k2, v2 := range v {
|
||||
if cr != nil { cr.sendContainerState(containerMapKey) }
|
||||
{{if eq .MapKey "string"}}if asSymbols {
|
||||
ee.EncodeSymbol(k2)
|
||||
} else {
|
||||
ee.EncodeString(c_UTF8, k2)
|
||||
}{{else}}{{ encmd .MapKey "k2"}}{{end}}
|
||||
if cr != nil { cr.sendContainerState(containerMapValue) }
|
||||
e.mapElemKey()
|
||||
{{if eq .MapKey "string"}} e.e.EncodeString(k2) {{else}}{{ encmd .MapKey "k2"}}{{end}}
|
||||
e.mapElemValue()
|
||||
{{ encmd .Elem "v2"}}
|
||||
}
|
||||
}
|
||||
if cr != nil { cr.sendContainerState(containerMapEnd) }{{/* ee.EncodeEnd() */}}
|
||||
e.mapEnd()
|
||||
}
|
||||
|
||||
{{end}}{{end}}{{end}}
|
||||
{{end}}{{end}}{{end -}}
|
||||
|
||||
// -- decode
|
||||
|
||||
// -- -- fast path type switch
|
||||
func fastpathDecodeTypeSwitch(iv interface{}, d *Decoder) bool {
|
||||
if !fastpathEnabled {
|
||||
return false
|
||||
}
|
||||
var changed bool
|
||||
var containerLen int
|
||||
switch v := iv.(type) {
|
||||
{{range .Values}}{{if not .Primitive}}{{if not .MapKey }}
|
||||
case []{{ .Elem }}:{{else}}
|
||||
case map[{{ .MapKey }}]{{ .Elem }}:{{end}}
|
||||
fastpathTV.{{ .MethodNamePfx "Dec" false }}V(v, fastpathCheckNilFalse, false, d){{if not .MapKey }}
|
||||
case *[]{{ .Elem }}:{{else}}
|
||||
case *map[{{ .MapKey }}]{{ .Elem }}:{{end}}
|
||||
v2, changed2 := fastpathTV.{{ .MethodNamePfx "Dec" false }}V(*v, fastpathCheckNilFalse, true, d)
|
||||
if changed2 {
|
||||
{{range .Values}}{{if not .Primitive}}{{if not .MapKey -}}
|
||||
case []{{ .Elem }}:
|
||||
fastpathTV.{{ .MethodNamePfx "Dec" false }}N(v, d)
|
||||
case *[]{{ .Elem }}:
|
||||
var v2 []{{ .Elem }}
|
||||
if v2, changed = fastpathTV.{{ .MethodNamePfx "Dec" false }}Y(*v, d); changed {
|
||||
*v = v2
|
||||
}
|
||||
{{end}}{{end}}
|
||||
{{end}}{{end}}{{end -}}
|
||||
{{range .Values}}{{if not .Primitive}}{{if .MapKey }}{{/*
|
||||
// maps only change if nil, and in that case, there's no point copying
|
||||
*/ -}}
|
||||
case map[{{ .MapKey }}]{{ .Elem }}:
|
||||
containerLen = d.mapStart(d.d.ReadMapStart())
|
||||
if containerLen != containerLenNil {
|
||||
if containerLen != 0 {
|
||||
fastpathTV.{{ .MethodNamePfx "Dec" false }}L(v, containerLen, d)
|
||||
}
|
||||
d.mapEnd()
|
||||
}
|
||||
case *map[{{ .MapKey }}]{{ .Elem }}:
|
||||
{{/*
|
||||
containerLen = d.mapStart(d.d.ReadMapStart())
|
||||
if containerLen == 0 {
|
||||
d.mapEnd()
|
||||
} else if containerLen == containerLenNil {
|
||||
*v = nil
|
||||
} else {
|
||||
if *v == nil {
|
||||
*v = make(map[{{ .MapKey }}]{{ .Elem }}, decInferLen(containerLen, d.h.MaxInitLen, {{ .Size }}))
|
||||
}
|
||||
fastpathTV.{{ .MethodNamePfx "Dec" false }}L(*v, containerLen, d)
|
||||
}
|
||||
// consider delegating fully to X - encoding *map is uncommon, so ok to pay small function call cost
|
||||
*/ -}}
|
||||
fastpathTV.{{ .MethodNamePfx "Dec" false }}X(v, d)
|
||||
{{end}}{{end}}{{end -}}
|
||||
default:
|
||||
_ = v // TODO: workaround https://github.com/golang/go/issues/12927 (remove after go 1.6 release)
|
||||
_ = v // workaround https://github.com/golang/go/issues/12927 seen in go1.4
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func fastpathDecodeSetZeroTypeSwitch(iv interface{}) bool {
|
||||
switch v := iv.(type) {
|
||||
{{range .Values}}{{if not .Primitive}}{{if not .MapKey -}}
|
||||
case *[]{{ .Elem }}:
|
||||
*v = nil
|
||||
{{end}}{{end}}{{end}}
|
||||
{{range .Values}}{{if not .Primitive}}{{if .MapKey -}}
|
||||
case *map[{{ .MapKey }}]{{ .Elem }}:
|
||||
*v = nil
|
||||
{{end}}{{end}}{{end}}
|
||||
default:
|
||||
_ = v // workaround https://github.com/golang/go/issues/12927 seen in go1.4
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// -- -- fast path functions
|
||||
{{range .Values}}{{if not .Primitive}}{{if not .MapKey }}
|
||||
{{range .Values}}{{if not .Primitive}}{{if not .MapKey -}}
|
||||
{{/*
|
||||
Slices can change if they
|
||||
- did not come from an array
|
||||
- are addressable (from a ptr)
|
||||
- are settable (e.g. contained in an interface{})
|
||||
*/}}
|
||||
func (f *decFnInfo) {{ .MethodNamePfx "fastpathDec" false }}R(rv reflect.Value) {
|
||||
array := f.seq == seqTypeArray
|
||||
if !array && rv.CanAddr() { {{/* // CanSet => CanAddr + Exported */}}
|
||||
vp := rv.Addr().Interface().(*[]{{ .Elem }})
|
||||
v, changed := fastpathTV.{{ .MethodNamePfx "Dec" false }}V(*vp, fastpathCheckNilFalse, !array, f.d)
|
||||
if changed {
|
||||
func (d *Decoder) {{ .MethodNamePfx "fastpathDec" false }}R(f *codecFnInfo, rv reflect.Value) {
|
||||
{{/*
|
||||
// seqTypeArray=true means that we are not getting a pointer, so no need to check that.
|
||||
if f.seq != seqTypeArray && rv.Kind() == reflect.Ptr {
|
||||
*/ -}}
|
||||
var v []{{ .Elem }}
|
||||
switch rv.Kind() {
|
||||
case reflect.Ptr:
|
||||
vp := rv2i(rv).(*[]{{ .Elem }})
|
||||
var changed bool
|
||||
if v, changed = fastpathTV.{{ .MethodNamePfx "Dec" false }}Y(*vp, d); changed {
|
||||
*vp = v
|
||||
}
|
||||
} else {
|
||||
v := rv.Interface().([]{{ .Elem }})
|
||||
fastpathTV.{{ .MethodNamePfx "Dec" false }}V(v, fastpathCheckNilFalse, false, f.d)
|
||||
case reflect.Array:
|
||||
rvGetSlice4Array(rv, &v)
|
||||
fastpathTV.{{ .MethodNamePfx "Dec" false }}N(v, d)
|
||||
default:
|
||||
fastpathTV.{{ .MethodNamePfx "Dec" false }}N(rv2i(rv).([]{{ .Elem }}), d)
|
||||
}
|
||||
}
|
||||
|
||||
func (f fastpathT) {{ .MethodNamePfx "Dec" false }}X(vp *[]{{ .Elem }}, checkNil bool, d *Decoder) {
|
||||
v, changed := f.{{ .MethodNamePfx "Dec" false }}V(*vp, checkNil, true, d)
|
||||
if changed {
|
||||
*vp = v
|
||||
}
|
||||
func (f fastpathT) {{ .MethodNamePfx "Dec" false }}X(vp *[]{{ .Elem }}, d *Decoder) {
|
||||
if v, changed := f.{{ .MethodNamePfx "Dec" false }}Y(*vp, d); changed { *vp = v }
|
||||
}
|
||||
func (_ fastpathT) {{ .MethodNamePfx "Dec" false }}V(v []{{ .Elem }}, checkNil bool, canChange bool, d *Decoder) (_ []{{ .Elem }}, changed bool) {
|
||||
dd := d.d
|
||||
{{/* // if dd.isContainerType(valueTypeNil) { dd.TryDecodeAsNil() */}}
|
||||
if checkNil && dd.TryDecodeAsNil() {
|
||||
if v != nil {
|
||||
changed = true
|
||||
}
|
||||
return nil, changed
|
||||
func (fastpathT) {{ .MethodNamePfx "Dec" false }}Y(v []{{ .Elem }}, d *Decoder) (v2 []{{ .Elem }}, changed bool) {
|
||||
{{ if eq .Elem "uint8" "byte" -}}
|
||||
switch d.d.ContainerType() {
|
||||
case valueTypeNil, valueTypeMap:
|
||||
break
|
||||
default:
|
||||
v2 = d.decodeBytesInto(v[:len(v):len(v)])
|
||||
changed = !(len(v2) > 0 && len(v2) == len(v) && &v2[0] == &v[0]) // not same slice
|
||||
return
|
||||
}
|
||||
|
||||
{{ end -}}
|
||||
slh, containerLenS := d.decSliceHelperStart()
|
||||
if containerLenS == 0 {
|
||||
if canChange {
|
||||
if v == nil {
|
||||
v = []{{ .Elem }}{}
|
||||
} else if len(v) != 0 {
|
||||
v = v[:0]
|
||||
}
|
||||
changed = true
|
||||
}
|
||||
slh.End()
|
||||
return v, changed
|
||||
if slh.IsNil {
|
||||
if v == nil { return }
|
||||
return nil, true
|
||||
}
|
||||
|
||||
if containerLenS > 0 {
|
||||
x2read := containerLenS
|
||||
var xtrunc bool
|
||||
if containerLenS == 0 {
|
||||
if v == nil { v = []{{ .Elem }}{} } else if len(v) != 0 { v = v[:0] }
|
||||
slh.End()
|
||||
return v, true
|
||||
}
|
||||
hasLen := containerLenS > 0
|
||||
var xlen int
|
||||
if hasLen {
|
||||
if containerLenS > cap(v) {
|
||||
if canChange { {{/*
|
||||
// fast-path is for "basic" immutable types, so no need to copy them over
|
||||
// s := make([]{{ .Elem }}, decInferLen(containerLenS, d.h.MaxInitLen))
|
||||
// copy(s, v[:cap(v)])
|
||||
// v = s */}}
|
||||
var xlen int
|
||||
xlen, xtrunc = decInferLen(containerLenS, d.h.MaxInitLen, {{ .Size }})
|
||||
if xtrunc {
|
||||
if xlen <= cap(v) {
|
||||
v = v[:xlen]
|
||||
} else {
|
||||
v = make([]{{ .Elem }}, xlen)
|
||||
}
|
||||
} else {
|
||||
v = make([]{{ .Elem }}, xlen)
|
||||
}
|
||||
changed = true
|
||||
xlen = decInferLen(containerLenS, d.h.MaxInitLen, {{ .Size }})
|
||||
if xlen <= cap(v) {
|
||||
v = v[:uint(xlen)]
|
||||
} else {
|
||||
d.arrayCannotExpand(len(v), containerLenS)
|
||||
v = make([]{{ .Elem }}, uint(xlen))
|
||||
}
|
||||
x2read = len(v)
|
||||
changed = true
|
||||
} else if containerLenS != len(v) {
|
||||
if canChange {
|
||||
v = v[:containerLenS]
|
||||
changed = true
|
||||
}
|
||||
} {{/* // all checks done. cannot go past len. */}}
|
||||
j := 0
|
||||
for ; j < x2read; j++ {
|
||||
slh.ElemContainerState(j)
|
||||
{{ if eq .Elem "interface{}" }}d.decode(&v[j]){{ else }}v[j] = {{ decmd .Elem }}{{ end }}
|
||||
}
|
||||
if xtrunc { {{/* // means canChange=true, changed=true already. */}}
|
||||
for ; j < containerLenS; j++ {
|
||||
v = append(v, {{ zerocmd .Elem }})
|
||||
slh.ElemContainerState(j)
|
||||
{{ if eq .Elem "interface{}" }}d.decode(&v[j]){{ else }}v[j] = {{ decmd .Elem }}{{ end }}
|
||||
}
|
||||
} else if !canChange {
|
||||
for ; j < containerLenS; j++ {
|
||||
slh.ElemContainerState(j)
|
||||
d.swallow()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
breakFound := dd.CheckBreak() {{/* check break first, so we can initialize v with a capacity of 4 if necessary */}}
|
||||
if breakFound {
|
||||
if canChange {
|
||||
if v == nil {
|
||||
v = []{{ .Elem }}{}
|
||||
} else if len(v) != 0 {
|
||||
v = v[:0]
|
||||
}
|
||||
changed = true
|
||||
}
|
||||
slh.End()
|
||||
return v, changed
|
||||
}
|
||||
if cap(v) == 0 {
|
||||
v = make([]{{ .Elem }}, 1, 4)
|
||||
v = v[:containerLenS]
|
||||
changed = true
|
||||
}
|
||||
j := 0
|
||||
for ; !breakFound; j++ {
|
||||
if j >= len(v) {
|
||||
if canChange {
|
||||
v = append(v, {{ zerocmd .Elem }})
|
||||
changed = true
|
||||
} else {
|
||||
d.arrayCannotExpand(len(v), j+1)
|
||||
}
|
||||
}
|
||||
slh.ElemContainerState(j)
|
||||
if j < len(v) { {{/* // all checks done. cannot go past len. */}}
|
||||
{{ if eq .Elem "interface{}" }}d.decode(&v[j])
|
||||
{{ else }}v[j] = {{ decmd .Elem }}{{ end }}
|
||||
} else {
|
||||
d.swallow()
|
||||
}
|
||||
breakFound = dd.CheckBreak()
|
||||
}
|
||||
if canChange && j < len(v) {
|
||||
v = v[:j]
|
||||
}
|
||||
var j int
|
||||
for j = 0; (hasLen && j < containerLenS) || !(hasLen || d.checkBreak()); j++ {
|
||||
if j == 0 && len(v) == 0 { // means hasLen == false
|
||||
xlen = decInferLen(containerLenS, d.h.MaxInitLen, {{ .Size }}) {{/* xlen = decDefSliceCap */}}
|
||||
v = make([]{{ .Elem }}, uint(xlen))
|
||||
changed = true
|
||||
}
|
||||
{{/* // if indefinite, etc, then expand the slice if necessary */ -}}
|
||||
if j >= len(v) {
|
||||
v = append(v, {{ zerocmd .Elem }})
|
||||
changed = true
|
||||
}
|
||||
slh.ElemContainerState(j)
|
||||
{{ if eq .Elem "interface{}" }}d.decode(&v[uint(j)]){{ else }}v[uint(j)] = {{ decmd .Elem false }}{{ end }}
|
||||
}
|
||||
if j < len(v) {
|
||||
v = v[:uint(j)]
|
||||
changed = true
|
||||
} else if j == 0 && v == nil {
|
||||
v = []{{ .Elem }}{}
|
||||
changed = true
|
||||
}
|
||||
slh.End()
|
||||
return v, changed
|
||||
}
|
||||
func (fastpathT) {{ .MethodNamePfx "Dec" false }}N(v []{{ .Elem }}, d *Decoder) {
|
||||
{{ if eq .Elem "uint8" "byte" -}}
|
||||
switch d.d.ContainerType() {
|
||||
case valueTypeNil, valueTypeMap:
|
||||
break
|
||||
default:
|
||||
v2 := d.decodeBytesInto(v[:len(v):len(v)])
|
||||
if !(len(v2) > 0 && len(v2) == len(v) && &v2[0] == &v[0]) { // not same slice
|
||||
copy(v, v2)
|
||||
}
|
||||
return
|
||||
}
|
||||
{{ end -}}
|
||||
slh, containerLenS := d.decSliceHelperStart()
|
||||
if slh.IsNil {
|
||||
return
|
||||
}
|
||||
if containerLenS == 0 {
|
||||
slh.End()
|
||||
return
|
||||
}
|
||||
hasLen := containerLenS > 0
|
||||
for j := 0; (hasLen && j < containerLenS) || !(hasLen || d.checkBreak()); j++ {
|
||||
{{/* // if indefinite, etc, then expand the slice if necessary */ -}}
|
||||
if j >= len(v) {
|
||||
slh.arrayCannotExpand(hasLen, len(v), j, containerLenS)
|
||||
return
|
||||
}
|
||||
slh.ElemContainerState(j)
|
||||
{{ if eq .Elem "interface{}" -}}
|
||||
d.decode(&v[uint(j)])
|
||||
{{- else -}}
|
||||
v[uint(j)] = {{ decmd .Elem false }}
|
||||
{{- end }}
|
||||
}
|
||||
slh.End()
|
||||
}
|
||||
{{end}}{{end}}{{end -}}
|
||||
|
||||
{{end}}{{end}}{{end}}
|
||||
|
||||
|
||||
{{range .Values}}{{if not .Primitive}}{{if .MapKey }}
|
||||
{{range .Values}}{{if not .Primitive}}{{if .MapKey -}}
|
||||
{{/*
|
||||
Maps can change if they are
|
||||
- addressable (from a ptr)
|
||||
- settable (e.g. contained in an interface{})
|
||||
*/}}
|
||||
func (f *decFnInfo) {{ .MethodNamePfx "fastpathDec" false }}R(rv reflect.Value) {
|
||||
if rv.CanAddr() {
|
||||
vp := rv.Addr().Interface().(*map[{{ .MapKey }}]{{ .Elem }})
|
||||
v, changed := fastpathTV.{{ .MethodNamePfx "Dec" false }}V(*vp, fastpathCheckNilFalse, true, f.d)
|
||||
if changed {
|
||||
*vp = v
|
||||
|
||||
Also, these methods are called by decodeValue directly, after handling a TryNil.
|
||||
Consequently, there's no need to check for containerLenNil here.
|
||||
*/ -}}
|
||||
func (d *Decoder) {{ .MethodNamePfx "fastpathDec" false }}R(f *codecFnInfo, rv reflect.Value) {
|
||||
containerLen := d.mapStart(d.d.ReadMapStart())
|
||||
{{/*
|
||||
if containerLen == containerLenNil {
|
||||
if rv.Kind() == reflect.Ptr {
|
||||
*(rv2i(rv).(*map[{{ .MapKey }}]{{ .Elem }})) = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
*/ -}}
|
||||
if rv.Kind() == reflect.Ptr {
|
||||
vp, _ := rv2i(rv).(*map[{{ .MapKey }}]{{ .Elem }})
|
||||
if *vp == nil {
|
||||
*vp = make(map[{{ .MapKey }}]{{ .Elem }}, decInferLen(containerLen, d.h.MaxInitLen, {{ .Size }}))
|
||||
}
|
||||
if containerLen != 0 {
|
||||
fastpathTV.{{ .MethodNamePfx "Dec" false }}L(*vp, containerLen, d)
|
||||
}
|
||||
} else if containerLen != 0 {
|
||||
fastpathTV.{{ .MethodNamePfx "Dec" false }}L(rv2i(rv).(map[{{ .MapKey }}]{{ .Elem }}), containerLen, d)
|
||||
}
|
||||
d.mapEnd()
|
||||
}
|
||||
func (f fastpathT) {{ .MethodNamePfx "Dec" false }}X(vp *map[{{ .MapKey }}]{{ .Elem }}, d *Decoder) {
|
||||
containerLen := d.mapStart(d.d.ReadMapStart())
|
||||
if containerLen == containerLenNil {
|
||||
*vp = nil
|
||||
} else {
|
||||
v := rv.Interface().(map[{{ .MapKey }}]{{ .Elem }})
|
||||
fastpathTV.{{ .MethodNamePfx "Dec" false }}V(v, fastpathCheckNilFalse, false, f.d)
|
||||
}
|
||||
}
|
||||
func (f fastpathT) {{ .MethodNamePfx "Dec" false }}X(vp *map[{{ .MapKey }}]{{ .Elem }}, checkNil bool, d *Decoder) {
|
||||
v, changed := f.{{ .MethodNamePfx "Dec" false }}V(*vp, checkNil, true, d)
|
||||
if changed {
|
||||
*vp = v
|
||||
}
|
||||
}
|
||||
func (_ fastpathT) {{ .MethodNamePfx "Dec" false }}V(v map[{{ .MapKey }}]{{ .Elem }}, checkNil bool, canChange bool,
|
||||
d *Decoder) (_ map[{{ .MapKey }}]{{ .Elem }}, changed bool) {
|
||||
dd := d.d
|
||||
cr := d.cr
|
||||
{{/* // if dd.isContainerType(valueTypeNil) {dd.TryDecodeAsNil() */}}
|
||||
if checkNil && dd.TryDecodeAsNil() {
|
||||
if v != nil {
|
||||
changed = true
|
||||
if *vp == nil {
|
||||
*vp = make(map[{{ .MapKey }}]{{ .Elem }}, decInferLen(containerLen, d.h.MaxInitLen, {{ .Size }}))
|
||||
}
|
||||
return nil, changed
|
||||
if containerLen != 0 {
|
||||
f.{{ .MethodNamePfx "Dec" false }}L(*vp, containerLen, d)
|
||||
}
|
||||
d.mapEnd()
|
||||
}
|
||||
|
||||
containerLen := dd.ReadMapStart()
|
||||
if canChange && v == nil {
|
||||
xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, {{ .Size }})
|
||||
v = make(map[{{ .MapKey }}]{{ .Elem }}, xlen)
|
||||
changed = true
|
||||
}
|
||||
func (fastpathT) {{ .MethodNamePfx "Dec" false }}L(v map[{{ .MapKey }}]{{ .Elem }}, containerLen int, d *Decoder) {
|
||||
{{/* No need to check if containerLen == containerLenNil, as that is checked by R and L above */ -}}
|
||||
if v == nil {
|
||||
d.errorf("cannot decode into nil map[{{ .MapKey }}]{{ .Elem }} given stream length: %v", containerLen)
|
||||
{{/* d.swallowMapContents(containerLen) */ -}}
|
||||
return
|
||||
}
|
||||
{{ if eq .Elem "interface{}" }}mapGet := !d.h.MapValueReset && !d.h.InterfaceReset{{end}}
|
||||
var mk {{ .MapKey }}
|
||||
{{if eq .Elem "interface{}" }}mapGet := v != nil && !d.h.MapValueReset && !d.h.InterfaceReset
|
||||
{{else if eq .Elem "bytes" "[]byte" }}mapGet := v != nil && !d.h.MapValueReset
|
||||
{{end -}}
|
||||
var mk {{ .MapKey }}
|
||||
var mv {{ .Elem }}
|
||||
if containerLen > 0 {
|
||||
for j := 0; j < containerLen; j++ {
|
||||
if cr != nil { cr.sendContainerState(containerMapKey) }
|
||||
{{ if eq .MapKey "interface{}" }}mk = nil
|
||||
d.decode(&mk)
|
||||
if bv, bok := mk.([]byte); bok {
|
||||
mk = d.string(bv) {{/* // maps cannot have []byte as key. switch to string. */}}
|
||||
}{{ else }}mk = {{ decmd .MapKey }}{{ end }}
|
||||
if cr != nil { cr.sendContainerState(containerMapValue) }
|
||||
{{ if eq .Elem "interface{}" }}if mapGet { mv = v[mk] } else { mv = nil }
|
||||
d.decode(&mv){{ else }}mv = {{ decmd .Elem }}{{ end }}
|
||||
if v != nil {
|
||||
v[mk] = mv
|
||||
}
|
||||
}
|
||||
} else if containerLen < 0 {
|
||||
for j := 0; !dd.CheckBreak(); j++ {
|
||||
if cr != nil { cr.sendContainerState(containerMapKey) }
|
||||
{{ if eq .MapKey "interface{}" }}mk = nil
|
||||
d.decode(&mk)
|
||||
if bv, bok := mk.([]byte); bok {
|
||||
mk = d.string(bv) {{/* // maps cannot have []byte as key. switch to string. */}}
|
||||
}{{ else }}mk = {{ decmd .MapKey }}{{ end }}
|
||||
if cr != nil { cr.sendContainerState(containerMapValue) }
|
||||
{{ if eq .Elem "interface{}" }}if mapGet { mv = v[mk] } else { mv = nil }
|
||||
d.decode(&mv){{ else }}mv = {{ decmd .Elem }}{{ end }}
|
||||
if v != nil {
|
||||
v[mk] = mv
|
||||
}
|
||||
}
|
||||
hasLen := containerLen > 0
|
||||
for j := 0; (hasLen && j < containerLen) || !(hasLen || d.checkBreak()); j++ {
|
||||
d.mapElemKey()
|
||||
{{ if eq .MapKey "interface{}" }}mk = nil
|
||||
d.decode(&mk)
|
||||
if bv, bok := mk.([]byte); bok {
|
||||
mk = d.stringZC(bv) {{/* // maps cannot have []byte as key. switch to string. */}}
|
||||
}{{ else }}mk = {{ decmd .MapKey true }}{{ end }}
|
||||
d.mapElemValue()
|
||||
{{ if eq .Elem "interface{}" "[]byte" "bytes" -}}
|
||||
if mapGet { mv = v[mk] } else { mv = nil }
|
||||
{{ end -}}
|
||||
{{ if eq .Elem "interface{}" -}}
|
||||
d.decode(&mv)
|
||||
{{ else if eq .Elem "[]byte" "bytes" -}}
|
||||
mv = d.decodeBytesInto(mv)
|
||||
{{ else -}}
|
||||
mv = {{ decmd .Elem false }}
|
||||
{{ end -}}
|
||||
v[mk] = mv
|
||||
}
|
||||
if cr != nil { cr.sendContainerState(containerMapEnd) }
|
||||
return v, changed
|
||||
}
|
||||
|
||||
{{end}}{{end}}{{end}}
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
// 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.
|
||||
|
||||
// +build notfastpath
|
||||
|
||||
package codec
|
||||
|
||||
import "reflect"
|
||||
|
||||
const fastpathEnabled = false
|
||||
|
||||
// The generated fast-path code is very large, and adds a few seconds to the build time.
|
||||
// This causes test execution, execution of small tools which use codec, etc
|
||||
// to take a long time.
|
||||
|
@ -12,21 +17,27 @@ import "reflect"
|
|||
// This tag disables fastpath during build, allowing for faster build, test execution,
|
||||
// short-program runs, etc.
|
||||
|
||||
func fastpathDecodeTypeSwitch(iv interface{}, d *Decoder) bool { return false }
|
||||
func fastpathEncodeTypeSwitch(iv interface{}, e *Encoder) bool { return false }
|
||||
func fastpathEncodeTypeSwitchSlice(iv interface{}, e *Encoder) bool { return false }
|
||||
func fastpathEncodeTypeSwitchMap(iv interface{}, e *Encoder) bool { return false }
|
||||
func fastpathDecodeTypeSwitch(iv interface{}, d *Decoder) bool { return false }
|
||||
func fastpathEncodeTypeSwitch(iv interface{}, e *Encoder) bool { return false }
|
||||
|
||||
// func fastpathEncodeTypeSwitchSlice(iv interface{}, e *Encoder) bool { return false }
|
||||
// func fastpathEncodeTypeSwitchMap(iv interface{}, e *Encoder) bool { return false }
|
||||
|
||||
func fastpathDecodeSetZeroTypeSwitch(iv interface{}) bool { return false }
|
||||
|
||||
type fastpathT struct{}
|
||||
type fastpathE struct {
|
||||
rtid uintptr
|
||||
rt reflect.Type
|
||||
encfn func(*encFnInfo, reflect.Value)
|
||||
decfn func(*decFnInfo, reflect.Value)
|
||||
encfn func(*Encoder, *codecFnInfo, reflect.Value)
|
||||
decfn func(*Decoder, *codecFnInfo, reflect.Value)
|
||||
}
|
||||
type fastpathA [0]fastpathE
|
||||
|
||||
func (x fastpathA) index(rtid uintptr) int { return -1 }
|
||||
func fastpathAvIndex(rtid uintptr) int { return -1 }
|
||||
|
||||
var fastpathAV fastpathA
|
||||
var fastpathAv fastpathA
|
||||
var fastpathTV fastpathT
|
||||
|
||||
// ----
|
||||
type TestMammoth2Wrapper struct{} // to allow testMammoth work in notfastpath mode
|
||||
|
|
|
@ -1,104 +1,90 @@
|
|||
{{var "v"}} := {{if not isArray}}*{{end}}{{ .Varname }}
|
||||
{{var "h"}}, {{var "l"}} := z.DecSliceHelperStart() {{/* // helper, containerLenS */}}{{if not isArray}}
|
||||
{{var "h"}}, {{var "l"}} := z.DecSliceHelperStart() {{/* // helper, containerLenS */}}
|
||||
{{if not isArray -}}
|
||||
var {{var "c"}} bool {{/* // changed */}}
|
||||
_ = {{var "c"}}{{end}}
|
||||
_ = {{var "c"}}
|
||||
if {{var "h"}}.IsNil {
|
||||
if {{var "v"}} != nil {
|
||||
{{var "v"}} = nil
|
||||
{{var "c"}} = true
|
||||
}
|
||||
} else {{end -}}
|
||||
if {{var "l"}} == 0 {
|
||||
{{if isSlice }}if {{var "v"}} == nil {
|
||||
{{if isSlice -}}
|
||||
if {{var "v"}} == nil {
|
||||
{{var "v"}} = []{{ .Typ }}{}
|
||||
{{var "c"}} = true
|
||||
} else if len({{var "v"}}) != 0 {
|
||||
{{var "v"}} = {{var "v"}}[:0]
|
||||
{{var "c"}} = true
|
||||
} {{end}} {{if isChan }}if {{var "v"}} == nil {
|
||||
} {{else if isChan }}if {{var "v"}} == nil {
|
||||
{{var "v"}} = make({{ .CTyp }}, 0)
|
||||
{{var "c"}} = true
|
||||
} {{end}}
|
||||
} else if {{var "l"}} > 0 {
|
||||
{{if isChan }}if {{var "v"}} == nil {
|
||||
{{var "rl"}}, _ = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})
|
||||
{{var "v"}} = make({{ .CTyp }}, {{var "rl"}})
|
||||
{{var "c"}} = true
|
||||
}
|
||||
for {{var "r"}} := 0; {{var "r"}} < {{var "l"}}; {{var "r"}}++ {
|
||||
{{var "h"}}.ElemContainerState({{var "r"}})
|
||||
var {{var "t"}} {{ .Typ }}
|
||||
{{ $x := printf "%st%s" .TempVar .Rand }}{{ decLineVar $x }}
|
||||
{{var "v"}} <- {{var "t"}}
|
||||
}
|
||||
{{ else }} var {{var "rr"}}, {{var "rl"}} int {{/* // num2read, length of slice/array/chan */}}
|
||||
var {{var "rt"}} bool {{/* truncated */}}
|
||||
_, _ = {{var "rl"}}, {{var "rt"}}
|
||||
{{var "rr"}} = {{var "l"}} // len({{var "v"}})
|
||||
{{end -}}
|
||||
} else {
|
||||
{{var "hl"}} := {{var "l"}} > 0
|
||||
var {{var "rl"}} int
|
||||
_ = {{var "rl"}}
|
||||
{{if isSlice }} if {{var "hl"}} {
|
||||
if {{var "l"}} > cap({{var "v"}}) {
|
||||
{{if isArray }}z.DecArrayCannotExpand(len({{var "v"}}), {{var "l"}})
|
||||
{{ else }}{{if not .Immutable }}
|
||||
{{var "rg"}} := len({{var "v"}}) > 0
|
||||
{{var "v2"}} := {{var "v"}} {{end}}
|
||||
{{var "rl"}}, {{var "rt"}} = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})
|
||||
if {{var "rt"}} {
|
||||
if {{var "rl"}} <= cap({{var "v"}}) {
|
||||
{{var "v"}} = {{var "v"}}[:{{var "rl"}}]
|
||||
} else {
|
||||
{{var "v"}} = make([]{{ .Typ }}, {{var "rl"}})
|
||||
}
|
||||
{{var "rl"}} = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})
|
||||
if {{var "rl"}} <= cap({{var "v"}}) {
|
||||
{{var "v"}} = {{var "v"}}[:{{var "rl"}}]
|
||||
} else {
|
||||
{{var "v"}} = make([]{{ .Typ }}, {{var "rl"}})
|
||||
}
|
||||
{{var "c"}} = true
|
||||
{{var "rr"}} = len({{var "v"}}) {{if not .Immutable }}
|
||||
if {{var "rg"}} { copy({{var "v"}}, {{var "v2"}}) } {{end}} {{end}}{{/* end not Immutable, isArray */}}
|
||||
} {{if isSlice }} else if {{var "l"}} != len({{var "v"}}) {
|
||||
} else if {{var "l"}} != len({{var "v"}}) {
|
||||
{{var "v"}} = {{var "v"}}[:{{var "l"}}]
|
||||
{{var "c"}} = true
|
||||
} {{end}} {{/* end isSlice:47 */}}
|
||||
{{var "j"}} := 0
|
||||
for ; {{var "j"}} < {{var "rr"}} ; {{var "j"}}++ {
|
||||
{{var "h"}}.ElemContainerState({{var "j"}})
|
||||
{{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }}
|
||||
}
|
||||
{{if isArray }}for ; {{var "j"}} < {{var "l"}} ; {{var "j"}}++ {
|
||||
{{var "h"}}.ElemContainerState({{var "j"}})
|
||||
z.DecSwallow()
|
||||
}
|
||||
{{ else }}if {{var "rt"}} {
|
||||
for ; {{var "j"}} < {{var "l"}} ; {{var "j"}}++ {
|
||||
{{var "v"}} = append({{var "v"}}, {{ zero}})
|
||||
{{var "h"}}.ElemContainerState({{var "j"}})
|
||||
{{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }}
|
||||
{{end -}}
|
||||
var {{var "j"}} int
|
||||
{{/* // var {{var "dn"}} bool */ -}}
|
||||
for {{var "j"}} = 0; ({{var "hl"}} && {{var "j"}} < {{var "l"}}) || !({{var "hl"}} || z.DecCheckBreak()); {{var "j"}}++ { // bounds-check-elimination
|
||||
{{if not isArray}} if {{var "j"}} == 0 && {{var "v"}} == nil {
|
||||
if {{var "hl"}} {
|
||||
{{var "rl"}} = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})
|
||||
} else {
|
||||
{{var "rl"}} = {{if isSlice}}8{{else if isChan}}64{{end}}
|
||||
}
|
||||
{{var "v"}} = make({{if isSlice}}[]{{ .Typ }}{{else if isChan}}{{.CTyp}}{{end}}, {{var "rl"}})
|
||||
{{var "c"}} = true
|
||||
}
|
||||
} {{end}} {{/* end isArray:56 */}}
|
||||
{{end}} {{/* end isChan:16 */}}
|
||||
} else { {{/* len < 0 */}}
|
||||
{{var "j"}} := 0
|
||||
for ; !r.CheckBreak(); {{var "j"}}++ {
|
||||
{{if isChan }}
|
||||
{{end -}}
|
||||
{{var "h"}}.ElemContainerState({{var "j"}})
|
||||
var {{var "t"}} {{ .Typ }}
|
||||
{{ $x := printf "%st%s" .TempVar .Rand }}{{ decLineVar $x }}
|
||||
{{var "v"}} <- {{var "t"}}
|
||||
{{ else }}
|
||||
{{/* {{var "dn"}} = r.TryDecodeAsNil() */}}{{/* commented out, as decLineVar handles this already each time */ -}}
|
||||
{{if isChan}}{{ $x := printf "%[1]vvcx%[2]v" .TempVar .Rand }}var {{$x}} {{ .Typ }}
|
||||
{{ decLineVar $x -}}
|
||||
{{var "v"}} <- {{ $x }}
|
||||
{{else}}{{/* // if indefinite, etc, then expand the slice if necessary */ -}}
|
||||
var {{var "db"}} bool
|
||||
if {{var "j"}} >= len({{var "v"}}) {
|
||||
{{if isArray }}z.DecArrayCannotExpand(len({{var "v"}}), {{var "j"}}+1)
|
||||
{{ else }}{{var "v"}} = append({{var "v"}}, {{zero}})// var {{var "z"}} {{ .Typ }}
|
||||
{{var "c"}} = true {{end}}
|
||||
{{if isSlice }} {{var "v"}} = append({{var "v"}}, {{ zero }})
|
||||
{{var "c"}} = true
|
||||
{{else}} z.DecArrayCannotExpand(len(v), {{var "j"}}+1); {{var "db"}} = true
|
||||
{{end -}}
|
||||
}
|
||||
{{var "h"}}.ElemContainerState({{var "j"}})
|
||||
if {{var "j"}} < len({{var "v"}}) {
|
||||
{{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }}
|
||||
} else {
|
||||
if {{var "db"}} {
|
||||
z.DecSwallow()
|
||||
} else {
|
||||
{{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x -}}
|
||||
}
|
||||
{{end}}
|
||||
{{end -}}
|
||||
}
|
||||
{{if isSlice }}if {{var "j"}} < len({{var "v"}}) {
|
||||
{{if isSlice}} if {{var "j"}} < len({{var "v"}}) {
|
||||
{{var "v"}} = {{var "v"}}[:{{var "j"}}]
|
||||
{{var "c"}} = true
|
||||
} else if {{var "j"}} == 0 && {{var "v"}} == nil {
|
||||
{{var "v"}} = []{{ .Typ }}{}
|
||||
{{var "v"}} = make([]{{ .Typ }}, 0)
|
||||
{{var "c"}} = true
|
||||
}{{end}}
|
||||
}
|
||||
{{end -}}
|
||||
}
|
||||
{{var "h"}}.End()
|
||||
{{if not isArray }}if {{var "c"}} {
|
||||
*{{ .Varname }} = {{var "v"}}
|
||||
}{{end}}
|
||||
}
|
||||
{{end -}}
|
||||
|
|
|
@ -1,58 +1,58 @@
|
|||
{{var "v"}} := *{{ .Varname }}
|
||||
{{var "l"}} := r.ReadMapStart()
|
||||
{{var "bh"}} := z.DecBasicHandle()
|
||||
{{var "l"}} := z.DecReadMapStart()
|
||||
if {{var "l"}} == codecSelferDecContainerLenNil{{xs}} {
|
||||
*{{ .Varname }} = nil
|
||||
} else {
|
||||
if {{var "v"}} == nil {
|
||||
{{var "rl"}}, _ := z.DecInferLen({{var "l"}}, {{var "bh"}}.MaxInitLen, {{ .Size }})
|
||||
{{var "rl"}} := z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})
|
||||
{{var "v"}} = make(map[{{ .KTyp }}]{{ .Typ }}, {{var "rl"}})
|
||||
*{{ .Varname }} = {{var "v"}}
|
||||
}
|
||||
var {{var "mk"}} {{ .KTyp }}
|
||||
{{ $mk := var "mk" -}}
|
||||
var {{ $mk }} {{ .KTyp }}
|
||||
var {{var "mv"}} {{ .Typ }}
|
||||
var {{var "mg"}} {{if decElemKindPtr}}, {{var "ms"}}, {{var "mok"}}{{end}} bool
|
||||
if {{var "bh"}}.MapValueReset {
|
||||
var {{var "mg"}}, {{var "mdn"}} {{if decElemKindPtr}}, {{var "ms"}}, {{var "mok"}}{{end}} bool
|
||||
if z.DecBasicHandle().MapValueReset {
|
||||
{{if decElemKindPtr}}{{var "mg"}} = true
|
||||
{{else if decElemKindIntf}}if !{{var "bh"}}.InterfaceReset { {{var "mg"}} = true }
|
||||
{{else if decElemKindIntf}}if !z.DecBasicHandle().InterfaceReset { {{var "mg"}} = true }
|
||||
{{else if not decElemKindImmutable}}{{var "mg"}} = true
|
||||
{{end}} }
|
||||
if {{var "l"}} > 0 {
|
||||
for {{var "j"}} := 0; {{var "j"}} < {{var "l"}}; {{var "j"}}++ {
|
||||
z.DecSendContainerState(codecSelfer_containerMapKey{{ .Sfx }})
|
||||
{{ $x := printf "%vmk%v" .TempVar .Rand }}{{ decLineVarK $x }}
|
||||
{{ if eq .KTyp "interface{}" }}{{/* // special case if a byte array. */}}if {{var "bv"}}, {{var "bok"}} := {{var "mk"}}.([]byte); {{var "bok"}} {
|
||||
{{var "mk"}} = string({{var "bv"}})
|
||||
}{{ end }}{{if decElemKindPtr}}
|
||||
{{var "ms"}} = true{{end}}
|
||||
if {{var "l"}} != 0 {
|
||||
{{var "hl"}} := {{var "l"}} > 0
|
||||
for {{var "j"}} := 0; ({{var "hl"}} && {{var "j"}} < {{var "l"}}) || !({{var "hl"}} || z.DecCheckBreak()); {{var "j"}}++ {
|
||||
z.DecReadMapElemKey()
|
||||
{{ if eq .KTyp "string" -}}
|
||||
{{ decLineVarK $mk -}}{{- /* decLineVarKStrZC $mk */ -}}
|
||||
{{ else -}}
|
||||
{{ decLineVarK $mk -}}
|
||||
{{ end -}}
|
||||
{{ if eq .KTyp "interface{}" }}{{/* // special case if a byte array. */ -}}
|
||||
if {{var "bv"}}, {{var "bok"}} := {{var "mk"}}.([]byte); {{var "bok"}} {
|
||||
{{var "mk"}} = z.DecStringZC({{var "bv"}})
|
||||
}
|
||||
{{ end -}}
|
||||
{{if decElemKindPtr -}}
|
||||
{{var "ms"}} = true
|
||||
{{end -}}
|
||||
if {{var "mg"}} {
|
||||
{{if decElemKindPtr}}{{var "mv"}}, {{var "mok"}} = {{var "v"}}[{{var "mk"}}]
|
||||
{{if decElemKindPtr -}}
|
||||
{{var "mv"}}, {{var "mok"}} = {{var "v"}}[{{ $mk }}]
|
||||
if {{var "mok"}} {
|
||||
{{var "ms"}} = false
|
||||
} {{else}}{{var "mv"}} = {{var "v"}}[{{var "mk"}}] {{end}}
|
||||
}
|
||||
{{else -}}
|
||||
{{var "mv"}} = {{var "v"}}[{{ $mk }}]
|
||||
{{end -}}
|
||||
} {{if not decElemKindImmutable}}else { {{var "mv"}} = {{decElemZero}} }{{end}}
|
||||
z.DecSendContainerState(codecSelfer_containerMapValue{{ .Sfx }})
|
||||
{{ $x := printf "%vmv%v" .TempVar .Rand }}{{ decLineVar $x }}
|
||||
if {{if decElemKindPtr}} {{var "ms"}} && {{end}} {{var "v"}} != nil {
|
||||
{{var "v"}}[{{var "mk"}}] = {{var "mv"}}
|
||||
z.DecReadMapElemValue()
|
||||
{{var "mdn"}} = false
|
||||
{{ $x := printf "%vmv%v" .TempVar .Rand }}{{ $y := printf "%vmdn%v" .TempVar .Rand }}{{ decLineVar $x $y -}}
|
||||
if {{var "mdn"}} {
|
||||
{{var "v"}}[{{ $mk }}] = {{decElemZero}}
|
||||
} else {{if decElemKindPtr}} if {{var "ms"}} {{end}} {
|
||||
{{var "v"}}[{{ $mk }}] = {{var "mv"}}
|
||||
}
|
||||
}
|
||||
} else if {{var "l"}} < 0 {
|
||||
for {{var "j"}} := 0; !r.CheckBreak(); {{var "j"}}++ {
|
||||
z.DecSendContainerState(codecSelfer_containerMapKey{{ .Sfx }})
|
||||
{{ $x := printf "%vmk%v" .TempVar .Rand }}{{ decLineVarK $x }}
|
||||
{{ if eq .KTyp "interface{}" }}{{/* // special case if a byte array. */}}if {{var "bv"}}, {{var "bok"}} := {{var "mk"}}.([]byte); {{var "bok"}} {
|
||||
{{var "mk"}} = string({{var "bv"}})
|
||||
}{{ end }}{{if decElemKindPtr}}
|
||||
{{var "ms"}} = true {{ end }}
|
||||
if {{var "mg"}} {
|
||||
{{if decElemKindPtr}}{{var "mv"}}, {{var "mok"}} = {{var "v"}}[{{var "mk"}}]
|
||||
if {{var "mok"}} {
|
||||
{{var "ms"}} = false
|
||||
} {{else}}{{var "mv"}} = {{var "v"}}[{{var "mk"}}] {{end}}
|
||||
} {{if not decElemKindImmutable}}else { {{var "mv"}} = {{decElemZero}} }{{end}}
|
||||
z.DecSendContainerState(codecSelfer_containerMapValue{{ .Sfx }})
|
||||
{{ $x := printf "%vmv%v" .TempVar .Rand }}{{ decLineVar $x }}
|
||||
if {{if decElemKindPtr}} {{var "ms"}} && {{end}} {{var "v"}} != nil {
|
||||
{{var "v"}}[{{var "mk"}}] = {{var "mv"}}
|
||||
}
|
||||
} // else len==0: leave as-is (do not clear map entries)
|
||||
z.DecReadMapEnd()
|
||||
}
|
||||
} // else len==0: TODO: Should we clear map entries?
|
||||
z.DecSendContainerState(codecSelfer_containerMapEnd{{ .Sfx }})
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
{{.Label}}:
|
||||
switch timeout{{.Sfx}} := z.EncBasicHandle().ChanRecvTimeout; {
|
||||
case timeout{{.Sfx}} == 0: // only consume available
|
||||
for {
|
||||
select {
|
||||
case b{{.Sfx}} := <-{{.Chan}}:
|
||||
{{ .Slice }} = append({{.Slice}}, b{{.Sfx}})
|
||||
default:
|
||||
break {{.Label}}
|
||||
}
|
||||
}
|
||||
case timeout{{.Sfx}} > 0: // consume until timeout
|
||||
tt{{.Sfx}} := time.NewTimer(timeout{{.Sfx}})
|
||||
for {
|
||||
select {
|
||||
case b{{.Sfx}} := <-{{.Chan}}:
|
||||
{{.Slice}} = append({{.Slice}}, b{{.Sfx}})
|
||||
case <-tt{{.Sfx}}.C:
|
||||
// close(tt.C)
|
||||
break {{.Label}}
|
||||
}
|
||||
}
|
||||
default: // consume until close
|
||||
for b{{.Sfx}} := range {{.Chan}} {
|
||||
{{.Slice}} = append({{.Slice}}, b{{.Sfx}})
|
||||
}
|
||||
}
|
|
@ -1,12 +1,9 @@
|
|||
// //+build ignore
|
||||
// comment this out // + build ignore
|
||||
|
||||
// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
|
||||
// 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.
|
||||
|
||||
// ************************************************************
|
||||
// DO NOT EDIT.
|
||||
// THIS FILE IS AUTO-GENERATED from gen-helper.go.tmpl
|
||||
// ************************************************************
|
||||
// Code generated from gen-helper.go.tmpl - DO NOT EDIT.
|
||||
|
||||
package codec
|
||||
|
||||
|
@ -15,38 +12,52 @@ import (
|
|||
"reflect"
|
||||
)
|
||||
|
||||
// GenVersion is the current version of codecgen.
|
||||
const GenVersion = 23
|
||||
|
||||
// This file is used to generate helper code for codecgen.
|
||||
// The values here i.e. genHelper(En|De)coder are not to be used directly by
|
||||
// library users. They WILL change continously and without notice.
|
||||
//
|
||||
// To help enforce this, we create an unexported type with exported members.
|
||||
// The only way to get the type is via the one exported type that we control (somewhat).
|
||||
//
|
||||
// When static codecs are created for types, they will use this value
|
||||
// to perform encoding or decoding of primitives or known slice or map types.
|
||||
// library users. They WILL change continuously and without notice.
|
||||
|
||||
// GenHelperEncoder is exported so that it can be used externally by codecgen.
|
||||
// Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE.
|
||||
func GenHelperEncoder(e *Encoder) (genHelperEncoder, encDriver) {
|
||||
return genHelperEncoder{e: e}, e.e
|
||||
//
|
||||
// Library users: DO NOT USE IT DIRECTLY or INDIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE.
|
||||
func GenHelper() (g genHelper) { return }
|
||||
|
||||
type genHelper struct{}
|
||||
|
||||
func (genHelper) Encoder(e *Encoder) (ge genHelperEncoder, ee genHelperEncDriver) {
|
||||
ge = genHelperEncoder{e: e}
|
||||
ee = genHelperEncDriver{encDriver: e.e}
|
||||
return
|
||||
}
|
||||
|
||||
// GenHelperDecoder is exported so that it can be used externally by codecgen.
|
||||
// Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE.
|
||||
func GenHelperDecoder(d *Decoder) (genHelperDecoder, decDriver) {
|
||||
return genHelperDecoder{d: d}, d.d
|
||||
func (genHelper) Decoder(d *Decoder) (gd genHelperDecoder, dd genHelperDecDriver) {
|
||||
gd = genHelperDecoder{d: d}
|
||||
dd = genHelperDecDriver{decDriver: d.d}
|
||||
return
|
||||
}
|
||||
|
||||
type genHelperEncDriver struct {
|
||||
encDriver
|
||||
}
|
||||
|
||||
type genHelperDecDriver struct {
|
||||
decDriver
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
type genHelperEncoder struct {
|
||||
e *Encoder
|
||||
M mustHdl
|
||||
F fastpathT
|
||||
e *Encoder
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
type genHelperDecoder struct {
|
||||
d *Decoder
|
||||
C checkOverflow
|
||||
F fastpathT
|
||||
d *Decoder
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
|
@ -59,69 +70,80 @@ func (f genHelperEncoder) EncBinary() bool {
|
|||
return f.e.be // f.e.hh.isBinaryEncoding()
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncFallback(iv interface{}) {
|
||||
// println(">>>>>>>>> EncFallback")
|
||||
f.e.encodeI(iv, false, false)
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncTextMarshal(iv encoding.TextMarshaler) {
|
||||
bs, fnerr := iv.MarshalText()
|
||||
f.e.marshal(bs, fnerr, false, c_UTF8)
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncJSONMarshal(iv jsonMarshaler) {
|
||||
bs, fnerr := iv.MarshalJSON()
|
||||
f.e.marshal(bs, fnerr, true, c_UTF8)
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncBinaryMarshal(iv encoding.BinaryMarshaler) {
|
||||
bs, fnerr := iv.MarshalBinary()
|
||||
f.e.marshal(bs, fnerr, false, c_RAW)
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) TimeRtidIfBinc() uintptr {
|
||||
if _, ok := f.e.hh.(*BincHandle); ok {
|
||||
return timeTypId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) IsJSONHandle() bool {
|
||||
return f.e.js
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) HasExtensions() bool {
|
||||
return len(f.e.h.extHandle) != 0
|
||||
func (f genHelperEncoder) EncFallback(iv interface{}) {
|
||||
// f.e.encodeI(iv, false, false)
|
||||
f.e.encodeValue(reflect.ValueOf(iv), nil)
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncExt(v interface{}) (r bool) {
|
||||
rt := reflect.TypeOf(v)
|
||||
if rt.Kind() == reflect.Ptr {
|
||||
rt = rt.Elem()
|
||||
}
|
||||
rtid := reflect.ValueOf(rt).Pointer()
|
||||
if xfFn := f.e.h.getExt(rtid); xfFn != nil {
|
||||
f.e.e.EncodeExt(v, xfFn.tag, xfFn.ext, f.e)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
func (f genHelperEncoder) EncTextMarshal(iv encoding.TextMarshaler) {
|
||||
bs, fnerr := iv.MarshalText()
|
||||
f.e.marshalUtf8(bs, fnerr)
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncSendContainerState(c containerState) {
|
||||
if f.e.cr != nil {
|
||||
f.e.cr.sendContainerState(c)
|
||||
}
|
||||
func (f genHelperEncoder) EncJSONMarshal(iv jsonMarshaler) {
|
||||
bs, fnerr := iv.MarshalJSON()
|
||||
f.e.marshalAsis(bs, fnerr)
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncBinaryMarshal(iv encoding.BinaryMarshaler) {
|
||||
bs, fnerr := iv.MarshalBinary()
|
||||
f.e.marshalRaw(bs, fnerr)
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncRaw(iv Raw) { f.e.rawBytes(iv) }
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) Extension(v interface{}) (xfn *extTypeTagFn) {
|
||||
return f.e.h.getExtForI(v)
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncExtension(v interface{}, xfFn *extTypeTagFn) {
|
||||
f.e.e.EncodeExt(v, xfFn.tag, xfFn.ext)
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) WriteStr(s string) {
|
||||
f.e.w().writestr(s)
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncWriteMapStart(length int) { f.e.mapStart(length) }
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncWriteMapEnd() { f.e.mapEnd() }
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncWriteArrayStart(length int) { f.e.arrayStart(length) }
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncWriteArrayEnd() { f.e.arrayEnd() }
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncWriteArrayElem() { f.e.arrayElem() }
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncWriteMapElemKey() { f.e.mapElemKey() }
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncWriteMapElemValue() { f.e.mapElemValue() }
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncEncodeComplex64(v complex64) { f.e.encodeComplex64(v) }
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncEncodeComplex128(v complex128) { f.e.encodeComplex128(v) }
|
||||
|
||||
// ---------------- DECODER FOLLOWS -----------------
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
|
@ -135,19 +157,27 @@ func (f genHelperDecoder) DecBinary() bool {
|
|||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecSwallow() {
|
||||
f.d.swallow()
|
||||
}
|
||||
func (f genHelperDecoder) DecSwallow() { f.d.swallow() }
|
||||
|
||||
// // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
// func (f genHelperDecoder) DecScratchBuffer() []byte {
|
||||
// return f.d.b[:]
|
||||
// }
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecScratchBuffer() []byte {
|
||||
return f.d.b[:]
|
||||
func (f genHelperDecoder) DecScratchArrayBuffer() *[decScratchByteArrayLen]byte {
|
||||
return &f.d.b
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecFallback(iv interface{}, chkPtr bool) {
|
||||
// println(">>>>>>>>> DecFallback")
|
||||
f.d.decodeI(iv, chkPtr, false, false, false)
|
||||
rv := reflect.ValueOf(iv)
|
||||
if chkPtr {
|
||||
if x, _ := isDecodeable(rv); !x {
|
||||
f.d.haltAsNotDecodeable(rv)
|
||||
}
|
||||
}
|
||||
f.d.decodeValue(rv, nil)
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
|
@ -167,37 +197,21 @@ func (f genHelperDecoder) DecArrayCannotExpand(sliceLen, streamLen int) {
|
|||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecTextUnmarshal(tm encoding.TextUnmarshaler) {
|
||||
fnerr := tm.UnmarshalText(f.d.d.DecodeBytes(f.d.b[:], true, true))
|
||||
if fnerr != nil {
|
||||
panic(fnerr)
|
||||
}
|
||||
halt.onerror(tm.UnmarshalText(f.d.d.DecodeStringAsBytes()))
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecJSONUnmarshal(tm jsonUnmarshaler) {
|
||||
// bs := f.dd.DecodeBytes(f.d.b[:], true, true)
|
||||
// grab the bytes to be read, as UnmarshalJSON needs the full JSON so as to unmarshal it itself.
|
||||
fnerr := tm.UnmarshalJSON(f.d.nextValueBytes())
|
||||
if fnerr != nil {
|
||||
panic(fnerr)
|
||||
}
|
||||
f.d.jsonUnmarshalV(tm)
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecBinaryUnmarshal(bm encoding.BinaryUnmarshaler) {
|
||||
fnerr := bm.UnmarshalBinary(f.d.d.DecodeBytes(nil, false, true))
|
||||
if fnerr != nil {
|
||||
panic(fnerr)
|
||||
}
|
||||
halt.onerror(bm.UnmarshalBinary(f.d.d.DecodeBytes(nil)))
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) TimeRtidIfBinc() uintptr {
|
||||
if _, ok := f.d.hh.(*BincHandle); ok {
|
||||
return timeTypId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
func (f genHelperDecoder) DecRaw() []byte { return f.d.rawBytes() }
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) IsJSONHandle() bool {
|
||||
|
@ -205,29 +219,49 @@ func (f genHelperDecoder) IsJSONHandle() bool {
|
|||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) HasExtensions() bool {
|
||||
return len(f.d.h.extHandle) != 0
|
||||
func (f genHelperDecoder) Extension(v interface{}) (xfn *extTypeTagFn) {
|
||||
return f.d.h.getExtForI(v)
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecExt(v interface{}) (r bool) {
|
||||
rt := reflect.TypeOf(v).Elem()
|
||||
rtid := reflect.ValueOf(rt).Pointer()
|
||||
if xfFn := f.d.h.getExt(rtid); xfFn != nil {
|
||||
f.d.d.DecodeExt(v, xfFn.tag, xfFn.ext)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
func (f genHelperDecoder) DecExtension(v interface{}, xfFn *extTypeTagFn) {
|
||||
f.d.d.DecodeExt(v, xfFn.tag, xfFn.ext)
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecInferLen(clen, maxlen, unit int) (rvlen int, truncated bool) {
|
||||
func (f genHelperDecoder) DecInferLen(clen, maxlen, unit int) (rvlen int) {
|
||||
return decInferLen(clen, maxlen, unit)
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecSendContainerState(c containerState) {
|
||||
if f.d.cr != nil {
|
||||
f.d.cr.sendContainerState(c)
|
||||
}
|
||||
}
|
||||
func (f genHelperDecoder) DecReadMapStart() int { return f.d.mapStart(f.d.d.ReadMapStart()) }
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecReadMapEnd() { f.d.mapEnd() }
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecReadArrayStart() int { return f.d.arrayStart(f.d.d.ReadArrayStart()) }
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecReadArrayEnd() { f.d.arrayEnd() }
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecReadArrayElem() { f.d.arrayElem() }
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecReadMapElemKey() { f.d.mapElemKey() }
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecReadMapElemValue() { f.d.mapElemValue() }
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecDecodeFloat32() float32 { return f.d.decodeFloat32() }
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecCheckBreak() bool { return f.d.checkBreak() }
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecStringZC(v []byte) string { return f.d.stringZC(v) }
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecodeBytesInto(v []byte) []byte { return f.d.decodeBytesInto(v) }
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
// //+build ignore
|
||||
// comment this out // + build ignore
|
||||
|
||||
// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
|
||||
// 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.
|
||||
|
||||
// ************************************************************
|
||||
// DO NOT EDIT.
|
||||
// THIS FILE IS AUTO-GENERATED from gen-helper.go.tmpl
|
||||
// ************************************************************
|
||||
// Code generated from gen-helper.go.tmpl - DO NOT EDIT.
|
||||
|
||||
package codec
|
||||
|
||||
|
@ -15,103 +12,127 @@ import (
|
|||
"reflect"
|
||||
)
|
||||
|
||||
// GenVersion is the current version of codecgen.
|
||||
const GenVersion = {{ .Version }}
|
||||
|
||||
// This file is used to generate helper code for codecgen.
|
||||
// The values here i.e. genHelper(En|De)coder are not to be used directly by
|
||||
// library users. They WILL change continously and without notice.
|
||||
//
|
||||
// library users. They WILL change continuously and without notice.
|
||||
|
||||
{{/*
|
||||
// To help enforce this, we create an unexported type with exported members.
|
||||
// The only way to get the type is via the one exported type that we control (somewhat).
|
||||
//
|
||||
// When static codecs are created for types, they will use this value
|
||||
// to perform encoding or decoding of primitives or known slice or map types.
|
||||
*/ -}}
|
||||
|
||||
// GenHelperEncoder is exported so that it can be used externally by codecgen.
|
||||
// Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE.
|
||||
func GenHelperEncoder(e *Encoder) (genHelperEncoder, encDriver) {
|
||||
return genHelperEncoder{e:e}, e.e
|
||||
//
|
||||
// Library users: DO NOT USE IT DIRECTLY or INDIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE.
|
||||
func GenHelper() (g genHelper) { return }
|
||||
|
||||
type genHelper struct {}
|
||||
|
||||
func (genHelper) Encoder(e *Encoder) (ge genHelperEncoder, ee genHelperEncDriver) {
|
||||
ge = genHelperEncoder{e: e}
|
||||
ee = genHelperEncDriver{encDriver: e.e}
|
||||
return
|
||||
}
|
||||
|
||||
// GenHelperDecoder is exported so that it can be used externally by codecgen.
|
||||
// Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE.
|
||||
func GenHelperDecoder(d *Decoder) (genHelperDecoder, decDriver) {
|
||||
return genHelperDecoder{d:d}, d.d
|
||||
func (genHelper) Decoder(d *Decoder) (gd genHelperDecoder, dd genHelperDecDriver) {
|
||||
gd = genHelperDecoder{d: d}
|
||||
dd = genHelperDecDriver{decDriver: d.d}
|
||||
return
|
||||
}
|
||||
|
||||
type genHelperEncDriver struct {
|
||||
encDriver
|
||||
}
|
||||
|
||||
type genHelperDecDriver struct {
|
||||
decDriver
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
type genHelperEncoder struct {
|
||||
e *Encoder
|
||||
M mustHdl
|
||||
F fastpathT
|
||||
e *Encoder
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
type genHelperDecoder struct {
|
||||
d *Decoder
|
||||
C checkOverflow
|
||||
F fastpathT
|
||||
d *Decoder
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncBasicHandle() *BasicHandle {
|
||||
return f.e.h
|
||||
}
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncBinary() bool {
|
||||
return f.e.be // f.e.hh.isBinaryEncoding()
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncFallback(iv interface{}) {
|
||||
// println(">>>>>>>>> EncFallback")
|
||||
f.e.encodeI(iv, false, false)
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncTextMarshal(iv encoding.TextMarshaler) {
|
||||
bs, fnerr := iv.MarshalText()
|
||||
f.e.marshal(bs, fnerr, false, c_UTF8)
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncJSONMarshal(iv jsonMarshaler) {
|
||||
bs, fnerr := iv.MarshalJSON()
|
||||
f.e.marshal(bs, fnerr, true, c_UTF8)
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncBinaryMarshal(iv encoding.BinaryMarshaler) {
|
||||
bs, fnerr := iv.MarshalBinary()
|
||||
f.e.marshal(bs, fnerr, false, c_RAW)
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) TimeRtidIfBinc() uintptr {
|
||||
if _, ok := f.e.hh.(*BincHandle); ok {
|
||||
return timeTypId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) IsJSONHandle() bool {
|
||||
return f.e.js
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) HasExtensions() bool {
|
||||
return len(f.e.h.extHandle) != 0
|
||||
func (f genHelperEncoder) EncFallback(iv interface{}) {
|
||||
// f.e.encodeI(iv, false, false)
|
||||
f.e.encodeValue(reflect.ValueOf(iv), nil)
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncExt(v interface{}) (r bool) {
|
||||
rt := reflect.TypeOf(v)
|
||||
if rt.Kind() == reflect.Ptr {
|
||||
rt = rt.Elem()
|
||||
}
|
||||
rtid := reflect.ValueOf(rt).Pointer()
|
||||
if xfFn := f.e.h.getExt(rtid); xfFn != nil {
|
||||
f.e.e.EncodeExt(v, xfFn.tag, xfFn.ext, f.e)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
func (f genHelperEncoder) EncTextMarshal(iv encoding.TextMarshaler) {
|
||||
bs, fnerr := iv.MarshalText()
|
||||
f.e.marshalUtf8(bs, fnerr)
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncSendContainerState(c containerState) {
|
||||
if f.e.cr != nil {
|
||||
f.e.cr.sendContainerState(c)
|
||||
}
|
||||
func (f genHelperEncoder) EncJSONMarshal(iv jsonMarshaler) {
|
||||
bs, fnerr := iv.MarshalJSON()
|
||||
f.e.marshalAsis(bs, fnerr)
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncBinaryMarshal(iv encoding.BinaryMarshaler) {
|
||||
bs, fnerr := iv.MarshalBinary()
|
||||
f.e.marshalRaw(bs, fnerr)
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncRaw(iv Raw) { f.e.rawBytes(iv) }
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) Extension(v interface{}) (xfn *extTypeTagFn) {
|
||||
return f.e.h.getExtForI(v)
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncExtension(v interface{}, xfFn *extTypeTagFn) {
|
||||
f.e.e.EncodeExt(v, xfFn.tag, xfFn.ext)
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) WriteStr(s string) {
|
||||
f.e.w().writestr(s)
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncWriteMapStart(length int) { f.e.mapStart(length) }
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncWriteMapEnd() { f.e.mapEnd() }
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncWriteArrayStart(length int) { f.e.arrayStart(length) }
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncWriteArrayEnd() { f.e.arrayEnd() }
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncWriteArrayElem() { f.e.arrayElem() }
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncWriteMapElemKey() { f.e.mapElemKey() }
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncWriteMapElemValue() { f.e.mapElemValue() }
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncEncodeComplex64(v complex64) { f.e.encodeComplex64(v) }
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncEncodeComplex128(v complex128) { f.e.encodeComplex128(v) }
|
||||
|
||||
// ---------------- DECODER FOLLOWS -----------------
|
||||
|
||||
|
@ -124,17 +145,26 @@ func (f genHelperDecoder) DecBinary() bool {
|
|||
return f.d.be // f.d.hh.isBinaryEncoding()
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecSwallow() {
|
||||
f.d.swallow()
|
||||
}
|
||||
func (f genHelperDecoder) DecSwallow() { f.d.swallow() }
|
||||
|
||||
// // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
// func (f genHelperDecoder) DecScratchBuffer() []byte {
|
||||
// return f.d.b[:]
|
||||
// }
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecScratchBuffer() []byte {
|
||||
return f.d.b[:]
|
||||
func (f genHelperDecoder) DecScratchArrayBuffer() *[decScratchByteArrayLen]byte {
|
||||
return &f.d.b
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecFallback(iv interface{}, chkPtr bool) {
|
||||
// println(">>>>>>>>> DecFallback")
|
||||
f.d.decodeI(iv, chkPtr, false, false, false)
|
||||
rv := reflect.ValueOf(iv)
|
||||
if chkPtr {
|
||||
if x, _ := isDecodeable(rv); !x {
|
||||
f.d.haltAsNotDecodeable(rv)
|
||||
}
|
||||
}
|
||||
f.d.decodeValue(rv, nil)
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecSliceHelperStart() (decSliceHelper, int) {
|
||||
|
@ -150,215 +180,62 @@ func (f genHelperDecoder) DecArrayCannotExpand(sliceLen, streamLen int) {
|
|||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecTextUnmarshal(tm encoding.TextUnmarshaler) {
|
||||
fnerr := tm.UnmarshalText(f.d.d.DecodeBytes(f.d.b[:], true, true))
|
||||
if fnerr != nil {
|
||||
panic(fnerr)
|
||||
}
|
||||
halt.onerror(tm.UnmarshalText(f.d.d.DecodeStringAsBytes()))
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecJSONUnmarshal(tm jsonUnmarshaler) {
|
||||
// bs := f.dd.DecodeBytes(f.d.b[:], true, true)
|
||||
// grab the bytes to be read, as UnmarshalJSON needs the full JSON so as to unmarshal it itself.
|
||||
fnerr := tm.UnmarshalJSON(f.d.nextValueBytes())
|
||||
if fnerr != nil {
|
||||
panic(fnerr)
|
||||
}
|
||||
f.d.jsonUnmarshalV(tm)
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecBinaryUnmarshal(bm encoding.BinaryUnmarshaler) {
|
||||
fnerr := bm.UnmarshalBinary(f.d.d.DecodeBytes(nil, false, true))
|
||||
if fnerr != nil {
|
||||
panic(fnerr)
|
||||
}
|
||||
halt.onerror(bm.UnmarshalBinary(f.d.d.DecodeBytes(nil)))
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) TimeRtidIfBinc() uintptr {
|
||||
if _, ok := f.d.hh.(*BincHandle); ok {
|
||||
return timeTypId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
func (f genHelperDecoder) DecRaw() []byte { return f.d.rawBytes() }
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) IsJSONHandle() bool {
|
||||
return f.d.js
|
||||
}
|
||||
{{/*
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) HasExtensions() bool {
|
||||
return len(f.d.h.extHandle) != 0
|
||||
func (f genHelperDecoder) I2Rtid(v interface{}) uintptr {
|
||||
return i2rtid(v)
|
||||
}
|
||||
*/ -}}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) Extension(v interface{}) (xfn *extTypeTagFn) {
|
||||
return f.d.h.getExtForI(v)
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecExt(v interface{}) (r bool) {
|
||||
rt := reflect.TypeOf(v).Elem()
|
||||
rtid := reflect.ValueOf(rt).Pointer()
|
||||
if xfFn := f.d.h.getExt(rtid); xfFn != nil {
|
||||
f.d.d.DecodeExt(v, xfFn.tag, xfFn.ext)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
func (f genHelperDecoder) DecExtension(v interface{}, xfFn *extTypeTagFn) {
|
||||
f.d.d.DecodeExt(v, xfFn.tag, xfFn.ext)
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecInferLen(clen, maxlen, unit int) (rvlen int, truncated bool) {
|
||||
func (f genHelperDecoder) DecInferLen(clen, maxlen, unit int) (rvlen int) {
|
||||
return decInferLen(clen, maxlen, unit)
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecSendContainerState(c containerState) {
|
||||
if f.d.cr != nil {
|
||||
f.d.cr.sendContainerState(c)
|
||||
}
|
||||
}
|
||||
|
||||
{{/*
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncDriver() encDriver {
|
||||
return f.e.e
|
||||
}
|
||||
func (f genHelperDecoder) DecReadMapStart() int { return f.d.mapStart(f.d.d.ReadMapStart()) }
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecDriver() decDriver {
|
||||
return f.d.d
|
||||
}
|
||||
func (f genHelperDecoder) DecReadMapEnd() { f.d.mapEnd() }
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecReadArrayStart() int { return f.d.arrayStart(f.d.d.ReadArrayStart()) }
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecReadArrayEnd() { f.d.arrayEnd() }
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecReadArrayElem() { f.d.arrayElem() }
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecReadMapElemKey() { f.d.mapElemKey() }
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecReadMapElemValue() { f.d.mapElemValue() }
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncNil() {
|
||||
f.e.e.EncodeNil()
|
||||
}
|
||||
func (f genHelperDecoder) DecDecodeFloat32() float32 { return f.d.decodeFloat32() }
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncBytes(v []byte) {
|
||||
f.e.e.EncodeStringBytes(c_RAW, v)
|
||||
}
|
||||
func (f genHelperDecoder) DecCheckBreak() bool { return f.d.checkBreak() }
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncArrayStart(length int) {
|
||||
f.e.e.EncodeArrayStart(length)
|
||||
}
|
||||
func (f genHelperDecoder) DecStringZC(v []byte) string { return f.d.stringZC(v) }
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncArrayEnd() {
|
||||
f.e.e.EncodeArrayEnd()
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncArrayEntrySeparator() {
|
||||
f.e.e.EncodeArrayEntrySeparator()
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncMapStart(length int) {
|
||||
f.e.e.EncodeMapStart(length)
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncMapEnd() {
|
||||
f.e.e.EncodeMapEnd()
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncMapEntrySeparator() {
|
||||
f.e.e.EncodeMapEntrySeparator()
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) EncMapKVSeparator() {
|
||||
f.e.e.EncodeMapKVSeparator()
|
||||
}
|
||||
|
||||
// ---------
|
||||
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecBytes(v *[]byte) {
|
||||
*v = f.d.d.DecodeBytes(*v)
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecTryNil() bool {
|
||||
return f.d.d.TryDecodeAsNil()
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecContainerIsNil() (b bool) {
|
||||
return f.d.d.IsContainerType(valueTypeNil)
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecContainerIsMap() (b bool) {
|
||||
return f.d.d.IsContainerType(valueTypeMap)
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecContainerIsArray() (b bool) {
|
||||
return f.d.d.IsContainerType(valueTypeArray)
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecCheckBreak() bool {
|
||||
return f.d.d.CheckBreak()
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecMapStart() int {
|
||||
return f.d.d.ReadMapStart()
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecArrayStart() int {
|
||||
return f.d.d.ReadArrayStart()
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecMapEnd() {
|
||||
f.d.d.ReadMapEnd()
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecArrayEnd() {
|
||||
f.d.d.ReadArrayEnd()
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecArrayEntrySeparator() {
|
||||
f.d.d.ReadArrayEntrySeparator()
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecMapEntrySeparator() {
|
||||
f.d.d.ReadMapEntrySeparator()
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) DecMapKVSeparator() {
|
||||
f.d.d.ReadMapKVSeparator()
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) ReadStringAsBytes(bs []byte) []byte {
|
||||
return f.d.d.DecodeStringAsBytes(bs)
|
||||
}
|
||||
|
||||
|
||||
// -- encode calls (primitives)
|
||||
{{range .Values}}{{if .Primitive }}{{if ne .Primitive "interface{}" }}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) {{ .MethodNamePfx "Enc" true }}(v {{ .Primitive }}) {
|
||||
ee := f.e.e
|
||||
{{ encmd .Primitive "v" }}
|
||||
}
|
||||
{{ end }}{{ end }}{{ end }}
|
||||
|
||||
// -- decode calls (primitives)
|
||||
{{range .Values}}{{if .Primitive }}{{if ne .Primitive "interface{}" }}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) {{ .MethodNamePfx "Dec" true }}(vp *{{ .Primitive }}) {
|
||||
dd := f.d.d
|
||||
*vp = {{ decmd .Primitive }}
|
||||
}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperDecoder) {{ .MethodNamePfx "Read" true }}() (v {{ .Primitive }}) {
|
||||
dd := f.d.d
|
||||
v = {{ decmd .Primitive }}
|
||||
return
|
||||
}
|
||||
{{ end }}{{ end }}{{ end }}
|
||||
|
||||
|
||||
// -- encode calls (slices/maps)
|
||||
{{range .Values}}{{if not .Primitive }}{{if .Slice }}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) {{ .MethodNamePfx "Enc" false }}(v []{{ .Elem }}) { {{ else }}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
func (f genHelperEncoder) {{ .MethodNamePfx "Enc" false }}(v map[{{ .MapKey }}]{{ .Elem }}) { {{end}}
|
||||
f.F.{{ .MethodNamePfx "Enc" false }}V(v, false, f.e)
|
||||
}
|
||||
{{ end }}{{ end }}
|
||||
|
||||
// -- decode calls (slices/maps)
|
||||
{{range .Values}}{{if not .Primitive }}
|
||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||
{{if .Slice }}func (f genHelperDecoder) {{ .MethodNamePfx "Dec" false }}(vp *[]{{ .Elem }}) {
|
||||
{{else}}func (f genHelperDecoder) {{ .MethodNamePfx "Dec" false }}(vp *map[{{ .MapKey }}]{{ .Elem }}) { {{end}}
|
||||
v, changed := f.F.{{ .MethodNamePfx "Dec" false }}V(*vp, false, true, f.d)
|
||||
if changed {
|
||||
*vp = v
|
||||
}
|
||||
}
|
||||
{{ end }}{{ end }}
|
||||
*/}}
|
||||
func (f genHelperDecoder) DecodeBytesInto(v []byte) []byte { return f.d.decodeBytesInto(v) }
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
|
||||
// +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.
|
||||
|
||||
package codec
|
||||
|
@ -7,169 +9,184 @@ package codec
|
|||
|
||||
const genDecMapTmpl = `
|
||||
{{var "v"}} := *{{ .Varname }}
|
||||
{{var "l"}} := r.ReadMapStart()
|
||||
{{var "bh"}} := z.DecBasicHandle()
|
||||
{{var "l"}} := z.DecReadMapStart()
|
||||
if {{var "l"}} == codecSelferDecContainerLenNil{{xs}} {
|
||||
*{{ .Varname }} = nil
|
||||
} else {
|
||||
if {{var "v"}} == nil {
|
||||
{{var "rl"}}, _ := z.DecInferLen({{var "l"}}, {{var "bh"}}.MaxInitLen, {{ .Size }})
|
||||
{{var "rl"}} := z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})
|
||||
{{var "v"}} = make(map[{{ .KTyp }}]{{ .Typ }}, {{var "rl"}})
|
||||
*{{ .Varname }} = {{var "v"}}
|
||||
}
|
||||
var {{var "mk"}} {{ .KTyp }}
|
||||
{{ $mk := var "mk" -}}
|
||||
var {{ $mk }} {{ .KTyp }}
|
||||
var {{var "mv"}} {{ .Typ }}
|
||||
var {{var "mg"}} {{if decElemKindPtr}}, {{var "ms"}}, {{var "mok"}}{{end}} bool
|
||||
if {{var "bh"}}.MapValueReset {
|
||||
var {{var "mg"}}, {{var "mdn"}} {{if decElemKindPtr}}, {{var "ms"}}, {{var "mok"}}{{end}} bool
|
||||
if z.DecBasicHandle().MapValueReset {
|
||||
{{if decElemKindPtr}}{{var "mg"}} = true
|
||||
{{else if decElemKindIntf}}if !{{var "bh"}}.InterfaceReset { {{var "mg"}} = true }
|
||||
{{else if decElemKindIntf}}if !z.DecBasicHandle().InterfaceReset { {{var "mg"}} = true }
|
||||
{{else if not decElemKindImmutable}}{{var "mg"}} = true
|
||||
{{end}} }
|
||||
if {{var "l"}} > 0 {
|
||||
for {{var "j"}} := 0; {{var "j"}} < {{var "l"}}; {{var "j"}}++ {
|
||||
z.DecSendContainerState(codecSelfer_containerMapKey{{ .Sfx }})
|
||||
{{ $x := printf "%vmk%v" .TempVar .Rand }}{{ decLineVarK $x }}
|
||||
{{ if eq .KTyp "interface{}" }}{{/* // special case if a byte array. */}}if {{var "bv"}}, {{var "bok"}} := {{var "mk"}}.([]byte); {{var "bok"}} {
|
||||
{{var "mk"}} = string({{var "bv"}})
|
||||
}{{ end }}{{if decElemKindPtr}}
|
||||
{{var "ms"}} = true{{end}}
|
||||
if {{var "l"}} != 0 {
|
||||
{{var "hl"}} := {{var "l"}} > 0
|
||||
for {{var "j"}} := 0; ({{var "hl"}} && {{var "j"}} < {{var "l"}}) || !({{var "hl"}} || z.DecCheckBreak()); {{var "j"}}++ {
|
||||
z.DecReadMapElemKey()
|
||||
{{ if eq .KTyp "string" -}}
|
||||
{{ decLineVarK $mk -}}{{- /* decLineVarKStrZC $mk */ -}}
|
||||
{{ else -}}
|
||||
{{ decLineVarK $mk -}}
|
||||
{{ end -}}
|
||||
{{ if eq .KTyp "interface{}" }}{{/* // special case if a byte array. */ -}}
|
||||
if {{var "bv"}}, {{var "bok"}} := {{var "mk"}}.([]byte); {{var "bok"}} {
|
||||
{{var "mk"}} = z.DecStringZC({{var "bv"}})
|
||||
}
|
||||
{{ end -}}
|
||||
{{if decElemKindPtr -}}
|
||||
{{var "ms"}} = true
|
||||
{{end -}}
|
||||
if {{var "mg"}} {
|
||||
{{if decElemKindPtr}}{{var "mv"}}, {{var "mok"}} = {{var "v"}}[{{var "mk"}}]
|
||||
{{if decElemKindPtr -}}
|
||||
{{var "mv"}}, {{var "mok"}} = {{var "v"}}[{{ $mk }}]
|
||||
if {{var "mok"}} {
|
||||
{{var "ms"}} = false
|
||||
} {{else}}{{var "mv"}} = {{var "v"}}[{{var "mk"}}] {{end}}
|
||||
}
|
||||
{{else -}}
|
||||
{{var "mv"}} = {{var "v"}}[{{ $mk }}]
|
||||
{{end -}}
|
||||
} {{if not decElemKindImmutable}}else { {{var "mv"}} = {{decElemZero}} }{{end}}
|
||||
z.DecSendContainerState(codecSelfer_containerMapValue{{ .Sfx }})
|
||||
{{ $x := printf "%vmv%v" .TempVar .Rand }}{{ decLineVar $x }}
|
||||
if {{if decElemKindPtr}} {{var "ms"}} && {{end}} {{var "v"}} != nil {
|
||||
{{var "v"}}[{{var "mk"}}] = {{var "mv"}}
|
||||
z.DecReadMapElemValue()
|
||||
{{var "mdn"}} = false
|
||||
{{ $x := printf "%vmv%v" .TempVar .Rand }}{{ $y := printf "%vmdn%v" .TempVar .Rand }}{{ decLineVar $x $y -}}
|
||||
if {{var "mdn"}} {
|
||||
{{var "v"}}[{{ $mk }}] = {{decElemZero}}
|
||||
} else {{if decElemKindPtr}} if {{var "ms"}} {{end}} {
|
||||
{{var "v"}}[{{ $mk }}] = {{var "mv"}}
|
||||
}
|
||||
}
|
||||
} else if {{var "l"}} < 0 {
|
||||
for {{var "j"}} := 0; !r.CheckBreak(); {{var "j"}}++ {
|
||||
z.DecSendContainerState(codecSelfer_containerMapKey{{ .Sfx }})
|
||||
{{ $x := printf "%vmk%v" .TempVar .Rand }}{{ decLineVarK $x }}
|
||||
{{ if eq .KTyp "interface{}" }}{{/* // special case if a byte array. */}}if {{var "bv"}}, {{var "bok"}} := {{var "mk"}}.([]byte); {{var "bok"}} {
|
||||
{{var "mk"}} = string({{var "bv"}})
|
||||
}{{ end }}{{if decElemKindPtr}}
|
||||
{{var "ms"}} = true {{ end }}
|
||||
if {{var "mg"}} {
|
||||
{{if decElemKindPtr}}{{var "mv"}}, {{var "mok"}} = {{var "v"}}[{{var "mk"}}]
|
||||
if {{var "mok"}} {
|
||||
{{var "ms"}} = false
|
||||
} {{else}}{{var "mv"}} = {{var "v"}}[{{var "mk"}}] {{end}}
|
||||
} {{if not decElemKindImmutable}}else { {{var "mv"}} = {{decElemZero}} }{{end}}
|
||||
z.DecSendContainerState(codecSelfer_containerMapValue{{ .Sfx }})
|
||||
{{ $x := printf "%vmv%v" .TempVar .Rand }}{{ decLineVar $x }}
|
||||
if {{if decElemKindPtr}} {{var "ms"}} && {{end}} {{var "v"}} != nil {
|
||||
{{var "v"}}[{{var "mk"}}] = {{var "mv"}}
|
||||
}
|
||||
} // else len==0: leave as-is (do not clear map entries)
|
||||
z.DecReadMapEnd()
|
||||
}
|
||||
} // else len==0: TODO: Should we clear map entries?
|
||||
z.DecSendContainerState(codecSelfer_containerMapEnd{{ .Sfx }})
|
||||
`
|
||||
|
||||
const genDecListTmpl = `
|
||||
{{var "v"}} := {{if not isArray}}*{{end}}{{ .Varname }}
|
||||
{{var "h"}}, {{var "l"}} := z.DecSliceHelperStart() {{/* // helper, containerLenS */}}{{if not isArray}}
|
||||
{{var "h"}}, {{var "l"}} := z.DecSliceHelperStart() {{/* // helper, containerLenS */}}
|
||||
{{if not isArray -}}
|
||||
var {{var "c"}} bool {{/* // changed */}}
|
||||
_ = {{var "c"}}{{end}}
|
||||
_ = {{var "c"}}
|
||||
if {{var "h"}}.IsNil {
|
||||
if {{var "v"}} != nil {
|
||||
{{var "v"}} = nil
|
||||
{{var "c"}} = true
|
||||
}
|
||||
} else {{end -}}
|
||||
if {{var "l"}} == 0 {
|
||||
{{if isSlice }}if {{var "v"}} == nil {
|
||||
{{if isSlice -}}
|
||||
if {{var "v"}} == nil {
|
||||
{{var "v"}} = []{{ .Typ }}{}
|
||||
{{var "c"}} = true
|
||||
} else if len({{var "v"}}) != 0 {
|
||||
{{var "v"}} = {{var "v"}}[:0]
|
||||
{{var "c"}} = true
|
||||
} {{end}} {{if isChan }}if {{var "v"}} == nil {
|
||||
} {{else if isChan }}if {{var "v"}} == nil {
|
||||
{{var "v"}} = make({{ .CTyp }}, 0)
|
||||
{{var "c"}} = true
|
||||
} {{end}}
|
||||
} else if {{var "l"}} > 0 {
|
||||
{{if isChan }}if {{var "v"}} == nil {
|
||||
{{var "rl"}}, _ = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})
|
||||
{{var "v"}} = make({{ .CTyp }}, {{var "rl"}})
|
||||
{{var "c"}} = true
|
||||
}
|
||||
for {{var "r"}} := 0; {{var "r"}} < {{var "l"}}; {{var "r"}}++ {
|
||||
{{var "h"}}.ElemContainerState({{var "r"}})
|
||||
var {{var "t"}} {{ .Typ }}
|
||||
{{ $x := printf "%st%s" .TempVar .Rand }}{{ decLineVar $x }}
|
||||
{{var "v"}} <- {{var "t"}}
|
||||
}
|
||||
{{ else }} var {{var "rr"}}, {{var "rl"}} int {{/* // num2read, length of slice/array/chan */}}
|
||||
var {{var "rt"}} bool {{/* truncated */}}
|
||||
_, _ = {{var "rl"}}, {{var "rt"}}
|
||||
{{var "rr"}} = {{var "l"}} // len({{var "v"}})
|
||||
{{end -}}
|
||||
} else {
|
||||
{{var "hl"}} := {{var "l"}} > 0
|
||||
var {{var "rl"}} int
|
||||
_ = {{var "rl"}}
|
||||
{{if isSlice }} if {{var "hl"}} {
|
||||
if {{var "l"}} > cap({{var "v"}}) {
|
||||
{{if isArray }}z.DecArrayCannotExpand(len({{var "v"}}), {{var "l"}})
|
||||
{{ else }}{{if not .Immutable }}
|
||||
{{var "rg"}} := len({{var "v"}}) > 0
|
||||
{{var "v2"}} := {{var "v"}} {{end}}
|
||||
{{var "rl"}}, {{var "rt"}} = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})
|
||||
if {{var "rt"}} {
|
||||
if {{var "rl"}} <= cap({{var "v"}}) {
|
||||
{{var "v"}} = {{var "v"}}[:{{var "rl"}}]
|
||||
} else {
|
||||
{{var "v"}} = make([]{{ .Typ }}, {{var "rl"}})
|
||||
}
|
||||
{{var "rl"}} = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})
|
||||
if {{var "rl"}} <= cap({{var "v"}}) {
|
||||
{{var "v"}} = {{var "v"}}[:{{var "rl"}}]
|
||||
} else {
|
||||
{{var "v"}} = make([]{{ .Typ }}, {{var "rl"}})
|
||||
}
|
||||
{{var "c"}} = true
|
||||
{{var "rr"}} = len({{var "v"}}) {{if not .Immutable }}
|
||||
if {{var "rg"}} { copy({{var "v"}}, {{var "v2"}}) } {{end}} {{end}}{{/* end not Immutable, isArray */}}
|
||||
} {{if isSlice }} else if {{var "l"}} != len({{var "v"}}) {
|
||||
} else if {{var "l"}} != len({{var "v"}}) {
|
||||
{{var "v"}} = {{var "v"}}[:{{var "l"}}]
|
||||
{{var "c"}} = true
|
||||
} {{end}} {{/* end isSlice:47 */}}
|
||||
{{var "j"}} := 0
|
||||
for ; {{var "j"}} < {{var "rr"}} ; {{var "j"}}++ {
|
||||
{{var "h"}}.ElemContainerState({{var "j"}})
|
||||
{{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }}
|
||||
}
|
||||
{{if isArray }}for ; {{var "j"}} < {{var "l"}} ; {{var "j"}}++ {
|
||||
{{var "h"}}.ElemContainerState({{var "j"}})
|
||||
z.DecSwallow()
|
||||
}
|
||||
{{ else }}if {{var "rt"}} {
|
||||
for ; {{var "j"}} < {{var "l"}} ; {{var "j"}}++ {
|
||||
{{var "v"}} = append({{var "v"}}, {{ zero}})
|
||||
{{var "h"}}.ElemContainerState({{var "j"}})
|
||||
{{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }}
|
||||
{{end -}}
|
||||
var {{var "j"}} int
|
||||
{{/* // var {{var "dn"}} bool */ -}}
|
||||
for {{var "j"}} = 0; ({{var "hl"}} && {{var "j"}} < {{var "l"}}) || !({{var "hl"}} || z.DecCheckBreak()); {{var "j"}}++ { // bounds-check-elimination
|
||||
{{if not isArray}} if {{var "j"}} == 0 && {{var "v"}} == nil {
|
||||
if {{var "hl"}} {
|
||||
{{var "rl"}} = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})
|
||||
} else {
|
||||
{{var "rl"}} = {{if isSlice}}8{{else if isChan}}64{{end}}
|
||||
}
|
||||
{{var "v"}} = make({{if isSlice}}[]{{ .Typ }}{{else if isChan}}{{.CTyp}}{{end}}, {{var "rl"}})
|
||||
{{var "c"}} = true
|
||||
}
|
||||
} {{end}} {{/* end isArray:56 */}}
|
||||
{{end}} {{/* end isChan:16 */}}
|
||||
} else { {{/* len < 0 */}}
|
||||
{{var "j"}} := 0
|
||||
for ; !r.CheckBreak(); {{var "j"}}++ {
|
||||
{{if isChan }}
|
||||
{{end -}}
|
||||
{{var "h"}}.ElemContainerState({{var "j"}})
|
||||
var {{var "t"}} {{ .Typ }}
|
||||
{{ $x := printf "%st%s" .TempVar .Rand }}{{ decLineVar $x }}
|
||||
{{var "v"}} <- {{var "t"}}
|
||||
{{ else }}
|
||||
{{/* {{var "dn"}} = r.TryDecodeAsNil() */}}{{/* commented out, as decLineVar handles this already each time */ -}}
|
||||
{{if isChan}}{{ $x := printf "%[1]vvcx%[2]v" .TempVar .Rand }}var {{$x}} {{ .Typ }}
|
||||
{{ decLineVar $x -}}
|
||||
{{var "v"}} <- {{ $x }}
|
||||
{{else}}{{/* // if indefinite, etc, then expand the slice if necessary */ -}}
|
||||
var {{var "db"}} bool
|
||||
if {{var "j"}} >= len({{var "v"}}) {
|
||||
{{if isArray }}z.DecArrayCannotExpand(len({{var "v"}}), {{var "j"}}+1)
|
||||
{{ else }}{{var "v"}} = append({{var "v"}}, {{zero}})// var {{var "z"}} {{ .Typ }}
|
||||
{{var "c"}} = true {{end}}
|
||||
{{if isSlice }} {{var "v"}} = append({{var "v"}}, {{ zero }})
|
||||
{{var "c"}} = true
|
||||
{{else}} z.DecArrayCannotExpand(len(v), {{var "j"}}+1); {{var "db"}} = true
|
||||
{{end -}}
|
||||
}
|
||||
{{var "h"}}.ElemContainerState({{var "j"}})
|
||||
if {{var "j"}} < len({{var "v"}}) {
|
||||
{{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }}
|
||||
} else {
|
||||
if {{var "db"}} {
|
||||
z.DecSwallow()
|
||||
} else {
|
||||
{{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x -}}
|
||||
}
|
||||
{{end}}
|
||||
{{end -}}
|
||||
}
|
||||
{{if isSlice }}if {{var "j"}} < len({{var "v"}}) {
|
||||
{{if isSlice}} if {{var "j"}} < len({{var "v"}}) {
|
||||
{{var "v"}} = {{var "v"}}[:{{var "j"}}]
|
||||
{{var "c"}} = true
|
||||
} else if {{var "j"}} == 0 && {{var "v"}} == nil {
|
||||
{{var "v"}} = []{{ .Typ }}{}
|
||||
{{var "v"}} = make([]{{ .Typ }}, 0)
|
||||
{{var "c"}} = true
|
||||
}{{end}}
|
||||
}
|
||||
{{end -}}
|
||||
}
|
||||
{{var "h"}}.End()
|
||||
{{if not isArray }}if {{var "c"}} {
|
||||
*{{ .Varname }} = {{var "v"}}
|
||||
}{{end}}
|
||||
}
|
||||
{{end -}}
|
||||
`
|
||||
|
||||
const genEncChanTmpl = `
|
||||
{{.Label}}:
|
||||
switch timeout{{.Sfx}} := z.EncBasicHandle().ChanRecvTimeout; {
|
||||
case timeout{{.Sfx}} == 0: // only consume available
|
||||
for {
|
||||
select {
|
||||
case b{{.Sfx}} := <-{{.Chan}}:
|
||||
{{ .Slice }} = append({{.Slice}}, b{{.Sfx}})
|
||||
default:
|
||||
break {{.Label}}
|
||||
}
|
||||
}
|
||||
case timeout{{.Sfx}} > 0: // consume until timeout
|
||||
tt{{.Sfx}} := time.NewTimer(timeout{{.Sfx}})
|
||||
for {
|
||||
select {
|
||||
case b{{.Sfx}} := <-{{.Chan}}:
|
||||
{{.Slice}} = append({{.Slice}}, b{{.Sfx}})
|
||||
case <-tt{{.Sfx}}.C:
|
||||
// close(tt.C)
|
||||
break {{.Label}}
|
||||
}
|
||||
}
|
||||
default: // consume until close
|
||||
for b{{.Sfx}} := range {{.Chan}} {
|
||||
{{.Slice}} = append({{.Slice}}, b{{.Sfx}})
|
||||
}
|
||||
}
|
||||
`
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,5 @@
|
|||
module github.com/ugorji/go/codec
|
||||
|
||||
go 1.11
|
||||
|
||||
require github.com/ugorji/go v1.2.4
|
|
@ -0,0 +1,14 @@
|
|||
// 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.
|
||||
|
||||
// +build go1.5
|
||||
|
||||
package codec
|
||||
|
||||
import "reflect"
|
||||
|
||||
const reflectArrayOfSupported = true
|
||||
|
||||
func reflectArrayOf(count int, elem reflect.Type) reflect.Type {
|
||||
return reflect.ArrayOf(count, elem)
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
// 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.
|
||||
|
||||
// +build !go1.5
|
||||
|
||||
package codec
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
const reflectArrayOfSupported = false
|
||||
|
||||
var errNoReflectArrayOf = errors.New("codec: reflect.ArrayOf unsupported by this go version")
|
||||
|
||||
func reflectArrayOf(count int, elem reflect.Type) reflect.Type {
|
||||
panic(errNoReflectArrayOf)
|
||||
}
|
|
@ -0,0 +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.
|
||||
|
||||
// +build go1.5
|
||||
|
||||
package codec
|
||||
|
||||
import "time"
|
||||
|
||||
func fmtTime(t time.Time, fmt string, b []byte) []byte {
|
||||
return t.AppendFormat(b, fmt)
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
// 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.
|
||||
|
||||
// +build !go1.5
|
||||
|
||||
package codec
|
||||
|
||||
import "time"
|
||||
|
||||
func fmtTime(t time.Time, fmt string, b []byte) []byte {
|
||||
s := t.Format(fmt)
|
||||
b = b[:len(s)]
|
||||
copy(b, s)
|
||||
return b
|
||||
}
|
|
@ -0,0 +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.
|
||||
|
||||
// +build !go1.10
|
||||
|
||||
package codec
|
||||
|
||||
import "reflect"
|
||||
|
||||
func makeMapReflect(t reflect.Type, size int) reflect.Value {
|
||||
return reflect.MakeMap(t)
|
||||
}
|
13
vendor/github.com/ugorji/go/codec/goversion_makemap_not_unsafe_gte_go110.go
generated
vendored
Normal file
13
vendor/github.com/ugorji/go/codec/goversion_makemap_not_unsafe_gte_go110.go
generated
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
// 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.
|
||||
|
||||
// +build go1.10
|
||||
// +build safe appengine
|
||||
|
||||
package codec
|
||||
|
||||
import "reflect"
|
||||
|
||||
func makeMapReflect(t reflect.Type, size int) reflect.Value {
|
||||
return reflect.MakeMapWithSize(t, size)
|
||||
}
|
26
vendor/github.com/ugorji/go/codec/goversion_makemap_unsafe_gte_go110.go
generated
vendored
Normal file
26
vendor/github.com/ugorji/go/codec/goversion_makemap_unsafe_gte_go110.go
generated
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
// +build go1.10
|
||||
// +build !safe
|
||||
// +build !appengine
|
||||
|
||||
// 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 (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
//go:linkname makemap runtime.makemap
|
||||
//go:noescape
|
||||
func makemap(typ unsafe.Pointer, size int, h unsafe.Pointer) unsafe.Pointer
|
|
@ -0,0 +1,40 @@
|
|||
// 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.
|
||||
|
||||
// +build go1.12
|
||||
// +build safe appengine
|
||||
|
||||
package codec
|
||||
|
||||
import "reflect"
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
// 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.
|
||||
|
||||
// +build go1.7
|
||||
// +build !go1.12
|
||||
// +build safe appengine
|
||||
|
||||
package codec
|
||||
|
||||
import "reflect"
|
||||
|
||||
type mapIter struct {
|
||||
m reflect.Value
|
||||
keys []reflect.Value
|
||||
j int
|
||||
values bool
|
||||
}
|
||||
|
||||
func (t *mapIter) Next() (r bool) {
|
||||
t.j++
|
||||
return t.j < len(t.keys)
|
||||
}
|
||||
|
||||
func (t *mapIter) Key() reflect.Value {
|
||||
return t.keys[t.j]
|
||||
}
|
||||
|
||||
func (t *mapIter) Value() (r reflect.Value) {
|
||||
if t.values {
|
||||
return t.m.MapIndex(t.keys[t.j])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (t *mapIter) Done() {}
|
||||
|
||||
func mapRange(t *mapIter, m, k, v reflect.Value, values bool) {
|
||||
*t = mapIter{
|
||||
m: m,
|
||||
keys: m.MapKeys(),
|
||||
values: values,
|
||||
j: -1,
|
||||
}
|
||||
}
|
8
vendor/github.com/ugorji/go/codec/goversion_unexportedembeddedptr_gte_go110.go
generated
vendored
Normal file
8
vendor/github.com/ugorji/go/codec/goversion_unexportedembeddedptr_gte_go110.go
generated
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
// 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.
|
||||
|
||||
// +build go1.10
|
||||
|
||||
package codec
|
||||
|
||||
const allowSetUnexportedEmbeddedPtr = false
|
8
vendor/github.com/ugorji/go/codec/goversion_unexportedembeddedptr_lt_go110.go
generated
vendored
Normal file
8
vendor/github.com/ugorji/go/codec/goversion_unexportedembeddedptr_lt_go110.go
generated
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
// 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.
|
||||
|
||||
// +build !go1.10
|
||||
|
||||
package codec
|
||||
|
||||
const allowSetUnexportedEmbeddedPtr = true
|
21
vendor/github.com/ugorji/go/codec/goversion_unsupported_lt_go14.go
generated
vendored
Normal file
21
vendor/github.com/ugorji/go/codec/goversion_unsupported_lt_go14.go
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
// 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.
|
||||
|
||||
// +build !go1.4
|
||||
|
||||
package codec
|
||||
|
||||
import "errors"
|
||||
|
||||
// This codec package will only work for go1.4 and above.
|
||||
// This is for the following reasons:
|
||||
// - go 1.4 was released in 2014
|
||||
// - go runtime is written fully in go
|
||||
// - interface only holds pointers
|
||||
// - reflect.Value is stabilized as 3 words
|
||||
|
||||
var errCodecSupportedOnlyFromGo14 = errors.New("codec: go 1.3 and below are not supported")
|
||||
|
||||
func init() {
|
||||
panic(errCodecSupportedOnlyFromGo14)
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
// 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.
|
||||
|
||||
// +build go1.5,!go1.6
|
||||
|
||||
package codec
|
||||
|
||||
import "os"
|
||||
|
||||
var genCheckVendor = os.Getenv("GO15VENDOREXPERIMENT") == "1"
|
|
@ -0,0 +1,10 @@
|
|||
// 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.
|
||||
|
||||
// +build go1.6,!go1.7
|
||||
|
||||
package codec
|
||||
|
||||
import "os"
|
||||
|
||||
var genCheckVendor = os.Getenv("GO15VENDOREXPERIMENT") != "0"
|
|
@ -0,0 +1,8 @@
|
|||
// 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.
|
||||
|
||||
// +build go1.7
|
||||
|
||||
package codec
|
||||
|
||||
const genCheckVendor = true
|
|
@ -0,0 +1,8 @@
|
|||
// 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.
|
||||
|
||||
// +build !go1.5
|
||||
|
||||
package codec
|
||||
|
||||
var genCheckVendor = false
|
File diff suppressed because it is too large
Load Diff
|
@ -1,79 +1,15 @@
|
|||
// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
|
||||
// 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
|
||||
|
||||
// maxArrayLen is the size of uint, which determines
|
||||
// the maximum length of any array.
|
||||
const maxArrayLen = 1<<((32<<(^uint(0)>>63))-1) - 1
|
||||
|
||||
// All non-std package dependencies live in this file,
|
||||
// so porting to different environment is easy (just update functions).
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func panicValToErr(panicVal interface{}, err *error) {
|
||||
if panicVal == nil {
|
||||
return
|
||||
}
|
||||
// case nil
|
||||
switch xerr := panicVal.(type) {
|
||||
case error:
|
||||
*err = xerr
|
||||
case string:
|
||||
*err = errors.New(xerr)
|
||||
default:
|
||||
*err = fmt.Errorf("%v", panicVal)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hIsEmptyValue(v reflect.Value, deref, checkStruct bool) bool {
|
||||
switch v.Kind() {
|
||||
case reflect.Invalid:
|
||||
return true
|
||||
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
|
||||
return v.Len() == 0
|
||||
case reflect.Bool:
|
||||
return !v.Bool()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return v.Int() == 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return v.Uint() == 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v.Float() == 0
|
||||
case reflect.Interface, reflect.Ptr:
|
||||
if deref {
|
||||
if v.IsNil() {
|
||||
return true
|
||||
}
|
||||
return hIsEmptyValue(v.Elem(), deref, checkStruct)
|
||||
} else {
|
||||
return v.IsNil()
|
||||
}
|
||||
case reflect.Struct:
|
||||
if !checkStruct {
|
||||
return false
|
||||
}
|
||||
// return true if all fields are empty. else return false.
|
||||
// we cannot use equality check, because some fields may be maps/slices/etc
|
||||
// and consequently the structs are not comparable.
|
||||
// return v.Interface() == reflect.Zero(v.Type()).Interface()
|
||||
for i, n := 0, v.NumField(); i < n; i++ {
|
||||
if !hIsEmptyValue(v.Field(i), deref, checkStruct) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isEmptyValue(v reflect.Value) bool {
|
||||
return hIsEmptyValue(v, derefForIsEmptyValue, checkStructForEmptyValue)
|
||||
}
|
||||
|
||||
func pruneSignExt(v []byte, pos bool) (n int) {
|
||||
if len(v) < 2 {
|
||||
} else if pos && v[0] == 0 {
|
||||
|
@ -86,157 +22,126 @@ func pruneSignExt(v []byte, pos bool) (n int) {
|
|||
return
|
||||
}
|
||||
|
||||
func implementsIntf(typ, iTyp reflect.Type) (success bool, indir int8) {
|
||||
if typ == nil {
|
||||
return
|
||||
}
|
||||
rt := typ
|
||||
// The type might be a pointer and we need to keep
|
||||
// dereferencing to the base type until we find an implementation.
|
||||
for {
|
||||
if rt.Implements(iTyp) {
|
||||
return true, indir
|
||||
}
|
||||
if p := rt; p.Kind() == reflect.Ptr {
|
||||
indir++
|
||||
if indir >= math.MaxInt8 { // insane number of indirections
|
||||
return false, 0
|
||||
}
|
||||
rt = p.Elem()
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
// No luck yet, but if this is a base type (non-pointer), the pointer might satisfy.
|
||||
if typ.Kind() != reflect.Ptr {
|
||||
// Not a pointer, but does the pointer work?
|
||||
if reflect.PtrTo(typ).Implements(iTyp) {
|
||||
return true, -1
|
||||
}
|
||||
}
|
||||
return false, 0
|
||||
}
|
||||
func halfFloatToFloatBits(h uint16) (f uint32) {
|
||||
// retrofitted from:
|
||||
// - OGRE (Object-Oriented Graphics Rendering Engine)
|
||||
// function: halfToFloatI https://www.ogre3d.org/docs/api/1.9/_ogre_bitwise_8h_source.html
|
||||
|
||||
// validate that this function is correct ...
|
||||
// culled from OGRE (Object-Oriented Graphics Rendering Engine)
|
||||
// function: halfToFloatI (http://stderr.org/doc/ogre-doc/api/OgreBitwise_8h-source.html)
|
||||
func halfFloatToFloatBits(yy uint16) (d uint32) {
|
||||
y := uint32(yy)
|
||||
s := (y >> 15) & 0x01
|
||||
e := (y >> 10) & 0x1f
|
||||
m := y & 0x03ff
|
||||
s := uint32(h >> 15)
|
||||
m := uint32(h & 0x03ff)
|
||||
e := int32((h >> 10) & 0x1f)
|
||||
|
||||
if e == 0 {
|
||||
if m == 0 { // plu or minus 0
|
||||
if m == 0 { // plus or minus 0
|
||||
return s << 31
|
||||
} else { // Denormalized number -- renormalize it
|
||||
for (m & 0x00000400) == 0 {
|
||||
m <<= 1
|
||||
e -= 1
|
||||
}
|
||||
e += 1
|
||||
const zz uint32 = 0x0400
|
||||
m &= ^zz
|
||||
}
|
||||
// Denormalized number -- renormalize it
|
||||
for (m & 0x0400) == 0 {
|
||||
m <<= 1
|
||||
e -= 1
|
||||
}
|
||||
e += 1
|
||||
m &= ^uint32(0x0400)
|
||||
} else if e == 31 {
|
||||
if m == 0 { // Inf
|
||||
return (s << 31) | 0x7f800000
|
||||
} else { // NaN
|
||||
return (s << 31) | 0x7f800000 | (m << 13)
|
||||
}
|
||||
return (s << 31) | 0x7f800000 | (m << 13) // NaN
|
||||
}
|
||||
e = e + (127 - 15)
|
||||
m = m << 13
|
||||
return (s << 31) | (e << 23) | m
|
||||
return (s << 31) | (uint32(e) << 23) | m
|
||||
}
|
||||
|
||||
// GrowCap will return a new capacity for a slice, given the following:
|
||||
func floatToHalfFloatBits(i uint32) (h uint16) {
|
||||
// retrofitted from:
|
||||
// - OGRE (Object-Oriented Graphics Rendering Engine)
|
||||
// function: halfToFloatI https://www.ogre3d.org/docs/api/1.9/_ogre_bitwise_8h_source.html
|
||||
// - http://www.java2s.com/example/java-utility-method/float-to/floattohalf-float-f-fae00.html
|
||||
s := (i >> 16) & 0x8000
|
||||
e := int32(((i >> 23) & 0xff) - (127 - 15))
|
||||
m := i & 0x7fffff
|
||||
|
||||
var h32 uint32
|
||||
|
||||
if e <= 0 {
|
||||
if e < -10 { // zero
|
||||
h32 = s // track -0 vs +0
|
||||
} else {
|
||||
m = (m | 0x800000) >> uint32(1-e)
|
||||
h32 = s | (m >> 13)
|
||||
}
|
||||
} else if e == 0xff-(127-15) {
|
||||
if m == 0 { // Inf
|
||||
h32 = s | 0x7c00
|
||||
} else { // NAN
|
||||
m >>= 13
|
||||
var me uint32
|
||||
if m == 0 {
|
||||
me = 1
|
||||
}
|
||||
h32 = s | 0x7c00 | m | me
|
||||
}
|
||||
} else {
|
||||
if e > 30 { // Overflow
|
||||
h32 = s | 0x7c00
|
||||
} else {
|
||||
h32 = s | (uint32(e) << 10) | (m >> 13)
|
||||
}
|
||||
}
|
||||
h = uint16(h32)
|
||||
return
|
||||
}
|
||||
|
||||
// growCap will return a new capacity for a slice, given the following:
|
||||
// - oldCap: current capacity
|
||||
// - unit: in-memory size of an element
|
||||
// - num: number of elements to add
|
||||
func growCap(oldCap, unit, num int) (newCap int) {
|
||||
func growCap(oldCap, unit, num uint) (newCap uint) {
|
||||
// appendslice logic (if cap < 1024, *2, else *1.25):
|
||||
// leads to many copy calls, especially when copying bytes.
|
||||
// bytes.Buffer model (2*cap + n): much better for bytes.
|
||||
// smarter way is to take the byte-size of the appended element(type) into account
|
||||
|
||||
// maintain 3 thresholds:
|
||||
// maintain 1 thresholds:
|
||||
// t1: if cap <= t1, newcap = 2x
|
||||
// t2: if cap <= t2, newcap = 1.75x
|
||||
// t3: if cap <= t3, newcap = 1.5x
|
||||
// else newcap = 1.25x
|
||||
// else newcap = 1.5x
|
||||
//
|
||||
// t1, t2, t3 >= 1024 always.
|
||||
// i.e. if unit size >= 16, then always do 2x or 1.25x (ie t1, t2, t3 are all same)
|
||||
// t1 is always >= 1024.
|
||||
// This means that, if unit size >= 16, then always do 2x or 1.5x (ie t1, t2, t3 are all same)
|
||||
//
|
||||
// With this, appending for bytes increase by:
|
||||
// 100% up to 4K
|
||||
// 75% up to 8K
|
||||
// 50% up to 16K
|
||||
// 25% beyond that
|
||||
// 50% beyond that
|
||||
|
||||
// unit can be 0 e.g. for struct{}{}; handle that appropriately
|
||||
var t1, t2, t3 int // thresholds
|
||||
if unit <= 1 {
|
||||
t1, t2, t3 = 4*1024, 8*1024, 16*1024
|
||||
} else if unit < 16 {
|
||||
t3 = 16 / unit * 1024
|
||||
t1 = t3 * 1 / 4
|
||||
t2 = t3 * 2 / 4
|
||||
} else {
|
||||
t1, t2, t3 = 1024, 1024, 1024
|
||||
maxCap := num + (oldCap * 3 / 2)
|
||||
if unit == 0 || maxCap > maxArrayLen || maxCap < oldCap { // handle wraparound, etc
|
||||
return maxArrayLen
|
||||
}
|
||||
|
||||
var x int // temporary variable
|
||||
|
||||
// x is multiplier here: one of 5, 6, 7 or 8; incr of 25%, 50%, 75% or 100% respectively
|
||||
if oldCap <= t1 { // [0,t1]
|
||||
x = 8
|
||||
} else if oldCap > t3 { // (t3,infinity]
|
||||
x = 5
|
||||
} else if oldCap <= t2 { // (t1,t2]
|
||||
x = 7
|
||||
} else { // (t2,t3]
|
||||
x = 6
|
||||
}
|
||||
newCap = x * oldCap / 4
|
||||
|
||||
if num > 0 {
|
||||
newCap += num
|
||||
var t1 uint = 1024 // default thresholds for large values
|
||||
if unit <= 4 {
|
||||
t1 = 8 * 1024
|
||||
} else if unit <= 16 {
|
||||
t1 = 2 * 1024
|
||||
}
|
||||
|
||||
// ensure newCap is a multiple of 64 (if it is > 64) or 16.
|
||||
if newCap > 64 {
|
||||
if x = newCap % 64; x != 0 {
|
||||
x = newCap / 64
|
||||
newCap = 64 * (x + 1)
|
||||
}
|
||||
} else {
|
||||
if x = newCap % 16; x != 0 {
|
||||
x = newCap / 16
|
||||
newCap = 16 * (x + 1)
|
||||
newCap = 2 + num
|
||||
if oldCap > 0 {
|
||||
if oldCap <= t1 { // [0,t1]
|
||||
newCap = num + (oldCap * 2)
|
||||
} else { // (t1,infinity]
|
||||
newCap = maxCap
|
||||
}
|
||||
}
|
||||
|
||||
// ensure newCap takes multiples of a cache line (size is a multiple of 64)
|
||||
t1 = newCap * unit
|
||||
if t2 := t1 % 64; t2 != 0 {
|
||||
t1 += 64 - t2
|
||||
newCap = t1 / unit
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func expandSliceValue(s reflect.Value, num int) reflect.Value {
|
||||
if num <= 0 {
|
||||
return s
|
||||
}
|
||||
l0 := s.Len()
|
||||
l1 := l0 + num // new slice length
|
||||
if l1 < l0 {
|
||||
panic("ExpandSlice: slice overflow")
|
||||
}
|
||||
c0 := s.Cap()
|
||||
if l1 <= c0 {
|
||||
return s.Slice(0, l1)
|
||||
}
|
||||
st := s.Type()
|
||||
c1 := growCap(c0, int(st.Elem().Size()), num)
|
||||
s2 := reflect.MakeSlice(st, l1, c1)
|
||||
// println("expandslicevalue: cap-old: ", c0, ", cap-new: ", c1, ", len-new: ", l1)
|
||||
reflect.Copy(s2, s)
|
||||
return s2
|
||||
}
|
||||
|
|
|
@ -1,20 +1,607 @@
|
|||
//+build !unsafe
|
||||
// +build !go1.9 safe appengine
|
||||
|
||||
// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
|
||||
// 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
|
||||
|
||||
// stringView returns a view of the []byte as a string.
|
||||
// In unsafe mode, it doesn't incur allocation and copying caused by conversion.
|
||||
// In regular safe mode, it is an allocation and copy.
|
||||
import (
|
||||
// "hash/adler32"
|
||||
"math"
|
||||
"reflect"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
// This file has safe variants of some helper functions.
|
||||
// MARKER: See helper_unsafe.go for the usage documentation.
|
||||
|
||||
const safeMode = true
|
||||
|
||||
func stringView(v []byte) string {
|
||||
return string(v)
|
||||
}
|
||||
|
||||
// bytesView returns a view of the string as a []byte.
|
||||
// In unsafe mode, it doesn't incur allocation and copying caused by conversion.
|
||||
// In regular safe mode, it is an allocation and copy.
|
||||
func bytesView(v string) []byte {
|
||||
return []byte(v)
|
||||
}
|
||||
|
||||
func byteSliceSameData(v1 []byte, v2 []byte) bool {
|
||||
return cap(v1) != 0 && cap(v2) != 0 && &(v1[:1][0]) == &(v2[:1][0])
|
||||
}
|
||||
|
||||
// func copyBytes(dst []byte, src []byte) {
|
||||
// copy(dst, src)
|
||||
// }
|
||||
|
||||
func isNil(v interface{}) (rv reflect.Value, isnil bool) {
|
||||
rv = reflect.ValueOf(v)
|
||||
if isnilBitset.isset(byte(rv.Kind())) {
|
||||
isnil = rv.IsNil()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// func rvAddr(rv reflect.Value) uintptr {
|
||||
// return rv.UnsafeAddr()
|
||||
// }
|
||||
|
||||
func eq4i(i0, i1 interface{}) bool {
|
||||
return i0 == i1
|
||||
}
|
||||
|
||||
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{} {
|
||||
return rv.Interface()
|
||||
}
|
||||
|
||||
func rvType(rv reflect.Value) reflect.Type {
|
||||
return rv.Type()
|
||||
}
|
||||
|
||||
func rvIsNil(rv reflect.Value) bool {
|
||||
return rv.IsNil()
|
||||
}
|
||||
|
||||
func rvSetSliceLen(rv reflect.Value, length int) {
|
||||
rv.SetLen(length)
|
||||
}
|
||||
|
||||
func rvZeroAddrK(t reflect.Type, k reflect.Kind) reflect.Value {
|
||||
return reflect.New(t).Elem()
|
||||
}
|
||||
|
||||
func rvZeroAddrTransientK(t reflect.Type, k reflect.Kind) (rv reflect.Value) {
|
||||
return reflect.New(t).Elem()
|
||||
}
|
||||
|
||||
func rvZeroAddrTransient2K(t reflect.Type, k reflect.Kind) (rv reflect.Value) {
|
||||
return reflect.New(t).Elem()
|
||||
}
|
||||
|
||||
func rvZeroK(t reflect.Type, k reflect.Kind) reflect.Value {
|
||||
return reflect.Zero(t)
|
||||
}
|
||||
|
||||
func rvConvert(v reflect.Value, t reflect.Type) (rv reflect.Value) {
|
||||
// reflect.Value.Convert(...) will make a copy if it is addressable.
|
||||
// since we need to maintain references for decoding, we must check appropriately.
|
||||
if v.CanAddr() {
|
||||
return v.Addr().Convert(reflect.PtrTo(t)).Elem()
|
||||
}
|
||||
return v.Convert(t)
|
||||
}
|
||||
|
||||
func rvAddressableReadonly(v reflect.Value) (rv reflect.Value) {
|
||||
rv = rvZeroAddrK(v.Type(), v.Kind())
|
||||
rvSetDirect(rv, v)
|
||||
return
|
||||
}
|
||||
|
||||
func rt2id(rt reflect.Type) uintptr {
|
||||
return reflect.ValueOf(rt).Pointer()
|
||||
}
|
||||
|
||||
func i2rtid(i interface{}) uintptr {
|
||||
return reflect.ValueOf(reflect.TypeOf(i)).Pointer()
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
|
||||
func isEmptyValue(v reflect.Value, tinfos *TypeInfos, recursive bool) bool {
|
||||
switch v.Kind() {
|
||||
case reflect.Invalid:
|
||||
return true
|
||||
case reflect.Array, reflect.String:
|
||||
return v.Len() == 0
|
||||
case reflect.Map, reflect.Slice, reflect.Chan:
|
||||
return v.IsNil() || v.Len() == 0
|
||||
case reflect.Bool:
|
||||
return !v.Bool()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return v.Int() == 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return v.Uint() == 0
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
c := v.Complex()
|
||||
return math.Float64bits(real(c)) == 0 && math.Float64bits(imag(c)) == 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v.Float() == 0
|
||||
case reflect.Func, reflect.UnsafePointer:
|
||||
return v.IsNil()
|
||||
case reflect.Interface, reflect.Ptr:
|
||||
isnil := v.IsNil()
|
||||
if recursive && !isnil {
|
||||
return isEmptyValue(v.Elem(), tinfos, recursive)
|
||||
}
|
||||
return isnil
|
||||
case reflect.Struct:
|
||||
return isEmptyStruct(v, tinfos, recursive)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// isEmptyStruct is only called from isEmptyValue, and checks if a struct is empty:
|
||||
// - does it implement IsZero() bool
|
||||
// - is it comparable, and can i compare directly using ==
|
||||
// - if checkStruct, then walk through the encodable fields
|
||||
// and check if they are empty or not.
|
||||
func isEmptyStruct(v reflect.Value, tinfos *TypeInfos, recursive bool) bool {
|
||||
// v is a struct kind - no need to check again.
|
||||
// We only check isZero on a struct kind, to reduce the amount of times
|
||||
// that we lookup the rtid and typeInfo for each type as we walk the tree.
|
||||
|
||||
vt := rvType(v)
|
||||
rtid := rt2id(vt)
|
||||
if tinfos == nil {
|
||||
tinfos = defTypeInfos
|
||||
}
|
||||
ti := tinfos.get(rtid, vt)
|
||||
if ti.rtid == timeTypId {
|
||||
return rv2i(v).(time.Time).IsZero()
|
||||
}
|
||||
if ti.flagIsZeroer {
|
||||
return rv2i(v).(isZeroer).IsZero()
|
||||
}
|
||||
if ti.flagIsZeroerPtr && v.CanAddr() {
|
||||
return rv2i(v.Addr()).(isZeroer).IsZero()
|
||||
}
|
||||
if ti.flagIsCodecEmptyer {
|
||||
return rv2i(v).(isCodecEmptyer).IsCodecEmpty()
|
||||
}
|
||||
if ti.flagIsCodecEmptyerPtr && v.CanAddr() {
|
||||
return rv2i(v.Addr()).(isCodecEmptyer).IsCodecEmpty()
|
||||
}
|
||||
if ti.flagComparable {
|
||||
return rv2i(v) == rv2i(rvZeroK(vt, reflect.Struct))
|
||||
}
|
||||
if !recursive {
|
||||
return false
|
||||
}
|
||||
// We only care about what we can encode/decode,
|
||||
// so that is what we use to check omitEmpty.
|
||||
for _, si := range ti.sfiSrc {
|
||||
sfv := si.path.field(v)
|
||||
if sfv.IsValid() && !isEmptyValue(sfv, tinfos, recursive) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
type atomicClsErr struct {
|
||||
v atomic.Value
|
||||
}
|
||||
|
||||
func (x *atomicClsErr) load() (e clsErr) {
|
||||
if i := x.v.Load(); i != nil {
|
||||
e = i.(clsErr)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
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 {
|
||||
return reflect.ValueOf(&n.u).Elem()
|
||||
}
|
||||
func (n *fauxUnion) ri() reflect.Value {
|
||||
return reflect.ValueOf(&n.i).Elem()
|
||||
}
|
||||
func (n *fauxUnion) rf() reflect.Value {
|
||||
return reflect.ValueOf(&n.f).Elem()
|
||||
}
|
||||
func (n *fauxUnion) rl() reflect.Value {
|
||||
return reflect.ValueOf(&n.l).Elem()
|
||||
}
|
||||
func (n *fauxUnion) rs() reflect.Value {
|
||||
return reflect.ValueOf(&n.s).Elem()
|
||||
}
|
||||
func (n *fauxUnion) rt() reflect.Value {
|
||||
return reflect.ValueOf(&n.t).Elem()
|
||||
}
|
||||
func (n *fauxUnion) rb() reflect.Value {
|
||||
return reflect.ValueOf(&n.b).Elem()
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
func rvSetBytes(rv reflect.Value, v []byte) {
|
||||
rv.SetBytes(v)
|
||||
}
|
||||
|
||||
func rvSetString(rv reflect.Value, v string) {
|
||||
rv.SetString(v)
|
||||
}
|
||||
|
||||
func rvSetBool(rv reflect.Value, v bool) {
|
||||
rv.SetBool(v)
|
||||
}
|
||||
|
||||
func rvSetTime(rv reflect.Value, v time.Time) {
|
||||
rv.Set(reflect.ValueOf(v))
|
||||
}
|
||||
|
||||
func rvSetFloat32(rv reflect.Value, v float32) {
|
||||
rv.SetFloat(float64(v))
|
||||
}
|
||||
|
||||
func rvSetFloat64(rv reflect.Value, v float64) {
|
||||
rv.SetFloat(v)
|
||||
}
|
||||
|
||||
func rvSetComplex64(rv reflect.Value, v complex64) {
|
||||
rv.SetComplex(complex128(v))
|
||||
}
|
||||
|
||||
func rvSetComplex128(rv reflect.Value, v complex128) {
|
||||
rv.SetComplex(v)
|
||||
}
|
||||
|
||||
func rvSetInt(rv reflect.Value, v int) {
|
||||
rv.SetInt(int64(v))
|
||||
}
|
||||
|
||||
func rvSetInt8(rv reflect.Value, v int8) {
|
||||
rv.SetInt(int64(v))
|
||||
}
|
||||
|
||||
func rvSetInt16(rv reflect.Value, v int16) {
|
||||
rv.SetInt(int64(v))
|
||||
}
|
||||
|
||||
func rvSetInt32(rv reflect.Value, v int32) {
|
||||
rv.SetInt(int64(v))
|
||||
}
|
||||
|
||||
func rvSetInt64(rv reflect.Value, v int64) {
|
||||
rv.SetInt(v)
|
||||
}
|
||||
|
||||
func rvSetUint(rv reflect.Value, v uint) {
|
||||
rv.SetUint(uint64(v))
|
||||
}
|
||||
|
||||
func rvSetUintptr(rv reflect.Value, v uintptr) {
|
||||
rv.SetUint(uint64(v))
|
||||
}
|
||||
|
||||
func rvSetUint8(rv reflect.Value, v uint8) {
|
||||
rv.SetUint(uint64(v))
|
||||
}
|
||||
|
||||
func rvSetUint16(rv reflect.Value, v uint16) {
|
||||
rv.SetUint(uint64(v))
|
||||
}
|
||||
|
||||
func rvSetUint32(rv reflect.Value, v uint32) {
|
||||
rv.SetUint(uint64(v))
|
||||
}
|
||||
|
||||
func rvSetUint64(rv reflect.Value, v uint64) {
|
||||
rv.SetUint(v)
|
||||
}
|
||||
|
||||
// ----------------
|
||||
|
||||
func rvSetDirect(rv reflect.Value, v reflect.Value) {
|
||||
rv.Set(v)
|
||||
}
|
||||
|
||||
func rvSetDirectZero(rv reflect.Value) {
|
||||
rv.Set(reflect.Zero(rv.Type()))
|
||||
}
|
||||
|
||||
func rvSlice(rv reflect.Value, length int) reflect.Value {
|
||||
return rv.Slice(0, length)
|
||||
}
|
||||
|
||||
func rvMakeSlice(rv reflect.Value, ti *typeInfo, xlen, xcap int) (v reflect.Value, set bool) {
|
||||
v = reflect.MakeSlice(ti.rt, xlen, xcap)
|
||||
if rv.Len() > 0 {
|
||||
reflect.Copy(v, rv)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func rvGrowSlice(rv reflect.Value, ti *typeInfo, xcap, incr int) (v reflect.Value, newcap int, set bool) {
|
||||
newcap = int(growCap(uint(xcap), uint(ti.elemsize), uint(incr)))
|
||||
v = reflect.MakeSlice(ti.rt, newcap, newcap)
|
||||
if rv.Len() > 0 {
|
||||
reflect.Copy(v, rv)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ----------------
|
||||
|
||||
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 rvSliceZeroCap(t reflect.Type) (v reflect.Value) {
|
||||
return reflect.MakeSlice(t, 0, 0)
|
||||
}
|
||||
|
||||
func rvLenSlice(rv reflect.Value) int {
|
||||
return rv.Len()
|
||||
}
|
||||
|
||||
func rvCapSlice(rv reflect.Value) int {
|
||||
return rv.Cap()
|
||||
}
|
||||
|
||||
func rvGetArrayBytes(rv reflect.Value, scratch []byte) (bs []byte) {
|
||||
l := rv.Len()
|
||||
if scratch == nil || rv.CanAddr() {
|
||||
return rv.Slice(0, l).Bytes()
|
||||
}
|
||||
|
||||
if l <= cap(scratch) {
|
||||
bs = scratch[:l]
|
||||
} else {
|
||||
bs = make([]byte, l)
|
||||
}
|
||||
reflect.Copy(reflect.ValueOf(bs), rv)
|
||||
return
|
||||
}
|
||||
|
||||
func rvGetArray4Slice(rv reflect.Value) (v reflect.Value) {
|
||||
v = rvZeroAddrK(reflectArrayOf(rvLenSlice(rv), rvType(rv).Elem()), reflect.Array)
|
||||
reflect.Copy(v, rv)
|
||||
return
|
||||
}
|
||||
|
||||
func rvGetSlice4Array(rv reflect.Value, v interface{}) {
|
||||
// v is a pointer to a slice to be populated
|
||||
|
||||
// rv.Slice fails if address is not addressable, which can occur during encoding.
|
||||
// Consequently, check if non-addressable, and if so, make new slice and copy into it first.
|
||||
// MARKER: this *may* cause allocation if non-addressable, unfortunately.
|
||||
|
||||
rve := reflect.ValueOf(v).Elem()
|
||||
l := rv.Len()
|
||||
if rv.CanAddr() {
|
||||
rve.Set(rv.Slice(0, l))
|
||||
} else {
|
||||
rvs := reflect.MakeSlice(rve.Type(), l, l)
|
||||
reflect.Copy(rvs, rv)
|
||||
rve.Set(rvs)
|
||||
}
|
||||
// reflect.ValueOf(v).Elem().Set(rv.Slice(0, rv.Len()))
|
||||
}
|
||||
|
||||
func rvCopySlice(dest, src reflect.Value) {
|
||||
reflect.Copy(dest, src)
|
||||
}
|
||||
|
||||
// ------------
|
||||
|
||||
func rvGetBool(rv reflect.Value) bool {
|
||||
return rv.Bool()
|
||||
}
|
||||
|
||||
func rvGetBytes(rv reflect.Value) []byte {
|
||||
return rv.Bytes()
|
||||
}
|
||||
|
||||
func rvGetTime(rv reflect.Value) time.Time {
|
||||
return rv2i(rv).(time.Time)
|
||||
}
|
||||
|
||||
func rvGetString(rv reflect.Value) string {
|
||||
return rv.String()
|
||||
}
|
||||
|
||||
func rvGetFloat64(rv reflect.Value) float64 {
|
||||
return rv.Float()
|
||||
}
|
||||
|
||||
func rvGetFloat32(rv reflect.Value) float32 {
|
||||
return float32(rv.Float())
|
||||
}
|
||||
|
||||
func rvGetComplex64(rv reflect.Value) complex64 {
|
||||
return complex64(rv.Complex())
|
||||
}
|
||||
|
||||
func rvGetComplex128(rv reflect.Value) complex128 {
|
||||
return rv.Complex()
|
||||
}
|
||||
|
||||
func rvGetInt(rv reflect.Value) int {
|
||||
return int(rv.Int())
|
||||
}
|
||||
|
||||
func rvGetInt8(rv reflect.Value) int8 {
|
||||
return int8(rv.Int())
|
||||
}
|
||||
|
||||
func rvGetInt16(rv reflect.Value) int16 {
|
||||
return int16(rv.Int())
|
||||
}
|
||||
|
||||
func rvGetInt32(rv reflect.Value) int32 {
|
||||
return int32(rv.Int())
|
||||
}
|
||||
|
||||
func rvGetInt64(rv reflect.Value) int64 {
|
||||
return rv.Int()
|
||||
}
|
||||
|
||||
func rvGetUint(rv reflect.Value) uint {
|
||||
return uint(rv.Uint())
|
||||
}
|
||||
|
||||
func rvGetUint8(rv reflect.Value) uint8 {
|
||||
return uint8(rv.Uint())
|
||||
}
|
||||
|
||||
func rvGetUint16(rv reflect.Value) uint16 {
|
||||
return uint16(rv.Uint())
|
||||
}
|
||||
|
||||
func rvGetUint32(rv reflect.Value) uint32 {
|
||||
return uint32(rv.Uint())
|
||||
}
|
||||
|
||||
func rvGetUint64(rv reflect.Value) uint64 {
|
||||
return rv.Uint()
|
||||
}
|
||||
|
||||
func rvGetUintptr(rv reflect.Value) uintptr {
|
||||
return uintptr(rv.Uint())
|
||||
}
|
||||
|
||||
func rvLenMap(rv reflect.Value) int {
|
||||
return rv.Len()
|
||||
}
|
||||
|
||||
// func rvLenArray(rv reflect.Value) int { return rv.Len() }
|
||||
|
||||
// ------------ map range and map indexing ----------
|
||||
|
||||
func mapGet(m, k, v reflect.Value, keyFastKind mapKeyFastKind, valIsIndirect, valIsRef bool) (vv reflect.Value) {
|
||||
return m.MapIndex(k)
|
||||
}
|
||||
|
||||
func mapSet(m, k, v reflect.Value, keyFastKind mapKeyFastKind, valIsIndirect, valIsRef bool) {
|
||||
m.SetMapIndex(k, v)
|
||||
}
|
||||
|
||||
// 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 (e *Encoder) jsondriver() *jsonEncDriver {
|
||||
return e.e.(*jsonEncDriver)
|
||||
}
|
||||
|
||||
// ---------- DECODER optimized ---------------
|
||||
|
||||
func (d *Decoder) checkBreak() bool {
|
||||
return d.d.CheckBreak()
|
||||
}
|
||||
|
||||
func (d *Decoder) jsondriver() *jsonDecDriver {
|
||||
return d.d.(*jsonDecDriver)
|
||||
}
|
||||
|
||||
// ---------- structFieldInfo optimized ---------------
|
||||
|
||||
func (n *structFieldInfoPathNode) rvField(v reflect.Value) reflect.Value {
|
||||
return v.Field(int(n.index))
|
||||
}
|
||||
|
||||
// ---------- others ---------------
|
||||
|
||||
/*
|
||||
func hashShortString(b []byte) (h uintptr) {
|
||||
// MARKER: consider fnv - it may be a better hash than adler
|
||||
return uintptr(adler32.Checksum(b))
|
||||
}
|
||||
|
||||
// func hashShortString(b []byte) (h uint64) {
|
||||
// // culled from https://github.com/golang/go/issues/32779#issuecomment-735494578
|
||||
// // Read the string in two parts using wide-integer loads.
|
||||
// // The prefix and suffix may overlap, which is fine.
|
||||
// switch {
|
||||
// case len(b) > 8:
|
||||
// h ^= binary.LittleEndian.Uint64(b[:8])
|
||||
// h *= 0x00000100000001B3 // inspired by FNV-64
|
||||
// h ^= binary.LittleEndian.Uint64(b[len(b)-8:])
|
||||
// case len(b) > 4:
|
||||
// h ^= uint64(binary.LittleEndian.Uint32(b[:4]))
|
||||
// h *= 0x01000193 // inspired by FNV-32
|
||||
// h ^= uint64(binary.LittleEndian.Uint32(b[len(b)-4:]))
|
||||
// default:
|
||||
// h ^= uint64(binary.LittleEndian.Uint16(b[:2]))
|
||||
// h *= 0x010f // inspired by hypothetical FNV-16
|
||||
// h ^= uint64(binary.LittleEndian.Uint16(b[len(b)-2:]))
|
||||
// }
|
||||
//
|
||||
// // Collapse a 64-bit, 32-bit, or 16-bit hash into an 8-bit hash.
|
||||
// h ^= h >> 32
|
||||
// h ^= h >> 16
|
||||
// h ^= h >> 8
|
||||
//
|
||||
// // The cache has 8 buckets based on the lower 3-bits of the length.
|
||||
// h = ((h << 3) | uint64(len(b)&7))
|
||||
// return
|
||||
// }
|
||||
|
||||
func rtsize(rt reflect.Type) uintptr {
|
||||
return rt.Size()
|
||||
}
|
||||
|
||||
*/
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,25 @@
|
|||
// +build !safe
|
||||
// +build !appengine
|
||||
// +build go1.9
|
||||
// +build gc
|
||||
|
||||
// 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 (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func rvType(rv reflect.Value) reflect.Type {
|
||||
return rvPtrToType(((*unsafeReflectValue)(unsafe.Pointer(&rv))).typ) // rv.Type()
|
||||
}
|
||||
|
||||
//go:linkname unsafeZeroArr runtime.zeroVal
|
||||
var unsafeZeroArr [1024]byte
|
||||
|
||||
//go:linkname rvPtrToType reflect.toType
|
||||
//go:noescape
|
||||
func rvPtrToType(typ unsafe.Pointer) reflect.Type
|
17
vendor/github.com/ugorji/go/codec/helper_unsafe_compiler_not_gc.go
generated
vendored
Normal file
17
vendor/github.com/ugorji/go/codec/helper_unsafe_compiler_not_gc.go
generated
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
// +build !safe
|
||||
// +build !appengine
|
||||
// +build go1.9
|
||||
// +build !gc
|
||||
|
||||
// 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 "reflect"
|
||||
|
||||
var unsafeZeroArr [1024]byte
|
||||
|
||||
func rvType(rv reflect.Value) reflect.Type {
|
||||
return rv.Type()
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,184 @@
|
|||
// 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.
|
||||
|
||||
// Code generated from mammoth-test.go.tmpl - DO NOT EDIT.
|
||||
|
||||
package codec
|
||||
|
||||
import "testing"
|
||||
import "fmt"
|
||||
import "reflect"
|
||||
|
||||
// TestMammoth has all the different paths optimized in fast-path
|
||||
// It has all the primitives, slices and maps.
|
||||
//
|
||||
// For each of those types, it has a pointer and a non-pointer field.
|
||||
|
||||
func init() { _ = fmt.Printf } // so we can include fmt as needed
|
||||
|
||||
type TestMammoth struct {
|
||||
|
||||
{{range .Values }}{{if .Primitive -}}
|
||||
{{ .MethodNamePfx "F" true }} {{ .Primitive }}
|
||||
{{ .MethodNamePfx "Fptr" true }} *{{ .Primitive }}
|
||||
{{end}}{{end}}
|
||||
|
||||
{{range .Values }}{{if not .Primitive }}{{if not .MapKey -}}
|
||||
{{ .MethodNamePfx "F" false }} []{{ .Elem }}
|
||||
{{ .MethodNamePfx "Fptr" false }} *[]{{ .Elem }}
|
||||
{{ .MethodNamePfx "Farr4" false }} [4]{{ .Elem }}
|
||||
{{end}}{{end}}{{end}}
|
||||
|
||||
{{range .Values }}{{if not .Primitive }}{{if .MapKey -}}
|
||||
{{ .MethodNamePfx "F" false }} map[{{ .MapKey }}]{{ .Elem }}
|
||||
{{ .MethodNamePfx "Fptr" false }} *map[{{ .MapKey }}]{{ .Elem }}
|
||||
{{end}}{{end}}{{end}}
|
||||
|
||||
}
|
||||
|
||||
{{range .Values }}{{if not .Primitive }}{{if not .MapKey -}}
|
||||
type {{ .MethodNamePfx "typMbs" false }} []{{ .Elem }}
|
||||
func (_ {{ .MethodNamePfx "typMbs" false }}) MapBySlice() { }
|
||||
{{end}}{{end}}{{end}}
|
||||
|
||||
{{range .Values }}{{if not .Primitive }}{{if .MapKey -}}
|
||||
type {{ .MethodNamePfx "typMap" false }} map[{{ .MapKey }}]{{ .Elem }}
|
||||
{{end}}{{end}}{{end}}
|
||||
|
||||
func doTestMammothSlices(t *testing.T, h Handle) {
|
||||
{{range $i, $e := .Values }}{{if not .Primitive }}{{if not .MapKey -}}
|
||||
var v{{$i}}va [8]{{ .Elem }}
|
||||
for _, v := range [][]{{ .Elem }}{ nil, {}, { {{ nonzerocmd .Elem }}, {{ zerocmd .Elem }}, {{ zerocmd .Elem }}, {{ nonzerocmd .Elem }} } } {
|
||||
{{/*
|
||||
// fmt.Printf(">>>> running mammoth slice v{{$i}}: %v\n", v)
|
||||
// - encode value to some []byte
|
||||
// - decode into a length-wise-equal []byte
|
||||
// - check if equal to initial slice
|
||||
// - encode ptr to the value
|
||||
// - check if encode bytes are same
|
||||
// - decode into ptrs to: nil, then 1-elem slice, equal-length, then large len slice
|
||||
// - decode into non-addressable slice of equal length, then larger len
|
||||
// - for each decode, compare elem-by-elem to the original slice
|
||||
// -
|
||||
// - rinse and repeat for a MapBySlice version
|
||||
// -
|
||||
*/ -}}
|
||||
var v{{$i}}v1, v{{$i}}v2 []{{ .Elem }}
|
||||
var bs{{$i}} []byte
|
||||
v{{$i}}v1 = v
|
||||
bs{{$i}} = testMarshalErr(v{{$i}}v1, h, t, "enc-slice-v{{$i}}")
|
||||
if v == nil {
|
||||
v{{$i}}v2 = make([]{{ .Elem }}, 2)
|
||||
testUnmarshalErr(v{{$i}}v2, bs{{$i}}, h, t, "dec-slice-v{{$i}}")
|
||||
testDeepEqualErr(v{{$i}}v2[0], v{{$i}}v2[1], t, "equal-slice-v{{$i}}") // should not change
|
||||
testDeepEqualErr(len(v{{$i}}v2), 2, t, "equal-slice-v{{$i}}") // should not change
|
||||
v{{$i}}v2 = make([]{{ .Elem }}, 2)
|
||||
testUnmarshalErr(reflect.ValueOf(v{{$i}}v2), bs{{$i}}, h, t, "dec-slice-v{{$i}}-noaddr") // non-addressable value
|
||||
testDeepEqualErr(v{{$i}}v2[0], v{{$i}}v2[1], t, "equal-slice-v{{$i}}-noaddr") // should not change
|
||||
testDeepEqualErr(len(v{{$i}}v2), 2, t, "equal-slice-v{{$i}}") // should not change
|
||||
} else {
|
||||
v{{$i}}v2 = make([]{{ .Elem }}, len(v))
|
||||
testUnmarshalErr(v{{$i}}v2, bs{{$i}}, h, t, "dec-slice-v{{$i}}")
|
||||
testDeepEqualErr(v{{$i}}v1, v{{$i}}v2, t, "equal-slice-v{{$i}}")
|
||||
v{{$i}}v2 = make([]{{ .Elem }}, len(v))
|
||||
testUnmarshalErr(reflect.ValueOf(v{{$i}}v2), bs{{$i}}, h, t, "dec-slice-v{{$i}}-noaddr") // non-addressable value
|
||||
testDeepEqualErr(v{{$i}}v1, v{{$i}}v2, t, "equal-slice-v{{$i}}-noaddr")
|
||||
}
|
||||
testReleaseBytes(bs{{$i}})
|
||||
// ...
|
||||
bs{{$i}} = testMarshalErr(&v{{$i}}v1, h, t, "enc-slice-v{{$i}}-p")
|
||||
v{{$i}}v2 = nil
|
||||
testUnmarshalErr(&v{{$i}}v2, bs{{$i}}, h, t, "dec-slice-v{{$i}}-p")
|
||||
testDeepEqualErr(v{{$i}}v1, v{{$i}}v2, t, "equal-slice-v{{$i}}-p")
|
||||
v{{$i}}va = [8]{{ .Elem }}{} // clear the array
|
||||
testUnmarshalErr(&v{{$i}}va, bs{{$i}}, h, t, "dec-array-v{{$i}}-p-1")
|
||||
if v{{$i}}v1 == nil && v{{$i}}v2 == nil { v{{$i}}v2 = []{{ .Elem }}{} } // so we can compare to zero len slice below
|
||||
testDeepEqualErr(v{{$i}}va[:len(v{{$i}}v2)], v{{$i}}v2, t, "equal-array-v{{$i}}-p-1")
|
||||
v{{$i}}va = [8]{{ .Elem }}{} // clear the array
|
||||
v{{$i}}v2 = v{{$i}}va[:1:1]
|
||||
testUnmarshalErr(&v{{$i}}v2, bs{{$i}}, h, t, "dec-slice-v{{$i}}-p-1")
|
||||
testDeepEqualErr(v{{$i}}v1, v{{$i}}v2, t, "equal-slice-v{{$i}}-p-1")
|
||||
v{{$i}}va = [8]{{ .Elem }}{} // clear the array
|
||||
v{{$i}}v2 = v{{$i}}va[:len(v{{$i}}v1):len(v{{$i}}v1)]
|
||||
testUnmarshalErr(&v{{$i}}v2, bs{{$i}}, h, t, "dec-slice-v{{$i}}-p-len")
|
||||
testDeepEqualErr(v{{$i}}v1, v{{$i}}v2, t, "equal-slice-v{{$i}}-p-len")
|
||||
v{{$i}}va = [8]{{ .Elem }}{} // clear the array
|
||||
v{{$i}}v2 = v{{$i}}va[:]
|
||||
testUnmarshalErr(&v{{$i}}v2, bs{{$i}}, h, t, "dec-slice-v{{$i}}-p-cap")
|
||||
testDeepEqualErr(v{{$i}}v1, v{{$i}}v2, t, "equal-slice-v{{$i}}-p-cap")
|
||||
if len(v{{$i}}v1) > 1 {
|
||||
v{{$i}}va = [8]{{ .Elem }}{} // clear the array
|
||||
testUnmarshalErr((&v{{$i}}va)[:len(v{{$i}}v1)], bs{{$i}}, h, t, "dec-slice-v{{$i}}-p-len-noaddr")
|
||||
testDeepEqualErr(v{{$i}}v1, v{{$i}}va[:len(v{{$i}}v1)], t, "equal-slice-v{{$i}}-p-len-noaddr")
|
||||
v{{$i}}va = [8]{{ .Elem }}{} // clear the array
|
||||
testUnmarshalErr((&v{{$i}}va)[:], bs{{$i}}, h, t, "dec-slice-v{{$i}}-p-cap-noaddr")
|
||||
testDeepEqualErr(v{{$i}}v1, v{{$i}}va[:len(v{{$i}}v1)], t, "equal-slice-v{{$i}}-p-cap-noaddr")
|
||||
}
|
||||
testReleaseBytes(bs{{$i}})
|
||||
// ...
|
||||
var v{{$i}}v3, v{{$i}}v4 {{ .MethodNamePfx "typMbs" false }}
|
||||
v{{$i}}v2 = nil
|
||||
if v != nil { v{{$i}}v2 = make([]{{ .Elem }}, len(v)) }
|
||||
v{{$i}}v3 = {{ .MethodNamePfx "typMbs" false }}(v{{$i}}v1)
|
||||
v{{$i}}v4 = {{ .MethodNamePfx "typMbs" false }}(v{{$i}}v2)
|
||||
if v != nil {
|
||||
bs{{$i}} = testMarshalErr(v{{$i}}v3, h, t, "enc-slice-v{{$i}}-custom")
|
||||
testUnmarshalErr(v{{$i}}v4, bs{{$i}}, h, t, "dec-slice-v{{$i}}-custom")
|
||||
testDeepEqualErr(v{{$i}}v3, v{{$i}}v4, t, "equal-slice-v{{$i}}-custom")
|
||||
testReleaseBytes(bs{{$i}})
|
||||
}
|
||||
bs{{$i}} = testMarshalErr(&v{{$i}}v3, h, t, "enc-slice-v{{$i}}-custom-p")
|
||||
v{{$i}}v2 = nil
|
||||
v{{$i}}v4 = {{ .MethodNamePfx "typMbs" false }}(v{{$i}}v2)
|
||||
testUnmarshalErr(&v{{$i}}v4, bs{{$i}}, h, t, "dec-slice-v{{$i}}-custom-p")
|
||||
testDeepEqualErr(v{{$i}}v3, v{{$i}}v4, t, "equal-slice-v{{$i}}-custom-p")
|
||||
testReleaseBytes(bs{{$i}})
|
||||
}
|
||||
{{end}}{{end}}{{end}}
|
||||
}
|
||||
|
||||
func doTestMammothMaps(t *testing.T, h Handle) {
|
||||
{{range $i, $e := .Values }}{{if not .Primitive }}{{if .MapKey -}}
|
||||
for _, v := range []map[{{ .MapKey }}]{{ .Elem }}{ nil, {}, { {{ nonzerocmd .MapKey }}:{{ zerocmd .Elem }} {{if ne "bool" .MapKey}}, {{ nonzerocmd .MapKey }}:{{ nonzerocmd .Elem }} {{end}} } } {
|
||||
// fmt.Printf(">>>> running mammoth map v{{$i}}: %v\n", v)
|
||||
var v{{$i}}v1, v{{$i}}v2 map[{{ .MapKey }}]{{ .Elem }}
|
||||
var bs{{$i}} []byte
|
||||
v{{$i}}v1 = v
|
||||
bs{{$i}} = testMarshalErr(v{{$i}}v1, h, t, "enc-map-v{{$i}}")
|
||||
if v != nil {
|
||||
if v == nil { v{{$i}}v2 = nil } else { v{{$i}}v2 = make(map[{{ .MapKey }}]{{ .Elem }}, len(v)) } // reset map
|
||||
testUnmarshalErr(v{{$i}}v2, bs{{$i}}, h, t, "dec-map-v{{$i}}")
|
||||
testDeepEqualErr(v{{$i}}v1, v{{$i}}v2, t, "equal-map-v{{$i}}")
|
||||
if v == nil { v{{$i}}v2 = nil } else { v{{$i}}v2 = make(map[{{ .MapKey }}]{{ .Elem }}, len(v)) } // reset map
|
||||
testUnmarshalErr(reflect.ValueOf(v{{$i}}v2), bs{{$i}}, h, t, "dec-map-v{{$i}}-noaddr") // decode into non-addressable map value
|
||||
testDeepEqualErr(v{{$i}}v1, v{{$i}}v2, t, "equal-map-v{{$i}}-noaddr")
|
||||
}
|
||||
if v == nil { v{{$i}}v2 = nil } else { v{{$i}}v2 = make(map[{{ .MapKey }}]{{ .Elem }}, len(v)) } // reset map
|
||||
testUnmarshalErr(&v{{$i}}v2, bs{{$i}}, h, t, "dec-map-v{{$i}}-p-len")
|
||||
testDeepEqualErr(v{{$i}}v1, v{{$i}}v2, t, "equal-map-v{{$i}}-p-len")
|
||||
testReleaseBytes(bs{{$i}})
|
||||
bs{{$i}} = testMarshalErr(&v{{$i}}v1, h, t, "enc-map-v{{$i}}-p")
|
||||
v{{$i}}v2 = nil
|
||||
testUnmarshalErr(&v{{$i}}v2, bs{{$i}}, h, t, "dec-map-v{{$i}}-p-nil")
|
||||
testDeepEqualErr(v{{$i}}v1, v{{$i}}v2, t, "equal-map-v{{$i}}-p-nil")
|
||||
testReleaseBytes(bs{{$i}})
|
||||
// ...
|
||||
if v == nil { v{{$i}}v2 = nil } else { v{{$i}}v2 = make(map[{{ .MapKey }}]{{ .Elem }}, len(v)) } // reset map
|
||||
var v{{$i}}v3, v{{$i}}v4 {{ .MethodNamePfx "typMap" false }}
|
||||
v{{$i}}v3 = {{ .MethodNamePfx "typMap" false }}(v{{$i}}v1)
|
||||
v{{$i}}v4 = {{ .MethodNamePfx "typMap" false }}(v{{$i}}v2)
|
||||
if v != nil {
|
||||
bs{{$i}} = testMarshalErr(v{{$i}}v3, h, t, "enc-map-v{{$i}}-custom")
|
||||
testUnmarshalErr(v{{$i}}v4, bs{{$i}}, h, t, "dec-map-v{{$i}}-p-len")
|
||||
testDeepEqualErr(v{{$i}}v3, v{{$i}}v4, t, "equal-map-v{{$i}}-p-len")
|
||||
testReleaseBytes(bs{{$i}})
|
||||
}
|
||||
}
|
||||
{{end}}{{end}}{{end}}
|
||||
|
||||
}
|
||||
|
||||
func doTestMammothMapsAndSlices(t *testing.T, h Handle) {
|
||||
doTestMammothSlices(t, h)
|
||||
doTestMammothMaps(t, h)
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
// +build !notfastpath
|
||||
|
||||
// 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.
|
||||
|
||||
// Code generated from mammoth2-test.go.tmpl - DO NOT EDIT.
|
||||
|
||||
package codec
|
||||
|
||||
// Increase codecoverage by covering all the codecgen paths, in fast-path and gen-helper.go....
|
||||
//
|
||||
// Add:
|
||||
// - test file for creating a mammoth generated file as _mammoth_generated.go
|
||||
// - generate a second mammoth files in a different file: mammoth2_generated_test.go
|
||||
// - mammoth-test.go.tmpl will do this
|
||||
// - run codecgen on it, into mammoth2_codecgen_generated_test.go (no build tags)
|
||||
// - as part of TestMammoth, run it also
|
||||
// - this will cover all the codecgen, gen-helper, etc in one full run
|
||||
// - check in mammoth* files into github also
|
||||
// - then
|
||||
//
|
||||
// Now, add some types:
|
||||
// - some that implement BinaryMarshal, TextMarshal, JSONMarshal, and one that implements none of it
|
||||
// - create a wrapper type that includes TestMammoth2, with it in slices, and maps, and the custom types
|
||||
// - this wrapper object is what we work encode/decode (so that the codecgen methods are called)
|
||||
|
||||
|
||||
// import "encoding/binary"
|
||||
import "fmt"
|
||||
|
||||
type TestMammoth2 struct {
|
||||
|
||||
{{range .Values }}{{if .Primitive }}{{/*
|
||||
*/}}{{ .MethodNamePfx "F" true }} {{ .Primitive }}
|
||||
{{ .MethodNamePfx "Fptr" true }} *{{ .Primitive }}
|
||||
{{end}}{{end}}
|
||||
|
||||
{{range .Values }}{{if not .Primitive }}{{if not .MapKey }}{{/*
|
||||
*/}}{{ .MethodNamePfx "F" false }} []{{ .Elem }}
|
||||
{{ .MethodNamePfx "Fptr" false }} *[]{{ .Elem }}
|
||||
{{end}}{{end}}{{end}}
|
||||
|
||||
{{range .Values }}{{if not .Primitive }}{{if .MapKey }}{{/*
|
||||
*/}}{{ .MethodNamePfx "F" false }} map[{{ .MapKey }}]{{ .Elem }}
|
||||
{{ .MethodNamePfx "Fptr" false }} *map[{{ .MapKey }}]{{ .Elem }}
|
||||
{{end}}{{end}}{{end}}
|
||||
|
||||
}
|
||||
|
||||
// -----------
|
||||
|
||||
type testMammoth2Binary uint64
|
||||
func (x testMammoth2Binary) MarshalBinary() (data []byte, err error) {
|
||||
data = make([]byte, 8)
|
||||
bigenstd.PutUint64(data, uint64(x))
|
||||
return
|
||||
}
|
||||
func (x *testMammoth2Binary) UnmarshalBinary(data []byte) (err error) {
|
||||
*x = testMammoth2Binary(bigenstd.Uint64(data))
|
||||
return
|
||||
}
|
||||
|
||||
type testMammoth2Text uint64
|
||||
func (x testMammoth2Text) MarshalText() (data []byte, err error) {
|
||||
data = []byte(fmt.Sprintf("%b", uint64(x)))
|
||||
return
|
||||
}
|
||||
func (x *testMammoth2Text) UnmarshalText(data []byte) (err error) {
|
||||
_, err = fmt.Sscanf(string(data), "%b", (*uint64)(x))
|
||||
return
|
||||
}
|
||||
|
||||
type testMammoth2Json uint64
|
||||
func (x testMammoth2Json) MarshalJSON() (data []byte, err error) {
|
||||
data = []byte(fmt.Sprintf("%v", uint64(x)))
|
||||
return
|
||||
}
|
||||
func (x *testMammoth2Json) UnmarshalJSON(data []byte) (err error) {
|
||||
_, err = fmt.Sscanf(string(data), "%v", (*uint64)(x))
|
||||
return
|
||||
}
|
||||
|
||||
type testMammoth2Basic [4]uint64
|
||||
|
||||
type TestMammoth2Wrapper struct {
|
||||
V TestMammoth2
|
||||
T testMammoth2Text
|
||||
B testMammoth2Binary
|
||||
J testMammoth2Json
|
||||
C testMammoth2Basic
|
||||
M map[testMammoth2Basic]TestMammoth2
|
||||
L []TestMammoth2
|
||||
A [4]int64
|
||||
|
||||
Tcomplex128 complex128
|
||||
Tcomplex64 complex64
|
||||
Tbytes []uint8
|
||||
Tpbytes *[]uint8
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,213 +0,0 @@
|
|||
// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
|
||||
// Use of this source code is governed by a MIT license found in the LICENSE file.
|
||||
|
||||
package codec
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
// NoopHandle returns a no-op handle. It basically does nothing.
|
||||
// It is only useful for benchmarking, as it gives an idea of the
|
||||
// overhead from the codec framework.
|
||||
//
|
||||
// LIBRARY USERS: *** DO NOT USE ***
|
||||
func NoopHandle(slen int) *noopHandle {
|
||||
h := noopHandle{}
|
||||
h.rand = rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
h.B = make([][]byte, slen)
|
||||
h.S = make([]string, slen)
|
||||
for i := 0; i < len(h.S); i++ {
|
||||
b := make([]byte, i+1)
|
||||
for j := 0; j < len(b); j++ {
|
||||
b[j] = 'a' + byte(i)
|
||||
}
|
||||
h.B[i] = b
|
||||
h.S[i] = string(b)
|
||||
}
|
||||
return &h
|
||||
}
|
||||
|
||||
// noopHandle does nothing.
|
||||
// It is used to simulate the overhead of the codec framework.
|
||||
type noopHandle struct {
|
||||
BasicHandle
|
||||
binaryEncodingType
|
||||
noopDrv // noopDrv is unexported here, so we can get a copy of it when needed.
|
||||
}
|
||||
|
||||
type noopDrv struct {
|
||||
d *Decoder
|
||||
e *Encoder
|
||||
i int
|
||||
S []string
|
||||
B [][]byte
|
||||
mks []bool // stack. if map (true), else if array (false)
|
||||
mk bool // top of stack. what container are we on? map or array?
|
||||
ct valueType // last response for IsContainerType.
|
||||
cb int // counter for ContainerType
|
||||
rand *rand.Rand
|
||||
}
|
||||
|
||||
func (h *noopDrv) r(v int) int { return h.rand.Intn(v) }
|
||||
func (h *noopDrv) m(v int) int { h.i++; return h.i % v }
|
||||
|
||||
func (h *noopDrv) newEncDriver(e *Encoder) encDriver { h.e = e; return h }
|
||||
func (h *noopDrv) newDecDriver(d *Decoder) decDriver { h.d = d; return h }
|
||||
|
||||
func (h *noopDrv) reset() {}
|
||||
func (h *noopDrv) uncacheRead() {}
|
||||
|
||||
// --- encDriver
|
||||
|
||||
// stack functions (for map and array)
|
||||
func (h *noopDrv) start(b bool) {
|
||||
// println("start", len(h.mks)+1)
|
||||
h.mks = append(h.mks, b)
|
||||
h.mk = b
|
||||
}
|
||||
func (h *noopDrv) end() {
|
||||
// println("end: ", len(h.mks)-1)
|
||||
h.mks = h.mks[:len(h.mks)-1]
|
||||
if len(h.mks) > 0 {
|
||||
h.mk = h.mks[len(h.mks)-1]
|
||||
} else {
|
||||
h.mk = false
|
||||
}
|
||||
}
|
||||
|
||||
func (h *noopDrv) EncodeBuiltin(rt uintptr, v interface{}) {}
|
||||
func (h *noopDrv) EncodeNil() {}
|
||||
func (h *noopDrv) EncodeInt(i int64) {}
|
||||
func (h *noopDrv) EncodeUint(i uint64) {}
|
||||
func (h *noopDrv) EncodeBool(b bool) {}
|
||||
func (h *noopDrv) EncodeFloat32(f float32) {}
|
||||
func (h *noopDrv) EncodeFloat64(f float64) {}
|
||||
func (h *noopDrv) EncodeRawExt(re *RawExt, e *Encoder) {}
|
||||
func (h *noopDrv) EncodeArrayStart(length int) { h.start(true) }
|
||||
func (h *noopDrv) EncodeMapStart(length int) { h.start(false) }
|
||||
func (h *noopDrv) EncodeEnd() { h.end() }
|
||||
|
||||
func (h *noopDrv) EncodeString(c charEncoding, v string) {}
|
||||
func (h *noopDrv) EncodeSymbol(v string) {}
|
||||
func (h *noopDrv) EncodeStringBytes(c charEncoding, v []byte) {}
|
||||
|
||||
func (h *noopDrv) EncodeExt(rv interface{}, xtag uint64, ext Ext, e *Encoder) {}
|
||||
|
||||
// ---- decDriver
|
||||
func (h *noopDrv) initReadNext() {}
|
||||
func (h *noopDrv) CheckBreak() bool { return false }
|
||||
func (h *noopDrv) IsBuiltinType(rt uintptr) bool { return false }
|
||||
func (h *noopDrv) DecodeBuiltin(rt uintptr, v interface{}) {}
|
||||
func (h *noopDrv) DecodeInt(bitsize uint8) (i int64) { return int64(h.m(15)) }
|
||||
func (h *noopDrv) DecodeUint(bitsize uint8) (ui uint64) { return uint64(h.m(35)) }
|
||||
func (h *noopDrv) DecodeFloat(chkOverflow32 bool) (f float64) { return float64(h.m(95)) }
|
||||
func (h *noopDrv) DecodeBool() (b bool) { return h.m(2) == 0 }
|
||||
func (h *noopDrv) DecodeString() (s string) { return h.S[h.m(8)] }
|
||||
|
||||
// func (h *noopDrv) DecodeStringAsBytes(bs []byte) []byte { return h.DecodeBytes(bs) }
|
||||
|
||||
func (h *noopDrv) DecodeBytes(bs []byte, isstring, zerocopy bool) []byte { return h.B[h.m(len(h.B))] }
|
||||
|
||||
func (h *noopDrv) ReadEnd() { h.end() }
|
||||
|
||||
// toggle map/slice
|
||||
func (h *noopDrv) ReadMapStart() int { h.start(true); return h.m(10) }
|
||||
func (h *noopDrv) ReadArrayStart() int { h.start(false); return h.m(10) }
|
||||
|
||||
func (h *noopDrv) ContainerType() (vt valueType) {
|
||||
// return h.m(2) == 0
|
||||
// handle kStruct, which will bomb is it calls this and doesn't get back a map or array.
|
||||
// consequently, if the return value is not map or array, reset it to one of them based on h.m(7) % 2
|
||||
// for kstruct: at least one out of every 2 times, return one of valueTypeMap or Array (else kstruct bombs)
|
||||
// however, every 10th time it is called, we just return something else.
|
||||
var vals = [...]valueType{valueTypeArray, valueTypeMap}
|
||||
// ------------ TAKE ------------
|
||||
// if h.cb%2 == 0 {
|
||||
// if h.ct == valueTypeMap || h.ct == valueTypeArray {
|
||||
// } else {
|
||||
// h.ct = vals[h.m(2)]
|
||||
// }
|
||||
// } else if h.cb%5 == 0 {
|
||||
// h.ct = valueType(h.m(8))
|
||||
// } else {
|
||||
// h.ct = vals[h.m(2)]
|
||||
// }
|
||||
// ------------ TAKE ------------
|
||||
// if h.cb%16 == 0 {
|
||||
// h.ct = valueType(h.cb % 8)
|
||||
// } else {
|
||||
// h.ct = vals[h.cb%2]
|
||||
// }
|
||||
h.ct = vals[h.cb%2]
|
||||
h.cb++
|
||||
return h.ct
|
||||
|
||||
// if h.ct == valueTypeNil || h.ct == valueTypeString || h.ct == valueTypeBytes {
|
||||
// return h.ct
|
||||
// }
|
||||
// return valueTypeUnset
|
||||
// TODO: may need to tweak this so it works.
|
||||
// if h.ct == valueTypeMap && vt == valueTypeArray || h.ct == valueTypeArray && vt == valueTypeMap {
|
||||
// h.cb = !h.cb
|
||||
// h.ct = vt
|
||||
// return h.cb
|
||||
// }
|
||||
// // go in a loop and check it.
|
||||
// h.ct = vt
|
||||
// h.cb = h.m(7) == 0
|
||||
// return h.cb
|
||||
}
|
||||
func (h *noopDrv) TryDecodeAsNil() bool {
|
||||
if h.mk {
|
||||
return false
|
||||
} else {
|
||||
return h.m(8) == 0
|
||||
}
|
||||
}
|
||||
func (h *noopDrv) DecodeExt(rv interface{}, xtag uint64, ext Ext) uint64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (h *noopDrv) DecodeNaked() {
|
||||
// use h.r (random) not h.m() because h.m() could cause the same value to be given.
|
||||
var sk int
|
||||
if h.mk {
|
||||
// if mapkey, do not support values of nil OR bytes, array, map or rawext
|
||||
sk = h.r(7) + 1
|
||||
} else {
|
||||
sk = h.r(12)
|
||||
}
|
||||
n := &h.d.n
|
||||
switch sk {
|
||||
case 0:
|
||||
n.v = valueTypeNil
|
||||
case 1:
|
||||
n.v, n.b = valueTypeBool, false
|
||||
case 2:
|
||||
n.v, n.b = valueTypeBool, true
|
||||
case 3:
|
||||
n.v, n.i = valueTypeInt, h.DecodeInt(64)
|
||||
case 4:
|
||||
n.v, n.u = valueTypeUint, h.DecodeUint(64)
|
||||
case 5:
|
||||
n.v, n.f = valueTypeFloat, h.DecodeFloat(true)
|
||||
case 6:
|
||||
n.v, n.f = valueTypeFloat, h.DecodeFloat(false)
|
||||
case 7:
|
||||
n.v, n.s = valueTypeString, h.DecodeString()
|
||||
case 8:
|
||||
n.v, n.l = valueTypeBytes, h.B[h.m(len(h.B))]
|
||||
case 9:
|
||||
n.v = valueTypeArray
|
||||
case 10:
|
||||
n.v = valueTypeMap
|
||||
default:
|
||||
n.v = valueTypeExt
|
||||
n.u = h.DecodeUint(64)
|
||||
n.l = h.B[h.m(len(h.B))]
|
||||
}
|
||||
h.ct = n.v
|
||||
return
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
package codec
|
||||
|
||||
//go:generate bash prebuild.sh
|
|
@ -1,199 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# _needgen is a helper function to tell if we need to generate files for msgp, codecgen.
|
||||
_needgen() {
|
||||
local a="$1"
|
||||
zneedgen=0
|
||||
if [[ ! -e "$a" ]]
|
||||
then
|
||||
zneedgen=1
|
||||
echo 1
|
||||
return 0
|
||||
fi
|
||||
for i in `ls -1 *.go.tmpl gen.go values_test.go`
|
||||
do
|
||||
if [[ "$a" -ot "$i" ]]
|
||||
then
|
||||
zneedgen=1
|
||||
echo 1
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
echo 0
|
||||
}
|
||||
|
||||
# _build generates fast-path.go and gen-helper.go.
|
||||
#
|
||||
# It is needed because there is some dependency between the generated code
|
||||
# and the other classes. Consequently, we have to totally remove the
|
||||
# generated files and put stubs in place, before calling "go run" again
|
||||
# to recreate them.
|
||||
_build() {
|
||||
if ! [[ "${zforce}" == "1" ||
|
||||
"1" == $( _needgen "fast-path.generated.go" ) ||
|
||||
"1" == $( _needgen "gen-helper.generated.go" ) ||
|
||||
"1" == $( _needgen "gen.generated.go" ) ||
|
||||
1 == 0 ]]
|
||||
then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# echo "Running prebuild"
|
||||
if [ "${zbak}" == "1" ]
|
||||
then
|
||||
# echo "Backing up old generated files"
|
||||
_zts=`date '+%m%d%Y_%H%M%S'`
|
||||
_gg=".generated.go"
|
||||
[ -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 "safe${_gg}" ] && mv safe${_gg} safe${_gg}__${_zts}.bak
|
||||
# [ -e "unsafe${_gg}" ] && mv unsafe${_gg} unsafe${_gg}__${_zts}.bak
|
||||
else
|
||||
rm -f fast-path.generated.go gen.generated.go gen-helper.generated.go \
|
||||
*safe.generated.go *_generated_test.go *.generated_ffjson_expose.go
|
||||
fi
|
||||
|
||||
cat > gen.generated.go <<EOF
|
||||
// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
|
||||
// Use of this source code is governed by a MIT license found in the LICENSE file.
|
||||
|
||||
package codec
|
||||
|
||||
// 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
|
||||
\`
|
||||
|
||||
EOF
|
||||
|
||||
cat > gen-from-tmpl.codec.generated.go <<EOF
|
||||
package codec
|
||||
import "io"
|
||||
func GenInternalGoFile(r io.Reader, w io.Writer, safe bool) error {
|
||||
return genInternalGoFile(r, w, safe)
|
||||
}
|
||||
EOF
|
||||
|
||||
cat > gen-from-tmpl.generated.go <<EOF
|
||||
//+build ignore
|
||||
|
||||
package main
|
||||
|
||||
//import "flag"
|
||||
import "ugorji.net/codec"
|
||||
import "os"
|
||||
|
||||
func run(fnameIn, fnameOut string, safe bool) {
|
||||
fin, err := os.Open(fnameIn)
|
||||
if err != nil { panic(err) }
|
||||
defer fin.Close()
|
||||
fout, err := os.Create(fnameOut)
|
||||
if err != nil { panic(err) }
|
||||
defer fout.Close()
|
||||
err = codec.GenInternalGoFile(fin, fout, safe)
|
||||
if err != nil { panic(err) }
|
||||
}
|
||||
|
||||
func main() {
|
||||
// do not make safe/unsafe variants.
|
||||
// Instead, depend on escape analysis, and place string creation and usage appropriately.
|
||||
// run("unsafe.go.tmpl", "safe.generated.go", true)
|
||||
// run("unsafe.go.tmpl", "unsafe.generated.go", false)
|
||||
run("fast-path.go.tmpl", "fast-path.generated.go", false)
|
||||
run("gen-helper.go.tmpl", "gen-helper.generated.go", false)
|
||||
}
|
||||
|
||||
EOF
|
||||
go run -tags=notfastpath gen-from-tmpl.generated.go && \
|
||||
rm -f gen-from-tmpl.*generated.go
|
||||
}
|
||||
|
||||
_codegenerators() {
|
||||
if [[ $zforce == "1" ||
|
||||
"1" == $( _needgen "values_codecgen${zsfx}" ) ||
|
||||
"1" == $( _needgen "values_msgp${zsfx}" ) ||
|
||||
"1" == $( _needgen "values_ffjson${zsfx}" ) ||
|
||||
1 == 0 ]]
|
||||
then
|
||||
# codecgen creates some temporary files in the directory (main, pkg).
|
||||
# Consequently, we should start msgp and ffjson first, and also put a small time latency before
|
||||
# starting codecgen.
|
||||
# Without this, ffjson chokes on one of the temporary files from codecgen.
|
||||
if [[ $zexternal == "1" ]]
|
||||
then
|
||||
echo "ffjson ... " && \
|
||||
ffjson -w values_ffjson${zsfx} $zfin &
|
||||
zzzIdFF=$!
|
||||
echo "msgp ... " && \
|
||||
msgp -tests=false -o=values_msgp${zsfx} -file=$zfin &
|
||||
zzzIdMsgp=$!
|
||||
|
||||
sleep 1 # give ffjson and msgp some buffer time. see note above.
|
||||
fi
|
||||
|
||||
echo "codecgen - !unsafe ... " && \
|
||||
codecgen -rt codecgen -t 'x,codecgen,!unsafe' -o values_codecgen${zsfx} -d 19780 $zfin &
|
||||
zzzIdC=$!
|
||||
echo "codecgen - unsafe ... " && \
|
||||
codecgen -u -rt codecgen -t 'x,codecgen,unsafe' -o values_codecgen_unsafe${zsfx} -d 19781 $zfin &
|
||||
zzzIdCU=$!
|
||||
wait $zzzIdC $zzzIdCU $zzzIdMsgp $zzzIdFF && \
|
||||
# remove (M|Unm)arshalJSON implementations, so they don't conflict with encoding/json bench \
|
||||
if [[ $zexternal == "1" ]]
|
||||
then
|
||||
sed -i 's+ MarshalJSON(+ _MarshalJSON(+g' values_ffjson${zsfx} && \
|
||||
sed -i 's+ UnmarshalJSON(+ _UnmarshalJSON(+g' values_ffjson${zsfx}
|
||||
fi && \
|
||||
echo "generators done!" && \
|
||||
true
|
||||
fi
|
||||
}
|
||||
|
||||
# _init reads the arguments and sets up the flags
|
||||
_init() {
|
||||
OPTIND=1
|
||||
while getopts "fbx" flag
|
||||
do
|
||||
case "x$flag" in
|
||||
'xf') zforce=1;;
|
||||
'xb') zbak=1;;
|
||||
'xx') zexternal=1;;
|
||||
*) echo "prebuild.sh accepts [-fbx] only"; return 1;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND-1))
|
||||
OPTIND=1
|
||||
}
|
||||
|
||||
# main script.
|
||||
# First ensure that this is being run from the basedir (i.e. dirname of script is .)
|
||||
if [ "." = `dirname $0` ]
|
||||
then
|
||||
zmydir=`pwd`
|
||||
zfin="test_values.generated.go"
|
||||
zsfx="_generated_test.go"
|
||||
# rm -f *_generated_test.go
|
||||
rm -f codecgen-*.go && \
|
||||
_init "$@" && \
|
||||
_build && \
|
||||
cp $zmydir/values_test.go $zmydir/$zfin && \
|
||||
_codegenerators && \
|
||||
echo prebuild done successfully
|
||||
rm -f $zmydir/$zfin
|
||||
else
|
||||
echo "Script must be run from the directory it resides in"
|
||||
fi
|
||||
|
|
@ -0,0 +1,814 @@
|
|||
// 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"
|
||||
|
||||
// decReader abstracts the reading source, allowing implementations that can
|
||||
// read from an io.Reader or directly off a byte slice with zero-copying.
|
||||
type decReader interface {
|
||||
// readx will use the implementation scratch buffer if possible i.e. n < len(scratchbuf), OR
|
||||
// just return a view of the []byte being decoded from.
|
||||
readx(n uint) []byte
|
||||
readb([]byte)
|
||||
|
||||
readn1() byte
|
||||
readn2() [2]byte
|
||||
readn3() [3]byte
|
||||
readn4() [4]byte
|
||||
readn8() [8]byte
|
||||
// readn1eof() (v uint8, eof bool)
|
||||
|
||||
// // read up to 8 bytes at a time
|
||||
// readn(num uint8) (v [8]byte)
|
||||
|
||||
numread() uint // number of bytes read
|
||||
|
||||
// readNumber(includeLastByteRead bool) []byte
|
||||
|
||||
// skip any whitespace characters, and return the first non-matching byte
|
||||
skipWhitespace() (token byte)
|
||||
|
||||
// jsonReadNum will include last read byte in first element of slice,
|
||||
// and continue numeric characters until it sees a non-numeric char
|
||||
// or EOF. If it sees a non-numeric character, it will unread that.
|
||||
jsonReadNum() []byte
|
||||
|
||||
// jsonReadAsisChars will read json plain characters (anything but " or \)
|
||||
// and return a slice terminated by a non-json asis character.
|
||||
jsonReadAsisChars() []byte
|
||||
|
||||
// skip will skip any byte that matches, and return the first non-matching byte
|
||||
// skip(accept *bitset256) (token byte)
|
||||
|
||||
// readTo will read any byte that matches, stopping once no-longer matching.
|
||||
// readTo(accept *bitset256) (out []byte)
|
||||
|
||||
// readUntil will read, only stopping once it matches the 'stop' byte (which it excludes).
|
||||
readUntil(stop byte) (out []byte)
|
||||
}
|
||||
|
||||
// ------------------------------------------------
|
||||
|
||||
type unreadByteStatus uint8
|
||||
|
||||
// unreadByteStatus goes from
|
||||
// undefined (when initialized) -- (read) --> canUnread -- (unread) --> canRead ...
|
||||
const (
|
||||
unreadByteUndefined unreadByteStatus = iota
|
||||
unreadByteCanRead
|
||||
unreadByteCanUnread
|
||||
)
|
||||
|
||||
// --------------------
|
||||
|
||||
type ioDecReaderCommon struct {
|
||||
r io.Reader // the reader passed in
|
||||
|
||||
n uint // num read
|
||||
|
||||
l byte // last byte
|
||||
ls unreadByteStatus // last byte status
|
||||
|
||||
b [6]byte // tiny buffer for reading single bytes
|
||||
|
||||
blist *bytesFreelist
|
||||
|
||||
bufr []byte // buffer for readTo/readUntil
|
||||
}
|
||||
|
||||
func (z *ioDecReaderCommon) reset(r io.Reader, blist *bytesFreelist) {
|
||||
z.blist = blist
|
||||
z.r = r
|
||||
z.ls = unreadByteUndefined
|
||||
z.l, z.n = 0, 0
|
||||
z.bufr = z.blist.check(z.bufr, 256)
|
||||
}
|
||||
|
||||
func (z *ioDecReaderCommon) numread() uint {
|
||||
return z.n
|
||||
}
|
||||
|
||||
// ------------------------------------------
|
||||
|
||||
// ioDecReader is a decReader that reads off an io.Reader.
|
||||
//
|
||||
// It also has a fallback implementation of ByteScanner if needed.
|
||||
type ioDecReader struct {
|
||||
ioDecReaderCommon
|
||||
|
||||
br io.ByteScanner
|
||||
|
||||
x [64 + 48]byte // for: get struct field name, swallow valueTypeBytes, etc
|
||||
}
|
||||
|
||||
func (z *ioDecReader) reset(r io.Reader, blist *bytesFreelist) {
|
||||
z.ioDecReaderCommon.reset(r, blist)
|
||||
|
||||
z.br, _ = r.(io.ByteScanner)
|
||||
}
|
||||
|
||||
func (z *ioDecReader) Read(p []byte) (n int, err error) {
|
||||
if len(p) == 0 {
|
||||
return
|
||||
}
|
||||
var firstByte bool
|
||||
if z.ls == unreadByteCanRead {
|
||||
z.ls = unreadByteCanUnread
|
||||
p[0] = z.l
|
||||
if len(p) == 1 {
|
||||
n = 1
|
||||
return
|
||||
}
|
||||
firstByte = true
|
||||
p = p[1:]
|
||||
}
|
||||
n, err = z.r.Read(p)
|
||||
if n > 0 {
|
||||
if err == io.EOF && n == len(p) {
|
||||
err = nil // read was successful, so postpone EOF (till next time)
|
||||
}
|
||||
z.l = p[n-1]
|
||||
z.ls = unreadByteCanUnread
|
||||
}
|
||||
if firstByte {
|
||||
n++
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (z *ioDecReader) ReadByte() (c byte, err error) {
|
||||
if z.br != nil {
|
||||
c, err = z.br.ReadByte()
|
||||
if err == nil {
|
||||
z.l = c
|
||||
z.ls = unreadByteCanUnread
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
n, err := z.Read(z.b[:1])
|
||||
if n == 1 {
|
||||
c = z.b[0]
|
||||
if err == io.EOF {
|
||||
err = nil // read was successful, so postpone EOF (till next time)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (z *ioDecReader) UnreadByte() (err error) {
|
||||
if z.br != nil {
|
||||
err = z.br.UnreadByte()
|
||||
if err == nil {
|
||||
z.ls = unreadByteCanRead
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
switch z.ls {
|
||||
case unreadByteCanUnread:
|
||||
z.ls = unreadByteCanRead
|
||||
case unreadByteCanRead:
|
||||
err = errDecUnreadByteLastByteNotRead
|
||||
case unreadByteUndefined:
|
||||
err = errDecUnreadByteNothingToRead
|
||||
default:
|
||||
err = errDecUnreadByteUnknown
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (z *ioDecReader) readn2() (bs [2]byte) {
|
||||
z.readb(bs[:])
|
||||
return
|
||||
}
|
||||
|
||||
func (z *ioDecReader) readn3() (bs [3]byte) {
|
||||
z.readb(bs[:])
|
||||
return
|
||||
}
|
||||
|
||||
func (z *ioDecReader) readn4() (bs [4]byte) {
|
||||
z.readb(bs[:])
|
||||
return
|
||||
}
|
||||
|
||||
func (z *ioDecReader) readn8() (bs [8]byte) {
|
||||
z.readb(bs[:])
|
||||
return
|
||||
}
|
||||
|
||||
func (z *ioDecReader) readx(n uint) (bs []byte) {
|
||||
if n == 0 {
|
||||
return
|
||||
}
|
||||
if n < uint(len(z.x)) {
|
||||
bs = z.x[:n]
|
||||
} else {
|
||||
bs = make([]byte, n)
|
||||
}
|
||||
_, err := readFull(z.r, bs)
|
||||
halt.onerror(err)
|
||||
z.n += uint(len(bs))
|
||||
return
|
||||
}
|
||||
|
||||
func (z *ioDecReader) readb(bs []byte) {
|
||||
if len(bs) == 0 {
|
||||
return
|
||||
}
|
||||
_, err := readFull(z.r, bs)
|
||||
halt.onerror(err)
|
||||
z.n += uint(len(bs))
|
||||
}
|
||||
|
||||
func (z *ioDecReader) readn1() (b uint8) {
|
||||
b, err := z.ReadByte()
|
||||
halt.onerror(err)
|
||||
z.n++
|
||||
return
|
||||
}
|
||||
|
||||
func (z *ioDecReader) readn1eof() (b uint8, eof bool) {
|
||||
b, err := z.ReadByte()
|
||||
if err == nil {
|
||||
z.n++
|
||||
} else if err == io.EOF {
|
||||
eof = true
|
||||
} else {
|
||||
halt.onerror(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (z *ioDecReader) jsonReadNum() (bs []byte) {
|
||||
z.unreadn1()
|
||||
z.bufr = z.bufr[:0]
|
||||
LOOP:
|
||||
i, eof := z.readn1eof()
|
||||
if eof {
|
||||
return z.bufr
|
||||
}
|
||||
if isNumberChar(i) {
|
||||
z.bufr = append(z.bufr, i)
|
||||
goto LOOP
|
||||
}
|
||||
z.unreadn1()
|
||||
return z.bufr
|
||||
}
|
||||
|
||||
func (z *ioDecReader) jsonReadAsisChars() (bs []byte) {
|
||||
z.bufr = z.bufr[:0]
|
||||
LOOP:
|
||||
i := z.readn1()
|
||||
z.bufr = append(z.bufr, i)
|
||||
if i == '"' || i == '\\' {
|
||||
return z.bufr
|
||||
}
|
||||
goto LOOP
|
||||
}
|
||||
|
||||
func (z *ioDecReader) skipWhitespace() (token byte) {
|
||||
LOOP:
|
||||
token = z.readn1()
|
||||
if isWhitespaceChar(token) {
|
||||
goto LOOP
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (z *ioDecReader) readUntil(stop byte) []byte {
|
||||
z.bufr = z.bufr[:0]
|
||||
LOOP:
|
||||
token := z.readn1()
|
||||
z.bufr = append(z.bufr, token)
|
||||
if token == stop {
|
||||
return z.bufr[:len(z.bufr)-1]
|
||||
}
|
||||
goto LOOP
|
||||
}
|
||||
|
||||
func (z *ioDecReader) unreadn1() {
|
||||
err := z.UnreadByte()
|
||||
halt.onerror(err)
|
||||
z.n--
|
||||
}
|
||||
|
||||
// ------------------------------------
|
||||
|
||||
type bufioDecReader struct {
|
||||
ioDecReaderCommon
|
||||
|
||||
c uint // cursor
|
||||
buf []byte
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) reset(r io.Reader, bufsize int, blist *bytesFreelist) {
|
||||
z.ioDecReaderCommon.reset(r, blist)
|
||||
z.c = 0
|
||||
if cap(z.buf) < bufsize {
|
||||
z.buf = blist.get(bufsize)
|
||||
} else {
|
||||
z.buf = z.buf[:0]
|
||||
}
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) readb(p []byte) {
|
||||
var n = uint(copy(p, z.buf[z.c:]))
|
||||
z.n += n
|
||||
z.c += n
|
||||
if len(p) != int(n) {
|
||||
z.readbFill(p, n, true, false)
|
||||
}
|
||||
}
|
||||
|
||||
func readbFillHandleErr(err error, must, eof bool) (isEOF bool) {
|
||||
if err == io.EOF {
|
||||
isEOF = true
|
||||
}
|
||||
if must && !(eof && isEOF) {
|
||||
halt.onerror(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) readbFill(p0 []byte, n uint, must, eof bool) (isEOF bool, err error) {
|
||||
// at this point, there's nothing in z.buf to read (z.buf is fully consumed)
|
||||
var p []byte
|
||||
if p0 != nil {
|
||||
p = p0[n:]
|
||||
}
|
||||
var n2 uint
|
||||
if len(p) > cap(z.buf) {
|
||||
n2, err = readFull(z.r, p)
|
||||
if err != nil {
|
||||
isEOF = readbFillHandleErr(err, must, eof)
|
||||
return
|
||||
}
|
||||
n += n2
|
||||
z.n += n2
|
||||
// always keep last byte in z.buf
|
||||
z.buf = z.buf[:1]
|
||||
z.buf[0] = p[len(p)-1]
|
||||
z.c = 1
|
||||
return
|
||||
}
|
||||
// z.c is now 0, and len(p) <= cap(z.buf)
|
||||
var n1 int
|
||||
LOOP:
|
||||
// for len(p) > 0 && z.err == nil {
|
||||
z.buf = z.buf[0:cap(z.buf)]
|
||||
n1, err = z.r.Read(z.buf)
|
||||
n2 = uint(n1)
|
||||
if n2 == 0 && err != nil {
|
||||
isEOF = readbFillHandleErr(err, must, eof)
|
||||
return
|
||||
}
|
||||
err = nil
|
||||
z.buf = z.buf[:n2]
|
||||
z.c = 0
|
||||
if len(p) > 0 {
|
||||
n2 = uint(copy(p, z.buf))
|
||||
z.c = n2
|
||||
n += n2
|
||||
z.n += n2
|
||||
p = p[n2:]
|
||||
if len(p) > 0 {
|
||||
goto LOOP
|
||||
}
|
||||
if z.c == 0 {
|
||||
z.buf = z.buf[:1]
|
||||
z.buf[0] = p[len(p)-1]
|
||||
z.c = 1
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) readn1() (b byte) {
|
||||
if z.c >= uint(len(z.buf)) {
|
||||
z.readbFill(nil, 0, true, false)
|
||||
}
|
||||
b = z.buf[z.c]
|
||||
z.c++
|
||||
z.n++
|
||||
return
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) readn1eof() (b byte, eof bool) {
|
||||
if z.c >= uint(len(z.buf)) {
|
||||
eof, _ = z.readbFill(nil, 0, true, true)
|
||||
if eof {
|
||||
return
|
||||
}
|
||||
}
|
||||
b = z.buf[z.c]
|
||||
z.c++
|
||||
z.n++
|
||||
return
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) unreadn1() {
|
||||
if z.c == 0 {
|
||||
halt.onerror(errDecUnreadByteNothingToRead)
|
||||
}
|
||||
z.c--
|
||||
z.n--
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) readn2() (bs [2]byte) {
|
||||
z.readb(bs[:])
|
||||
return
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) readn3() (bs [3]byte) {
|
||||
z.readb(bs[:])
|
||||
return
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) readn4() (bs [4]byte) {
|
||||
z.readb(bs[:])
|
||||
return
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) readn8() (bs [8]byte) {
|
||||
z.readb(bs[:])
|
||||
return
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) readx(n uint) (bs []byte) {
|
||||
if n == 0 {
|
||||
// return
|
||||
} else if z.c+n <= uint(len(z.buf)) {
|
||||
bs = z.buf[z.c : z.c+n]
|
||||
z.n += n
|
||||
z.c += n
|
||||
} else {
|
||||
bs = make([]byte, n)
|
||||
// n no longer used - can reuse
|
||||
n = uint(copy(bs, z.buf[z.c:]))
|
||||
z.n += n
|
||||
z.c += n
|
||||
z.readbFill(bs, n, true, false)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) jsonReadNum() (bs []byte) {
|
||||
z.unreadn1()
|
||||
z.bufr = z.bufr[:0]
|
||||
LOOP:
|
||||
i, eof := z.readn1eof()
|
||||
if eof {
|
||||
return z.bufr
|
||||
}
|
||||
if isNumberChar(i) {
|
||||
z.bufr = append(z.bufr, i)
|
||||
goto LOOP
|
||||
}
|
||||
z.unreadn1()
|
||||
return z.bufr
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) jsonReadAsisChars() (bs []byte) {
|
||||
z.bufr = z.bufr[:0]
|
||||
LOOP:
|
||||
i := z.readn1()
|
||||
z.bufr = append(z.bufr, i)
|
||||
if i == '"' || i == '\\' {
|
||||
return z.bufr
|
||||
}
|
||||
goto LOOP
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) skipWhitespace() (token byte) {
|
||||
i := z.c
|
||||
LOOP:
|
||||
if i < uint(len(z.buf)) {
|
||||
// inline z.skipLoopFn(i) and refactor, so cost is within inline budget
|
||||
token = z.buf[i]
|
||||
i++
|
||||
if isWhitespaceChar(token) {
|
||||
goto LOOP
|
||||
}
|
||||
z.n += i - 2 - z.c
|
||||
z.c = i
|
||||
return
|
||||
}
|
||||
return z.skipFillWhitespace()
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) skipFillWhitespace() (token byte) {
|
||||
z.n += uint(len(z.buf)) - z.c
|
||||
var i, n2 int
|
||||
var err error
|
||||
for {
|
||||
z.c = 0
|
||||
z.buf = z.buf[0:cap(z.buf)]
|
||||
n2, err = z.r.Read(z.buf)
|
||||
if n2 == 0 {
|
||||
halt.onerror(err)
|
||||
}
|
||||
z.buf = z.buf[:n2]
|
||||
for i, token = range z.buf {
|
||||
if !isWhitespaceChar(token) {
|
||||
z.n += (uint(i) - z.c) - 1
|
||||
z.loopFn(uint(i + 1))
|
||||
return
|
||||
}
|
||||
}
|
||||
z.n += uint(n2)
|
||||
}
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) loopFn(i uint) {
|
||||
z.c = i
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) readUntil(stop byte) (out []byte) {
|
||||
i := z.c
|
||||
LOOP:
|
||||
if i < uint(len(z.buf)) {
|
||||
if z.buf[i] == stop {
|
||||
z.n += (i - z.c) - 1
|
||||
i++
|
||||
out = z.buf[z.c:i]
|
||||
z.c = i
|
||||
goto FINISH
|
||||
}
|
||||
i++
|
||||
goto LOOP
|
||||
}
|
||||
out = z.readUntilFill(stop)
|
||||
FINISH:
|
||||
return out[:len(out)-1]
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) readUntilFill(stop byte) []byte {
|
||||
z.bufr = z.bufr[:0]
|
||||
z.n += uint(len(z.buf)) - z.c
|
||||
z.bufr = append(z.bufr, z.buf[z.c:]...)
|
||||
for {
|
||||
z.c = 0
|
||||
z.buf = z.buf[0:cap(z.buf)]
|
||||
n1, err := z.r.Read(z.buf)
|
||||
if n1 == 0 {
|
||||
halt.onerror(err)
|
||||
}
|
||||
n2 := uint(n1)
|
||||
z.buf = z.buf[:n2]
|
||||
for i, token := range z.buf {
|
||||
if token == stop {
|
||||
z.n += (uint(i) - z.c) - 1
|
||||
z.bufr = append(z.bufr, z.buf[z.c:i+1]...)
|
||||
z.loopFn(uint(i + 1))
|
||||
return z.bufr
|
||||
}
|
||||
}
|
||||
z.bufr = append(z.bufr, z.buf...)
|
||||
z.n += n2
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------
|
||||
|
||||
// bytesDecReader is a decReader that reads off a byte slice with zero copying
|
||||
//
|
||||
// Note: we do not try to convert index'ing out of bounds to an io.EOF.
|
||||
// instead, we let it bubble up to the exported Encode/Decode method
|
||||
// and recover it as an io.EOF.
|
||||
//
|
||||
// see panicValToErr(...) function in helper.go.
|
||||
type bytesDecReader struct {
|
||||
b []byte // data
|
||||
c uint // cursor
|
||||
}
|
||||
|
||||
func (z *bytesDecReader) reset(in []byte) {
|
||||
z.b = in[:len(in):len(in)] // reslicing must not go past capacity
|
||||
z.c = 0
|
||||
}
|
||||
|
||||
func (z *bytesDecReader) numread() uint {
|
||||
return z.c
|
||||
}
|
||||
|
||||
// Note: slicing from a non-constant start position is more expensive,
|
||||
// as more computation is required to decipher the pointer start position.
|
||||
// However, we do it only once, and it's better than reslicing both z.b and return value.
|
||||
|
||||
func (z *bytesDecReader) readx(n uint) (bs []byte) {
|
||||
x := z.c + n
|
||||
bs = z.b[z.c:x]
|
||||
z.c = x
|
||||
return
|
||||
}
|
||||
|
||||
func (z *bytesDecReader) readb(bs []byte) {
|
||||
copy(bs, z.readx(uint(len(bs))))
|
||||
}
|
||||
|
||||
func (z *bytesDecReader) readn1() (v uint8) {
|
||||
v = z.b[z.c]
|
||||
z.c++
|
||||
return
|
||||
}
|
||||
|
||||
// func (z *bytesDecReader) readn(num uint8) (bs [8]byte) {
|
||||
// x := z.c + uint(num)
|
||||
// copy(bs[:], z.b[z.c:x]) // slice z.b completely, so we get bounds error if past
|
||||
// z.c = x
|
||||
// return
|
||||
// }
|
||||
|
||||
func (z *bytesDecReader) readn2() (bs [2]byte) {
|
||||
x := z.c + 2
|
||||
copy(bs[:], z.b[z.c:x]) // slice z.b completely, so we get bounds error if past
|
||||
z.c = x
|
||||
return
|
||||
}
|
||||
|
||||
func (z *bytesDecReader) readn3() (bs [3]byte) {
|
||||
x := z.c + 3
|
||||
copy(bs[:], z.b[z.c:x]) // slice z.b completely, so we get bounds error if past
|
||||
z.c = x
|
||||
return
|
||||
}
|
||||
|
||||
func (z *bytesDecReader) readn4() (bs [4]byte) {
|
||||
x := z.c + 4
|
||||
copy(bs[:], z.b[z.c:x]) // slice z.b completely, so we get bounds error if past
|
||||
z.c = x
|
||||
return
|
||||
}
|
||||
|
||||
func (z *bytesDecReader) readn8() (bs [8]byte) {
|
||||
x := z.c + 8
|
||||
copy(bs[:], z.b[z.c:x]) // slice z.b completely, so we get bounds error if past
|
||||
z.c = x
|
||||
return
|
||||
}
|
||||
|
||||
func (z *bytesDecReader) jsonReadNum() (out []byte) {
|
||||
z.c--
|
||||
i := z.c
|
||||
LOOP:
|
||||
if i < uint(len(z.b)) && isNumberChar(z.b[i]) {
|
||||
i++
|
||||
goto LOOP
|
||||
}
|
||||
out = z.b[z.c:i]
|
||||
z.c = i
|
||||
return
|
||||
}
|
||||
|
||||
func (z *bytesDecReader) jsonReadAsisChars() (out []byte) {
|
||||
i := z.c
|
||||
LOOP:
|
||||
token := z.b[i]
|
||||
i++
|
||||
if token == '"' || token == '\\' {
|
||||
out = z.b[z.c:i]
|
||||
z.c = i
|
||||
return // z.b[c:i]
|
||||
}
|
||||
goto LOOP
|
||||
}
|
||||
|
||||
func (z *bytesDecReader) skipWhitespace() (token byte) {
|
||||
i := z.c
|
||||
LOOP:
|
||||
if isWhitespaceChar(z.b[i]) {
|
||||
i++
|
||||
goto LOOP
|
||||
}
|
||||
z.c = i + 1
|
||||
return z.b[i]
|
||||
}
|
||||
|
||||
// func (z *bytesDecReader) skipWhitespace() (token byte) {
|
||||
// LOOP:
|
||||
// token = z.b[z.c]
|
||||
// z.c++
|
||||
// if isWhitespaceChar(token) {
|
||||
// goto LOOP
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
|
||||
func (z *bytesDecReader) readUntil(stop byte) (out []byte) {
|
||||
i := z.c
|
||||
LOOP:
|
||||
if z.b[i] == stop {
|
||||
i++
|
||||
out = z.b[z.c : i-1]
|
||||
z.c = i
|
||||
return
|
||||
}
|
||||
i++
|
||||
goto LOOP
|
||||
}
|
||||
|
||||
// --------------
|
||||
|
||||
type decRd struct {
|
||||
mtr bool // is maptype a known type?
|
||||
str bool // is slicetype a known type?
|
||||
|
||||
be bool // is binary encoding
|
||||
js bool // is json handle
|
||||
jsms bool // is json handle, and MapKeyAsString
|
||||
cbor bool // is cbor handle
|
||||
|
||||
bytes bool // is bytes reader
|
||||
bufio bool // is this a bufioDecReader?
|
||||
|
||||
rb bytesDecReader
|
||||
ri *ioDecReader
|
||||
bi *bufioDecReader
|
||||
|
||||
decReader
|
||||
}
|
||||
|
||||
// From out benchmarking, we see the following in terms of performance:
|
||||
//
|
||||
// - interface calls
|
||||
// - branch that can inline what it calls
|
||||
//
|
||||
// the if/else-if/else block is expensive to inline.
|
||||
// Each node of this construct costs a lot and dominates the budget.
|
||||
// Best to only do an if fast-path else block (so fast-path is inlined).
|
||||
// This is irrespective of inlineExtraCallCost set in $GOROOT/src/cmd/compile/internal/gc/inl.go
|
||||
//
|
||||
// In decRd methods below, we delegate all IO functions into their own methods.
|
||||
// This allows for the inlining of the common path when z.bytes=true.
|
||||
// Go 1.12+ supports inlining methods with up to 1 inlined function (or 2 if no other constructs).
|
||||
//
|
||||
// However, up through Go 1.13, decRd's readXXX, skip and unreadXXX methods are not inlined.
|
||||
// Consequently, there is no benefit to do the xxxIO methods for decRd at this time.
|
||||
// Instead, we have a if/else-if/else block so that IO calls do not have to jump through
|
||||
// a second unnecessary function call.
|
||||
//
|
||||
// If golang inlining gets better and bytesDecReader methods can be inlined,
|
||||
// then we can revert to using these 2 functions so the bytesDecReader
|
||||
// methods are inlined and the IO paths call out to a function.
|
||||
//
|
||||
// decRd is designed to embed a decReader, and then re-implement some of the decReader
|
||||
// methods using a conditional branch. We only override the ones that have a bytes version
|
||||
// that is small enough to be inlined. We use ./run.sh -z to check.
|
||||
// Right now, only numread and readn1 can be inlined.
|
||||
|
||||
func (z *decRd) numread() uint {
|
||||
if z.bytes {
|
||||
return z.rb.numread()
|
||||
} else if z.bufio {
|
||||
return z.bi.numread()
|
||||
} else {
|
||||
return z.ri.numread()
|
||||
}
|
||||
}
|
||||
|
||||
func (z *decRd) readn1() (v uint8) {
|
||||
if z.bytes {
|
||||
// MARKER: manually inline, else this function is not inlined.
|
||||
// Keep in sync with bytesDecReader.readn1
|
||||
// return z.rb.readn1()
|
||||
v = z.rb.b[z.rb.c]
|
||||
z.rb.c++
|
||||
} else {
|
||||
v = z.readn1IO()
|
||||
}
|
||||
return
|
||||
}
|
||||
func (z *decRd) readn1IO() uint8 {
|
||||
if z.bufio {
|
||||
return z.bi.readn1()
|
||||
}
|
||||
return z.ri.readn1()
|
||||
}
|
||||
|
||||
type devNullReader struct{}
|
||||
|
||||
func (devNullReader) Read(p []byte) (int, error) { return 0, io.EOF }
|
||||
func (devNullReader) Close() error { return nil }
|
||||
|
||||
func readFull(r io.Reader, bs []byte) (n uint, err error) {
|
||||
var nn int
|
||||
for n < uint(len(bs)) && err == nil {
|
||||
nn, err = r.Read(bs[n:])
|
||||
if nn > 0 {
|
||||
if err == io.EOF {
|
||||
// leave EOF for next time
|
||||
err = nil
|
||||
}
|
||||
n += uint(nn)
|
||||
}
|
||||
}
|
||||
// do not do this below - it serves no purpose
|
||||
// if n != len(bs) && err == io.EOF { err = io.ErrUnexpectedEOF }
|
||||
return
|
||||
}
|
||||
|
||||
var _ decReader = (*decRd)(nil)
|
|
@ -0,0 +1,38 @@
|
|||
// 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 "reflect"
|
||||
|
||||
// This file exists, so that the files for specific formats do not all import reflect.
|
||||
// This just helps us ensure that reflect package is isolated to a few files.
|
||||
|
||||
// SetInterfaceExt sets an extension
|
||||
func (h *JsonHandle) SetInterfaceExt(rt reflect.Type, tag uint64, ext InterfaceExt) (err error) {
|
||||
return h.SetExt(rt, tag, makeExt(ext))
|
||||
}
|
||||
|
||||
// SetInterfaceExt sets an extension
|
||||
func (h *CborHandle) SetInterfaceExt(rt reflect.Type, tag uint64, ext InterfaceExt) (err error) {
|
||||
return h.SetExt(rt, tag, makeExt(ext))
|
||||
}
|
||||
|
||||
// SetBytesExt sets an extension
|
||||
func (h *MsgpackHandle) SetBytesExt(rt reflect.Type, tag uint64, ext BytesExt) (err error) {
|
||||
return h.SetExt(rt, tag, makeExt(ext))
|
||||
}
|
||||
|
||||
// SetBytesExt sets an extension
|
||||
func (h *SimpleHandle) SetBytesExt(rt reflect.Type, tag uint64, ext BytesExt) (err error) {
|
||||
return h.SetExt(rt, tag, makeExt(ext))
|
||||
}
|
||||
|
||||
// SetBytesExt sets an extension
|
||||
func (h *BincHandle) SetBytesExt(rt reflect.Type, tag uint64, ext BytesExt) (err error) {
|
||||
return h.SetExt(rt, tag, makeExt(ext))
|
||||
}
|
||||
|
||||
// func (h *XMLHandle) SetInterfaceExt(rt reflect.Type, tag uint64, ext InterfaceExt) (err error) {
|
||||
// return h.SetExt(rt, tag, &interfaceExtWrapper{InterfaceExt: ext})
|
||||
// }
|
|
@ -1,22 +1,20 @@
|
|||
// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
|
||||
// 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 (
|
||||
"bufio"
|
||||
"errors"
|
||||
"io"
|
||||
"net/rpc"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// rpcEncodeTerminator allows a handler specify a []byte terminator to send after each Encode.
|
||||
//
|
||||
// Some codecs like json need to put a space after each encoded value, to serve as a
|
||||
// delimiter for things like numbers (else json codec will continue reading till EOF).
|
||||
type rpcEncodeTerminator interface {
|
||||
rpcEncodeTerminate() []byte
|
||||
}
|
||||
var (
|
||||
errRpcJsonNeedsTermWhitespace = errors.New("rpc - requires JsonHandle with TermWhitespace=true")
|
||||
errRpcIsClosed = errors.New("rpc - connection has been closed")
|
||||
errRpcNoConn = errors.New("rpc - no connection")
|
||||
)
|
||||
|
||||
// Rpc provides a rpc Server or Client Codec for rpc communication.
|
||||
type Rpc interface {
|
||||
|
@ -24,104 +22,124 @@ type Rpc interface {
|
|||
ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec
|
||||
}
|
||||
|
||||
// RpcCodecBuffered allows access to the underlying bufio.Reader/Writer
|
||||
// used by the rpc connection. It accomodates use-cases where the connection
|
||||
// should be used by rpc and non-rpc functions, e.g. streaming a file after
|
||||
// sending an rpc response.
|
||||
type RpcCodecBuffered interface {
|
||||
BufferedReader() *bufio.Reader
|
||||
BufferedWriter() *bufio.Writer
|
||||
// RPCOptions holds options specific to rpc functionality
|
||||
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.
|
||||
RPCNoBuffer bool
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
||||
// rpcCodec defines the struct members and common methods.
|
||||
type rpcCodec struct {
|
||||
rwc io.ReadWriteCloser
|
||||
c io.Closer
|
||||
r io.Reader
|
||||
w io.Writer
|
||||
f ioFlusher
|
||||
|
||||
dec *Decoder
|
||||
enc *Encoder
|
||||
bw *bufio.Writer
|
||||
br *bufio.Reader
|
||||
mu sync.Mutex
|
||||
h Handle
|
||||
|
||||
cls bool
|
||||
clsmu sync.RWMutex
|
||||
cls atomicClsErr
|
||||
}
|
||||
|
||||
func newRPCCodec(conn io.ReadWriteCloser, h Handle) rpcCodec {
|
||||
bw := bufio.NewWriter(conn)
|
||||
br := bufio.NewReader(conn)
|
||||
return newRPCCodec2(conn, conn, conn, h)
|
||||
}
|
||||
|
||||
func newRPCCodec2(r io.Reader, w io.Writer, c io.Closer, h Handle) rpcCodec {
|
||||
// defensive: ensure that jsonH has TermWhitespace turned on.
|
||||
jsonH, ok := h.(*JsonHandle)
|
||||
if ok && !jsonH.TermWhitespace {
|
||||
halt.onerror(errRpcJsonNeedsTermWhitespace)
|
||||
}
|
||||
var f ioFlusher
|
||||
bh := h.getBasicHandle()
|
||||
if !bh.RPCNoBuffer {
|
||||
f, ok = w.(ioFlusher)
|
||||
if bh.WriterBufferSize <= 0 {
|
||||
if !ok {
|
||||
bw := bufio.NewWriter(w)
|
||||
f, w = bw, bw
|
||||
}
|
||||
}
|
||||
if bh.ReaderBufferSize <= 0 {
|
||||
if _, ok = w.(ioBuffered); !ok {
|
||||
r = bufio.NewReader(r)
|
||||
}
|
||||
}
|
||||
}
|
||||
return rpcCodec{
|
||||
rwc: conn,
|
||||
bw: bw,
|
||||
br: br,
|
||||
enc: NewEncoder(bw, h),
|
||||
dec: NewDecoder(br, h),
|
||||
c: c,
|
||||
w: w,
|
||||
r: r,
|
||||
f: f,
|
||||
h: h,
|
||||
enc: NewEncoder(w, h),
|
||||
dec: NewDecoder(r, h),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *rpcCodec) BufferedReader() *bufio.Reader {
|
||||
return c.br
|
||||
}
|
||||
|
||||
func (c *rpcCodec) BufferedWriter() *bufio.Writer {
|
||||
return c.bw
|
||||
}
|
||||
|
||||
func (c *rpcCodec) write(obj1, obj2 interface{}, writeObj2, doFlush bool) (err error) {
|
||||
if c.isClosed() {
|
||||
return io.EOF
|
||||
}
|
||||
if err = c.enc.Encode(obj1); err != nil {
|
||||
return
|
||||
}
|
||||
t, tOk := c.h.(rpcEncodeTerminator)
|
||||
if tOk {
|
||||
c.bw.Write(t.rpcEncodeTerminate())
|
||||
}
|
||||
if writeObj2 {
|
||||
if err = c.enc.Encode(obj2); err != nil {
|
||||
return
|
||||
func (c *rpcCodec) write(obj1, obj2 interface{}, writeObj2 bool) (err error) {
|
||||
err = c.ready()
|
||||
if err == nil {
|
||||
err = c.enc.Encode(obj1)
|
||||
if err == nil && writeObj2 {
|
||||
err = c.enc.Encode(obj2)
|
||||
}
|
||||
if tOk {
|
||||
c.bw.Write(t.rpcEncodeTerminate())
|
||||
if c.f != nil {
|
||||
flushErr := c.f.Flush()
|
||||
if err == nil {
|
||||
// ignore flush error if prior error occurred during Encode
|
||||
err = flushErr
|
||||
}
|
||||
}
|
||||
}
|
||||
if doFlush {
|
||||
return c.bw.Flush()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *rpcCodec) read(obj interface{}) (err error) {
|
||||
if c.isClosed() {
|
||||
return io.EOF
|
||||
err = c.ready()
|
||||
if err == nil {
|
||||
//If nil is passed in, we should read and discard
|
||||
if obj == nil {
|
||||
// return c.dec.Decode(&obj)
|
||||
err = c.dec.swallowErr()
|
||||
} else {
|
||||
err = c.dec.Decode(obj)
|
||||
}
|
||||
}
|
||||
//If nil is passed in, we should still attempt to read content to nowhere.
|
||||
if obj == nil {
|
||||
var obj2 interface{}
|
||||
return c.dec.Decode(&obj2)
|
||||
}
|
||||
return c.dec.Decode(obj)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *rpcCodec) isClosed() bool {
|
||||
c.clsmu.RLock()
|
||||
x := c.cls
|
||||
c.clsmu.RUnlock()
|
||||
return x
|
||||
func (c *rpcCodec) Close() (err error) {
|
||||
if c.c != nil {
|
||||
cls := c.cls.load()
|
||||
if !cls.closed {
|
||||
cls.err = c.c.Close()
|
||||
cls.closed = true
|
||||
c.cls.store(cls)
|
||||
}
|
||||
err = cls.err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *rpcCodec) Close() error {
|
||||
if c.isClosed() {
|
||||
return io.EOF
|
||||
func (c *rpcCodec) ready() (err error) {
|
||||
if c.c == nil {
|
||||
err = errRpcNoConn
|
||||
} else {
|
||||
cls := c.cls.load()
|
||||
if cls.closed {
|
||||
if err = cls.err; err == nil {
|
||||
err = errRpcIsClosed
|
||||
}
|
||||
}
|
||||
}
|
||||
c.clsmu.Lock()
|
||||
c.cls = true
|
||||
c.clsmu.Unlock()
|
||||
return c.rwc.Close()
|
||||
return
|
||||
}
|
||||
|
||||
func (c *rpcCodec) ReadResponseBody(body interface{}) error {
|
||||
|
@ -135,16 +153,11 @@ type goRpcCodec struct {
|
|||
}
|
||||
|
||||
func (c *goRpcCodec) WriteRequest(r *rpc.Request, body interface{}) error {
|
||||
// Must protect for concurrent access as per API
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
return c.write(r, body, true, true)
|
||||
return c.write(r, body, true)
|
||||
}
|
||||
|
||||
func (c *goRpcCodec) WriteResponse(r *rpc.Response, body interface{}) error {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
return c.write(r, body, true, true)
|
||||
return c.write(r, body, true)
|
||||
}
|
||||
|
||||
func (c *goRpcCodec) ReadResponseHeader(r *rpc.Response) error {
|
||||
|
@ -166,7 +179,36 @@ func (c *goRpcCodec) ReadRequestBody(body interface{}) error {
|
|||
type goRpc struct{}
|
||||
|
||||
// GoRpc implements Rpc using the communication protocol defined in net/rpc package.
|
||||
// Its methods (ServerCodec and ClientCodec) return values that implement RpcCodecBuffered.
|
||||
//
|
||||
// Note: network connection (from net.Dial, of type io.ReadWriteCloser) is not buffered.
|
||||
//
|
||||
// For performance, you should configure WriterBufferSize and ReaderBufferSize on the handle.
|
||||
// This ensures we use an adequate buffer during reading and writing.
|
||||
// If not configured, we will internally initialize and use a buffer during reads and writes.
|
||||
// This can be turned off via the RPCNoBuffer option on the Handle.
|
||||
// var handle codec.JsonHandle
|
||||
// handle.RPCNoBuffer = true // turns off attempt by rpc module to initialize a buffer
|
||||
//
|
||||
// Example 1: one way of configuring buffering explicitly:
|
||||
// var handle codec.JsonHandle // codec handle
|
||||
// handle.ReaderBufferSize = 1024
|
||||
// handle.WriterBufferSize = 1024
|
||||
// var conn io.ReadWriteCloser // connection got from a socket
|
||||
// var serverCodec = GoRpc.ServerCodec(conn, handle)
|
||||
// var clientCodec = GoRpc.ClientCodec(conn, handle)
|
||||
//
|
||||
// Example 2: you can also explicitly create a buffered connection yourself,
|
||||
// and not worry about configuring the buffer sizes in the Handle.
|
||||
// var handle codec.Handle // codec handle
|
||||
// var conn io.ReadWriteCloser // connection got from a socket
|
||||
// var bufconn = struct { // bufconn here is a buffered io.ReadWriteCloser
|
||||
// io.Closer
|
||||
// *bufio.Reader
|
||||
// *bufio.Writer
|
||||
// }{conn, bufio.NewReader(conn), bufio.NewWriter(conn)}
|
||||
// var serverCodec = GoRpc.ServerCodec(bufconn, handle)
|
||||
// var clientCodec = GoRpc.ClientCodec(bufconn, handle)
|
||||
//
|
||||
var GoRpc goRpc
|
||||
|
||||
func (x goRpc) ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec {
|
||||
|
@ -176,5 +218,3 @@ func (x goRpc) ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec {
|
|||
func (x goRpc) ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec {
|
||||
return &goRpcCodec{newRPCCodec(conn, h)}
|
||||
}
|
||||
|
||||
var _ RpcCodecBuffered = (*rpcCodec)(nil) // ensure *rpcCodec implements RpcCodecBuffered
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
|
||||
// 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 (
|
||||
"math"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -20,6 +20,8 @@ const (
|
|||
simpleVdPosInt = 8
|
||||
simpleVdNegInt = 12
|
||||
|
||||
simpleVdTime = 24
|
||||
|
||||
// containers: each lasts for 4 (ie n, n+1, n+2, ... n+7)
|
||||
simpleVdString = 216
|
||||
simpleVdByteArray = 224
|
||||
|
@ -28,35 +30,77 @@ const (
|
|||
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
|
||||
encNoSeparator
|
||||
e *Encoder
|
||||
encDriverNoopContainerWriter
|
||||
h *SimpleHandle
|
||||
w encWriter
|
||||
b [8]byte
|
||||
// b [8]byte
|
||||
e Encoder
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver) encoder() *Encoder {
|
||||
return &e.e
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver) EncodeNil() {
|
||||
e.w.writen1(simpleVdNil)
|
||||
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) EncodeFloat32(f float32) {
|
||||
e.w.writen1(simpleVdFloat32)
|
||||
bigenHelper{e.b[:4], e.w}.writeUint32(math.Float32bits(f))
|
||||
if e.h.EncZeroValuesAsNil && e.e.c != containerMapKey && f == 0.0 {
|
||||
e.EncodeNil()
|
||||
return
|
||||
}
|
||||
e.e.encWr.writen1(simpleVdFloat32)
|
||||
bigen.writeUint32(e.e.w(), math.Float32bits(f))
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver) EncodeFloat64(f float64) {
|
||||
e.w.writen1(simpleVdFloat64)
|
||||
bigenHelper{e.b[:8], e.w}.writeUint64(math.Float64bits(f))
|
||||
if e.h.EncZeroValuesAsNil && e.e.c != containerMapKey && f == 0.0 {
|
||||
e.EncodeNil()
|
||||
return
|
||||
}
|
||||
e.e.encWr.writen1(simpleVdFloat64)
|
||||
bigen.writeUint64(e.e.w(), math.Float64bits(f))
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver) EncodeInt(v int64) {
|
||||
|
@ -72,162 +116,206 @@ func (e *simpleEncDriver) EncodeUint(v uint64) {
|
|||
}
|
||||
|
||||
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)
|
||||
bigenHelper{e.b[:2], e.w}.writeUint16(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)
|
||||
bigenHelper{e.b[:4], e.w}.writeUint32(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)
|
||||
bigenHelper{e.b[:8], e.w}.writeUint64(v)
|
||||
e.e.encWr.writen1(bd + 3)
|
||||
bigen.writeUint64(e.e.w(), v)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
bigenHelper{e.b[:2], e.w}.writeUint16(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)
|
||||
bigenHelper{e.b[:4], e.w}.writeUint32(uint32(length))
|
||||
e.e.encWr.writen1(bd + 3)
|
||||
bigen.writeUint32(e.e.w(), uint32(length))
|
||||
} else {
|
||||
e.w.writen1(bd + 4)
|
||||
bigenHelper{e.b[:8], e.w}.writeUint64(uint64(length))
|
||||
e.e.encWr.writen1(bd + 4)
|
||||
bigen.writeUint64(e.e.w(), uint64(length))
|
||||
}
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver) EncodeExt(rv interface{}, xtag uint64, ext Ext, _ *Encoder) {
|
||||
bs := ext.WriteExt(rv)
|
||||
func (e *simpleEncDriver) EncodeExt(v interface{}, xtag uint64, ext Ext) {
|
||||
var bs0, bs []byte
|
||||
if ext == SelfExt {
|
||||
bs0 = e.e.blist.get(1024)
|
||||
bs = bs0
|
||||
e.e.sideEncode(v, &bs)
|
||||
} else {
|
||||
bs = ext.WriteExt(v)
|
||||
}
|
||||
if bs == nil {
|
||||
e.EncodeNil()
|
||||
return
|
||||
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)
|
||||
if !byteSliceSameData(bs0, bs) {
|
||||
e.e.blist.put(bs0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver) EncodeRawExt(re *RawExt, _ *Encoder) {
|
||||
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) encodeExtPreamble(xtag byte, length int) {
|
||||
e.encLen(simpleVdExt, length)
|
||||
e.w.writen1(xtag)
|
||||
e.e.encWr.writen1(xtag)
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver) EncodeArrayStart(length int) {
|
||||
func (e *simpleEncDriver) WriteArrayStart(length int) {
|
||||
e.encLen(simpleVdArray, length)
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver) EncodeMapStart(length int) {
|
||||
func (e *simpleEncDriver) WriteMapStart(length int) {
|
||||
e.encLen(simpleVdMap, length)
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver) EncodeString(c charEncoding, v string) {
|
||||
e.encLen(simpleVdString, len(v))
|
||||
e.w.writestr(v)
|
||||
func (e *simpleEncDriver) EncodeString(v string) {
|
||||
if e.h.EncZeroValuesAsNil && e.e.c != containerMapKey && v == "" {
|
||||
e.EncodeNil()
|
||||
return
|
||||
}
|
||||
if e.h.StringToRaw {
|
||||
e.encLen(simpleVdByteArray, len(v))
|
||||
} else {
|
||||
e.encLen(simpleVdString, len(v))
|
||||
}
|
||||
e.e.encWr.writestr(v)
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver) EncodeSymbol(v string) {
|
||||
e.EncodeString(c_UTF8, v)
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
|
||||
func (e *simpleEncDriver) EncodeStringBytesRaw(v []byte) {
|
||||
// if e.h.EncZeroValuesAsNil && e.c != containerMapKey && v == nil {
|
||||
if v == nil {
|
||||
e.EncodeNil()
|
||||
return
|
||||
}
|
||||
e.encLen(simpleVdByteArray, len(v))
|
||||
e.w.writeb(v)
|
||||
e.e.encWr.writeb(v)
|
||||
}
|
||||
|
||||
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()
|
||||
e.e.onerror(err)
|
||||
e.e.encWr.writen2(simpleVdTime, uint8(len(v)))
|
||||
e.e.encWr.writeb(v)
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
|
||||
type simpleDecDriver struct {
|
||||
d *Decoder
|
||||
h *SimpleHandle
|
||||
r decReader
|
||||
bdRead bool
|
||||
bd byte
|
||||
br bool // bytes reader
|
||||
_ bool
|
||||
noBuiltInTypes
|
||||
noStreamingCodec
|
||||
decNoSeparator
|
||||
b [scratchByteArrayLen]byte
|
||||
decDriverNoopContainerReader
|
||||
d Decoder
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver) decoder() *Decoder {
|
||||
return &d.d
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver) readNextBd() {
|
||||
d.bd = d.r.readn1()
|
||||
d.bd = d.d.decRd.readn1()
|
||||
d.bdRead = true
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver) ContainerType() (vt valueType) {
|
||||
if d.bd == simpleVdNil {
|
||||
return valueTypeNil
|
||||
} else if d.bd == simpleVdByteArray || d.bd == simpleVdByteArray+1 ||
|
||||
d.bd == simpleVdByteArray+2 || d.bd == simpleVdByteArray+3 || d.bd == simpleVdByteArray+4 {
|
||||
return valueTypeBytes
|
||||
} else if d.bd == simpleVdString || d.bd == simpleVdString+1 ||
|
||||
d.bd == simpleVdString+2 || d.bd == simpleVdString+3 || d.bd == simpleVdString+4 {
|
||||
return valueTypeString
|
||||
} else if d.bd == simpleVdArray || d.bd == simpleVdArray+1 ||
|
||||
d.bd == simpleVdArray+2 || d.bd == simpleVdArray+3 || d.bd == simpleVdArray+4 {
|
||||
return valueTypeArray
|
||||
} else if d.bd == simpleVdMap || d.bd == simpleVdMap+1 ||
|
||||
d.bd == simpleVdMap+2 || d.bd == simpleVdMap+3 || d.bd == simpleVdMap+4 {
|
||||
return valueTypeMap
|
||||
} else {
|
||||
// d.d.errorf("isContainerType: unsupported parameter: %v", vt)
|
||||
}
|
||||
return valueTypeUnset
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver) TryDecodeAsNil() bool {
|
||||
func (d *simpleDecDriver) advanceNil() (null bool) {
|
||||
if !d.bdRead {
|
||||
d.readNextBd()
|
||||
}
|
||||
if d.bd == simpleVdNil {
|
||||
d.bdRead = false
|
||||
return true
|
||||
return true // null = true
|
||||
}
|
||||
return false
|
||||
return
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver) decCheckInteger() (ui uint64, neg bool) {
|
||||
func (d *simpleDecDriver) ContainerType() (vt valueType) {
|
||||
if !d.bdRead {
|
||||
d.readNextBd()
|
||||
}
|
||||
switch d.bd {
|
||||
case simpleVdNil:
|
||||
d.bdRead = false
|
||||
return valueTypeNil
|
||||
case simpleVdByteArray, simpleVdByteArray + 1,
|
||||
simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
|
||||
return valueTypeBytes
|
||||
case simpleVdString, simpleVdString + 1,
|
||||
simpleVdString + 2, simpleVdString + 3, simpleVdString + 4:
|
||||
return valueTypeString
|
||||
case simpleVdArray, simpleVdArray + 1,
|
||||
simpleVdArray + 2, simpleVdArray + 3, simpleVdArray + 4:
|
||||
return valueTypeArray
|
||||
case simpleVdMap, simpleVdMap + 1,
|
||||
simpleVdMap + 2, simpleVdMap + 3, simpleVdMap + 4:
|
||||
return valueTypeMap
|
||||
}
|
||||
return valueTypeUnset
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver) TryNil() bool {
|
||||
return d.advanceNil()
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver) decCheckInteger() (ui uint64, neg bool) {
|
||||
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.readx(2)))
|
||||
ui = uint64(bigen.Uint16(d.d.decRd.readn2()))
|
||||
case simpleVdPosInt + 2:
|
||||
ui = uint64(bigen.Uint32(d.r.readx(4)))
|
||||
ui = uint64(bigen.Uint32(d.d.decRd.readn4()))
|
||||
case simpleVdPosInt + 3:
|
||||
ui = uint64(bigen.Uint64(d.r.readx(8)))
|
||||
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.readx(2)))
|
||||
ui = uint64(bigen.Uint16(d.d.decRd.readn2()))
|
||||
neg = true
|
||||
case simpleVdNegInt + 2:
|
||||
ui = uint64(bigen.Uint32(d.r.readx(4)))
|
||||
ui = uint64(bigen.Uint32(d.d.decRd.readn4()))
|
||||
neg = true
|
||||
case simpleVdNegInt + 3:
|
||||
ui = uint64(bigen.Uint64(d.r.readx(8)))
|
||||
ui = uint64(bigen.Uint64(d.d.decRd.readn8()))
|
||||
neg = true
|
||||
default:
|
||||
d.d.errorf("decIntAny: Integer only valid from pos/neg integer1..8. Invalid descriptor: %v", d.bd)
|
||||
return
|
||||
d.d.errorf("integer only valid from pos/neg integer1..8. Invalid descriptor: %v", d.bd)
|
||||
}
|
||||
// don't do this check, because callers may only want the unsigned value.
|
||||
// DO NOT do this check below, because callers may only want the unsigned value:
|
||||
//
|
||||
// if ui > math.MaxInt64 {
|
||||
// d.d.errorf("decIntAny: Integer out of range for signed int64: %v", ui)
|
||||
// return
|
||||
|
@ -235,174 +323,197 @@ func (d *simpleDecDriver) decCheckInteger() (ui uint64, neg bool) {
|
|||
return
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver) DecodeInt(bitsize uint8) (i int64) {
|
||||
ui, neg := d.decCheckInteger()
|
||||
i, overflow := chkOvf.SignedInt(ui)
|
||||
if overflow {
|
||||
d.d.errorf("simple: overflow converting %v to signed integer", ui)
|
||||
func (d *simpleDecDriver) DecodeInt64() (i int64) {
|
||||
if d.advanceNil() {
|
||||
return
|
||||
}
|
||||
ui, neg := d.decCheckInteger()
|
||||
i = chkOvf.SignedIntV(ui)
|
||||
if neg {
|
||||
i = -i
|
||||
}
|
||||
if chkOvf.Int(i, bitsize) {
|
||||
d.d.errorf("simple: overflow integer: %v", i)
|
||||
return
|
||||
}
|
||||
d.bdRead = false
|
||||
return
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver) DecodeUint(bitsize uint8) (ui uint64) {
|
||||
func (d *simpleDecDriver) DecodeUint64() (ui uint64) {
|
||||
if d.advanceNil() {
|
||||
return
|
||||
}
|
||||
ui, neg := d.decCheckInteger()
|
||||
if neg {
|
||||
d.d.errorf("Assigning negative signed value to unsigned type")
|
||||
return
|
||||
}
|
||||
if chkOvf.Uint(ui, bitsize) {
|
||||
d.d.errorf("simple: overflow integer: %v", ui)
|
||||
return
|
||||
d.d.errorf("assigning negative signed value to unsigned type")
|
||||
}
|
||||
d.bdRead = false
|
||||
return
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver) DecodeFloat(chkOverflow32 bool) (f float64) {
|
||||
if !d.bdRead {
|
||||
d.readNextBd()
|
||||
func (d *simpleDecDriver) DecodeFloat64() (f float64) {
|
||||
if d.advanceNil() {
|
||||
return
|
||||
}
|
||||
if d.bd == simpleVdFloat32 {
|
||||
f = float64(math.Float32frombits(bigen.Uint32(d.r.readx(4))))
|
||||
f = float64(math.Float32frombits(bigen.Uint32(d.d.decRd.readn4())))
|
||||
} else if d.bd == simpleVdFloat64 {
|
||||
f = math.Float64frombits(bigen.Uint64(d.r.readx(8)))
|
||||
f = math.Float64frombits(bigen.Uint64(d.d.decRd.readn8()))
|
||||
} else {
|
||||
if d.bd >= simpleVdPosInt && d.bd <= simpleVdNegInt+3 {
|
||||
f = float64(d.DecodeInt(64))
|
||||
f = float64(d.DecodeInt64())
|
||||
} else {
|
||||
d.d.errorf("Float only valid from float32/64: Invalid descriptor: %v", d.bd)
|
||||
return
|
||||
d.d.errorf("float only valid from float32/64: Invalid descriptor: %v", d.bd)
|
||||
}
|
||||
}
|
||||
if chkOverflow32 && chkOvf.Float32(f) {
|
||||
d.d.errorf("msgpack: float32 overflow: %v", f)
|
||||
return
|
||||
}
|
||||
d.bdRead = false
|
||||
return
|
||||
}
|
||||
|
||||
// bool can be decoded from bool only (single byte).
|
||||
func (d *simpleDecDriver) DecodeBool() (b bool) {
|
||||
if !d.bdRead {
|
||||
d.readNextBd()
|
||||
}
|
||||
if d.bd == simpleVdTrue {
|
||||
b = true
|
||||
} else if d.bd == simpleVdFalse {
|
||||
} else {
|
||||
d.d.errorf("Invalid single-byte value for bool: %s: %x", msgBadDesc, d.bd)
|
||||
if d.advanceNil() {
|
||||
return
|
||||
}
|
||||
if d.bd == simpleVdFalse {
|
||||
} else if d.bd == simpleVdTrue {
|
||||
b = true
|
||||
} else {
|
||||
d.d.errorf("cannot decode bool - %s: %x", msgBadDesc, d.bd)
|
||||
}
|
||||
d.bdRead = false
|
||||
return
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver) ReadMapStart() (length int) {
|
||||
if d.advanceNil() {
|
||||
return containerLenNil
|
||||
}
|
||||
d.bdRead = false
|
||||
return d.decLen()
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver) ReadArrayStart() (length int) {
|
||||
if d.advanceNil() {
|
||||
return containerLenNil
|
||||
}
|
||||
d.bdRead = false
|
||||
return d.decLen()
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver) uint2Len(ui uint64) int {
|
||||
if chkOvf.Uint(ui, intBitsize) {
|
||||
d.d.errorf("overflow integer: %v", ui)
|
||||
}
|
||||
return int(ui)
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver) decLen() int {
|
||||
switch d.bd % 8 {
|
||||
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.readx(2)))
|
||||
return int(bigen.Uint16(d.d.decRd.readn2()))
|
||||
case 3:
|
||||
ui := uint64(bigen.Uint32(d.r.readx(4)))
|
||||
if chkOvf.Uint(ui, intBitsize) {
|
||||
d.d.errorf("simple: overflow integer: %v", ui)
|
||||
return 0
|
||||
}
|
||||
return int(ui)
|
||||
return d.uint2Len(uint64(bigen.Uint32(d.d.decRd.readn4())))
|
||||
case 4:
|
||||
ui := bigen.Uint64(d.r.readx(8))
|
||||
if chkOvf.Uint(ui, intBitsize) {
|
||||
d.d.errorf("simple: overflow integer: %v", ui)
|
||||
return 0
|
||||
}
|
||||
return int(ui)
|
||||
return d.uint2Len(bigen.Uint64(d.d.decRd.readn8()))
|
||||
}
|
||||
d.d.errorf("decLen: 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) DecodeString() (s string) {
|
||||
return string(d.DecodeBytes(d.b[:], true, true))
|
||||
func (d *simpleDecDriver) DecodeStringAsBytes() (s []byte) {
|
||||
return d.DecodeBytes(nil)
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver) DecodeBytes(bs []byte, isstring, zerocopy bool) (bsOut []byte) {
|
||||
if !d.bdRead {
|
||||
d.readNextBd()
|
||||
}
|
||||
if d.bd == simpleVdNil {
|
||||
d.bdRead = false
|
||||
func (d *simpleDecDriver) DecodeBytes(bs []byte) (bsOut []byte) {
|
||||
d.d.decByteState = decByteStateNone
|
||||
if d.advanceNil() {
|
||||
return
|
||||
}
|
||||
// check if an "array" of uint8's (see ContainerType for how to infer if an array)
|
||||
if d.bd >= simpleVdArray && d.bd <= simpleVdMap+4 {
|
||||
if bs == nil {
|
||||
d.d.decByteState = decByteStateReuseBuf
|
||||
bs = d.d.b[:]
|
||||
}
|
||||
slen := d.ReadArrayStart()
|
||||
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))
|
||||
}
|
||||
return bs
|
||||
}
|
||||
|
||||
clen := d.decLen()
|
||||
d.bdRead = false
|
||||
if zerocopy {
|
||||
if d.br {
|
||||
return d.r.readx(clen)
|
||||
} else if len(bs) == 0 {
|
||||
bs = d.b[:]
|
||||
}
|
||||
if d.d.zerocopy() {
|
||||
d.d.decByteState = decByteStateZerocopy
|
||||
return d.d.decRd.rb.readx(uint(clen))
|
||||
}
|
||||
return decByteSlice(d.r, clen, bs)
|
||||
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) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) {
|
||||
if xtag > 0xff {
|
||||
d.d.errorf("decodeExt: tag must be <= 0xff; got: %v", xtag)
|
||||
func (d *simpleDecDriver) DecodeTime() (t time.Time) {
|
||||
if d.advanceNil() {
|
||||
return
|
||||
}
|
||||
realxtag1, xbs := d.decodeExtV(ext != nil, uint8(xtag))
|
||||
realxtag = uint64(realxtag1)
|
||||
if ext == nil {
|
||||
re := rv.(*RawExt)
|
||||
re.Tag = realxtag
|
||||
re.Data = detachZeroCopyBytes(d.br, re.Data, xbs)
|
||||
} else {
|
||||
ext.ReadExt(rv, xbs)
|
||||
if d.bd != simpleVdTime {
|
||||
d.d.errorf("invalid descriptor for time.Time - expect 0x%x, received 0x%x", simpleVdTime, d.bd)
|
||||
}
|
||||
d.bdRead = false
|
||||
clen := uint(d.d.decRd.readn1())
|
||||
b := d.d.decRd.readx(clen)
|
||||
d.d.onerror((&t).UnmarshalBinary(b))
|
||||
return
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver) decodeExtV(verifyTag bool, tag byte) (xtag byte, xbs []byte) {
|
||||
if !d.bdRead {
|
||||
d.readNextBd()
|
||||
func (d *simpleDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) {
|
||||
if xtag > 0xff {
|
||||
d.d.errorf("ext: tag must be <= 0xff; got: %v", xtag)
|
||||
}
|
||||
if d.advanceNil() {
|
||||
return
|
||||
}
|
||||
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, xbs)
|
||||
} else {
|
||||
ext.ReadExt(rv, xbs)
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
d.d.errorf("Wrong extension tag. Got %b. Expecting: %v", xtag, tag)
|
||||
return
|
||||
d.d.errorf("wrong extension tag. Got %b. Expecting: %v", xtag, tag)
|
||||
}
|
||||
xbs = d.r.readx(l)
|
||||
case simpleVdByteArray, simpleVdByteArray + 1, simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
|
||||
xbs = d.DecodeBytes(nil, false, true)
|
||||
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[:])
|
||||
}
|
||||
case simpleVdByteArray, simpleVdByteArray + 1,
|
||||
simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
|
||||
xbs = d.DecodeBytes(nil)
|
||||
default:
|
||||
d.d.errorf("Invalid d.bd for extensions (Expecting extensions or byte array). Got: 0x%x", d.bd)
|
||||
return
|
||||
d.d.errorf("ext - %s - expecting extensions/bytearray, got: 0x%x", msgBadDesc, d.bd)
|
||||
}
|
||||
d.bdRead = false
|
||||
return
|
||||
|
@ -413,7 +524,7 @@ func (d *simpleDecDriver) DecodeNaked() {
|
|||
d.readNextBd()
|
||||
}
|
||||
|
||||
n := &d.d.n
|
||||
n := d.d.naked()
|
||||
var decodeFurther bool
|
||||
|
||||
switch d.bd {
|
||||
|
@ -428,44 +539,154 @@ func (d *simpleDecDriver) DecodeNaked() {
|
|||
case simpleVdPosInt, simpleVdPosInt + 1, simpleVdPosInt + 2, simpleVdPosInt + 3:
|
||||
if d.h.SignedInteger {
|
||||
n.v = valueTypeInt
|
||||
n.i = d.DecodeInt(64)
|
||||
n.i = d.DecodeInt64()
|
||||
} else {
|
||||
n.v = valueTypeUint
|
||||
n.u = d.DecodeUint(64)
|
||||
n.u = d.DecodeUint64()
|
||||
}
|
||||
case simpleVdNegInt, simpleVdNegInt + 1, simpleVdNegInt + 2, simpleVdNegInt + 3:
|
||||
n.v = valueTypeInt
|
||||
n.i = d.DecodeInt(64)
|
||||
n.i = d.DecodeInt64()
|
||||
case simpleVdFloat32:
|
||||
n.v = valueTypeFloat
|
||||
n.f = d.DecodeFloat(true)
|
||||
n.f = d.DecodeFloat64()
|
||||
case simpleVdFloat64:
|
||||
n.v = valueTypeFloat
|
||||
n.f = d.DecodeFloat(false)
|
||||
case simpleVdString, simpleVdString + 1, simpleVdString + 2, simpleVdString + 3, simpleVdString + 4:
|
||||
n.f = d.DecodeFloat64()
|
||||
case simpleVdTime:
|
||||
n.v = valueTypeTime
|
||||
n.t = d.DecodeTime()
|
||||
case simpleVdString, simpleVdString + 1,
|
||||
simpleVdString + 2, simpleVdString + 3, simpleVdString + 4:
|
||||
n.v = valueTypeString
|
||||
n.s = d.DecodeString()
|
||||
case simpleVdByteArray, simpleVdByteArray + 1, simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
|
||||
n.v = valueTypeBytes
|
||||
n.l = d.DecodeBytes(nil, false, false)
|
||||
n.s = d.d.stringZC(d.DecodeStringAsBytes())
|
||||
case simpleVdByteArray, simpleVdByteArray + 1,
|
||||
simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
|
||||
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(l)
|
||||
case simpleVdArray, simpleVdArray + 1, simpleVdArray + 2, simpleVdArray + 3, simpleVdArray + 4:
|
||||
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
|
||||
decodeFurther = true
|
||||
case simpleVdMap, simpleVdMap + 1, simpleVdMap + 2, simpleVdMap + 3, simpleVdMap + 4:
|
||||
n.v = valueTypeMap
|
||||
decodeFurther = true
|
||||
default:
|
||||
d.d.errorf("decodeNaked: Unrecognized d.bd: 0x%x", d.bd)
|
||||
d.d.errorf("cannot infer value - %s 0x%x", msgBadDesc, d.bd)
|
||||
}
|
||||
|
||||
if !decodeFurther {
|
||||
d.bdRead = false
|
||||
}
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver) nextValueBytes(v0 []byte) (v []byte) {
|
||||
if !d.bdRead {
|
||||
d.readNextBd()
|
||||
}
|
||||
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) 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
|
||||
|
||||
switch c {
|
||||
case simpleVdNil, simpleVdFalse, simpleVdTrue, simpleVdString, simpleVdByteArray:
|
||||
// pass
|
||||
case simpleVdPosInt, simpleVdNegInt:
|
||||
h.append1(&v, d.d.decRd.readn1())
|
||||
case simpleVdPosInt + 1, simpleVdNegInt + 1:
|
||||
h.appendN(&v, d.d.decRd.readx(2)...)
|
||||
case simpleVdPosInt + 2, simpleVdNegInt + 2, simpleVdFloat32:
|
||||
h.appendN(&v, d.d.decRd.readx(4)...)
|
||||
case simpleVdPosInt + 3, simpleVdNegInt + 3, simpleVdFloat64:
|
||||
h.appendN(&v, d.d.decRd.readx(8)...)
|
||||
case simpleVdTime:
|
||||
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.d.decRd.readn1()
|
||||
length = uint(b)
|
||||
h.append1(&v, b)
|
||||
case 2:
|
||||
x := d.d.decRd.readn2()
|
||||
length = uint(bigen.Uint16(x))
|
||||
h.appendN(&v, x[:]...)
|
||||
case 3:
|
||||
x := d.d.decRd.readn4()
|
||||
length = uint(bigen.Uint32(x))
|
||||
h.appendN(&v, x[:]...)
|
||||
case 4:
|
||||
x := d.d.decRd.readn8()
|
||||
length = uint(bigen.Uint64(x))
|
||||
h.appendN(&v, x[:]...)
|
||||
}
|
||||
|
||||
bExt := c >= simpleVdExt && c <= simpleVdExt+7
|
||||
bStr := c >= simpleVdString && c <= simpleVdString+7
|
||||
bByteArray := c >= simpleVdByteArray && c <= simpleVdByteArray+7
|
||||
bArray := c >= simpleVdArray && c <= simpleVdArray+7
|
||||
bMap := c >= simpleVdMap && c <= simpleVdMap+7
|
||||
|
||||
if !(bExt || bStr || bByteArray || bArray || bMap) {
|
||||
d.d.errorf("cannot infer value - %s 0x%x", msgBadDesc, c)
|
||||
}
|
||||
|
||||
if bExt {
|
||||
h.append1(&v, d.d.decRd.readn1()) // tag
|
||||
}
|
||||
|
||||
if length == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
if bArray {
|
||||
for i := uint(0); i < length; i++ {
|
||||
v = d.nextValueBytesR(v)
|
||||
}
|
||||
} else if bMap {
|
||||
for i := uint(0); i < length; i++ {
|
||||
v = d.nextValueBytesR(v)
|
||||
v = d.nextValueBytesR(v)
|
||||
}
|
||||
} else {
|
||||
h.appendN(&v, d.d.decRd.readx(length)...)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -474,12 +695,12 @@ func (d *simpleDecDriver) DecodeNaked() {
|
|||
// SimpleHandle is a Handle for a very simple encoding format.
|
||||
//
|
||||
// simple is a simplistic codec similar to binc, but not as compact.
|
||||
// - Encoding of a value is always preceeded by the descriptor byte (bd)
|
||||
// - 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)
|
||||
// - Lenght of containers (strings, bytes, array, map, extensions)
|
||||
// - 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)
|
||||
|
@ -487,31 +708,41 @@ func (d *simpleDecDriver) DecodeNaked() {
|
|||
// - 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]...
|
||||
//
|
||||
// The full spec will be published soon.
|
||||
type SimpleHandle struct {
|
||||
BasicHandle
|
||||
binaryEncodingType
|
||||
BasicHandle
|
||||
// EncZeroValuesAsNil says to encode zero values for numbers, bool, string, etc as nil
|
||||
EncZeroValuesAsNil bool
|
||||
}
|
||||
|
||||
func (h *SimpleHandle) SetBytesExt(rt reflect.Type, tag uint64, ext BytesExt) (err error) {
|
||||
return h.SetExt(rt, tag, &setExtWrapper{b: ext})
|
||||
// Name returns the name of the handle: simple
|
||||
func (h *SimpleHandle) Name() string { return "simple" }
|
||||
|
||||
func (h *SimpleHandle) desc(bd byte) string { return simpledesc(bd) }
|
||||
|
||||
func (h *SimpleHandle) newEncDriver() encDriver {
|
||||
var e = &simpleEncDriver{h: h}
|
||||
e.e.e = e
|
||||
e.e.init(h)
|
||||
e.reset()
|
||||
return e
|
||||
}
|
||||
|
||||
func (h *SimpleHandle) newEncDriver(e *Encoder) encDriver {
|
||||
return &simpleEncDriver{e: e, w: e.w, h: h}
|
||||
}
|
||||
|
||||
func (h *SimpleHandle) newDecDriver(d *Decoder) decDriver {
|
||||
return &simpleDecDriver{d: d, r: d.r, h: h, br: d.bytes}
|
||||
func (h *SimpleHandle) newDecDriver() decDriver {
|
||||
d := &simpleDecDriver{h: h}
|
||||
d.d.d = d
|
||||
d.d.init(h)
|
||||
d.reset()
|
||||
return d
|
||||
}
|
||||
|
||||
func (e *simpleEncDriver) reset() {
|
||||
e.w = e.e.w
|
||||
}
|
||||
|
||||
func (d *simpleDecDriver) reset() {
|
||||
d.r = d.d.r
|
||||
d.bd, d.bdRead = 0, false
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
// 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.
|
||||
|
||||
// Code generated from sort-slice.go.tmpl - DO NOT EDIT.
|
||||
|
||||
package codec
|
||||
|
||||
import "time"
|
||||
import "reflect"
|
||||
import "bytes"
|
||||
|
||||
type stringSlice []string
|
||||
|
||||
func (p stringSlice) Len() int { return len(p) }
|
||||
func (p stringSlice) Swap(i, j int) { p[uint(i)], p[uint(j)] = p[uint(j)], p[uint(i)] }
|
||||
func (p stringSlice) Less(i, j int) bool {
|
||||
return p[uint(i)] < p[uint(j)]
|
||||
}
|
||||
|
||||
type uint8Slice []uint8
|
||||
|
||||
func (p uint8Slice) Len() int { return len(p) }
|
||||
func (p uint8Slice) Swap(i, j int) { p[uint(i)], p[uint(j)] = p[uint(j)], p[uint(i)] }
|
||||
func (p uint8Slice) Less(i, j int) bool {
|
||||
return p[uint(i)] < p[uint(j)]
|
||||
}
|
||||
|
||||
type uint64Slice []uint64
|
||||
|
||||
func (p uint64Slice) Len() int { return len(p) }
|
||||
func (p uint64Slice) Swap(i, j int) { p[uint(i)], p[uint(j)] = p[uint(j)], p[uint(i)] }
|
||||
func (p uint64Slice) Less(i, j int) bool {
|
||||
return p[uint(i)] < p[uint(j)]
|
||||
}
|
||||
|
||||
type intSlice []int
|
||||
|
||||
func (p intSlice) Len() int { return len(p) }
|
||||
func (p intSlice) Swap(i, j int) { p[uint(i)], p[uint(j)] = p[uint(j)], p[uint(i)] }
|
||||
func (p intSlice) Less(i, j int) bool {
|
||||
return p[uint(i)] < p[uint(j)]
|
||||
}
|
||||
|
||||
type int32Slice []int32
|
||||
|
||||
func (p int32Slice) Len() int { return len(p) }
|
||||
func (p int32Slice) Swap(i, j int) { p[uint(i)], p[uint(j)] = p[uint(j)], p[uint(i)] }
|
||||
func (p int32Slice) Less(i, j int) bool {
|
||||
return p[uint(i)] < p[uint(j)]
|
||||
}
|
||||
|
||||
type stringRv struct {
|
||||
v string
|
||||
r reflect.Value
|
||||
}
|
||||
type stringRvSlice []stringRv
|
||||
|
||||
func (p stringRvSlice) Len() int { return len(p) }
|
||||
func (p stringRvSlice) Swap(i, j int) { p[uint(i)], p[uint(j)] = p[uint(j)], p[uint(i)] }
|
||||
func (p stringRvSlice) Less(i, j int) bool {
|
||||
return p[uint(i)].v < p[uint(j)].v
|
||||
}
|
||||
|
||||
type float64Rv struct {
|
||||
v float64
|
||||
r reflect.Value
|
||||
}
|
||||
type float64RvSlice []float64Rv
|
||||
|
||||
func (p float64RvSlice) Len() int { return len(p) }
|
||||
func (p float64RvSlice) Swap(i, j int) { p[uint(i)], p[uint(j)] = p[uint(j)], p[uint(i)] }
|
||||
func (p float64RvSlice) Less(i, j int) bool {
|
||||
return p[uint(i)].v < p[uint(j)].v || isNaN64(p[uint(i)].v) && !isNaN64(p[uint(j)].v)
|
||||
}
|
||||
|
||||
type uint64Rv struct {
|
||||
v uint64
|
||||
r reflect.Value
|
||||
}
|
||||
type uint64RvSlice []uint64Rv
|
||||
|
||||
func (p uint64RvSlice) Len() int { return len(p) }
|
||||
func (p uint64RvSlice) Swap(i, j int) { p[uint(i)], p[uint(j)] = p[uint(j)], p[uint(i)] }
|
||||
func (p uint64RvSlice) Less(i, j int) bool {
|
||||
return p[uint(i)].v < p[uint(j)].v
|
||||
}
|
||||
|
||||
type int64Rv struct {
|
||||
v int64
|
||||
r reflect.Value
|
||||
}
|
||||
type int64RvSlice []int64Rv
|
||||
|
||||
func (p int64RvSlice) Len() int { return len(p) }
|
||||
func (p int64RvSlice) Swap(i, j int) { p[uint(i)], p[uint(j)] = p[uint(j)], p[uint(i)] }
|
||||
func (p int64RvSlice) Less(i, j int) bool {
|
||||
return p[uint(i)].v < p[uint(j)].v
|
||||
}
|
||||
|
||||
type boolRv struct {
|
||||
v bool
|
||||
r reflect.Value
|
||||
}
|
||||
type boolRvSlice []boolRv
|
||||
|
||||
func (p boolRvSlice) Len() int { return len(p) }
|
||||
func (p boolRvSlice) Swap(i, j int) { p[uint(i)], p[uint(j)] = p[uint(j)], p[uint(i)] }
|
||||
func (p boolRvSlice) Less(i, j int) bool {
|
||||
return !p[uint(i)].v && p[uint(j)].v
|
||||
}
|
||||
|
||||
type timeRv struct {
|
||||
v time.Time
|
||||
r reflect.Value
|
||||
}
|
||||
type timeRvSlice []timeRv
|
||||
|
||||
func (p timeRvSlice) Len() int { return len(p) }
|
||||
func (p timeRvSlice) Swap(i, j int) { p[uint(i)], p[uint(j)] = p[uint(j)], p[uint(i)] }
|
||||
func (p timeRvSlice) Less(i, j int) bool {
|
||||
return p[uint(i)].v.Before(p[uint(j)].v)
|
||||
}
|
||||
|
||||
type bytesRv struct {
|
||||
v []byte
|
||||
r reflect.Value
|
||||
}
|
||||
type bytesRvSlice []bytesRv
|
||||
|
||||
func (p bytesRvSlice) Len() int { return len(p) }
|
||||
func (p bytesRvSlice) Swap(i, j int) { p[uint(i)], p[uint(j)] = p[uint(j)], p[uint(i)] }
|
||||
func (p bytesRvSlice) Less(i, j int) bool {
|
||||
return bytes.Compare(p[uint(i)].v, p[uint(j)].v) == -1
|
||||
}
|
||||
|
||||
type bytesIntf struct {
|
||||
v []byte
|
||||
i interface{}
|
||||
}
|
||||
type bytesIntfSlice []bytesIntf
|
||||
|
||||
func (p bytesIntfSlice) Len() int { return len(p) }
|
||||
func (p bytesIntfSlice) Swap(i, j int) { p[uint(i)], p[uint(j)] = p[uint(j)], p[uint(i)] }
|
||||
func (p bytesIntfSlice) Less(i, j int) bool {
|
||||
return bytes.Compare(p[uint(i)].v, p[uint(j)].v) == -1
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
// 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.
|
||||
|
||||
// Code generated from sort-slice.go.tmpl - DO NOT EDIT.
|
||||
|
||||
{{/*
|
||||
xxxSlice
|
||||
xxxIntf
|
||||
xxxIntfSlice
|
||||
xxxRv
|
||||
xxxRvSlice
|
||||
|
||||
I'm now going to create them for
|
||||
- sortables
|
||||
- sortablesplus
|
||||
|
||||
With the parameters passed in sortables or sortablesplus,
|
||||
'time, 'bytes' are special, and correspond to time.Time and []byte respectively.
|
||||
*/}}
|
||||
|
||||
package codec
|
||||
|
||||
import "time"
|
||||
import "reflect"
|
||||
import "bytes"
|
||||
|
||||
{{/* func init() { _ = time.Unix } */}}
|
||||
|
||||
{{define "T"}}
|
||||
func (p {{ .Type }}) Len() int { return len(p) }
|
||||
func (p {{ .Type }}) Swap(i, j int) { p[uint(i)], p[uint(j)] = p[uint(j)], p[uint(i)] }
|
||||
func (p {{ .Type }}) Less(i, j int) bool {
|
||||
{{ if eq .Kind "bool" }} return !p[uint(i)]{{.V}} && p[uint(j)]{{.V}}
|
||||
{{ else if eq .Kind "float32" }} return p[uint(i)]{{.V}} < p[uint(j)]{{.V}} || isNaN32(p[uint(i)]{{.V}}) && !isNaN32(p[uint(j)]{{.V}})
|
||||
{{ else if eq .Kind "float64" }} return p[uint(i)]{{.V}} < p[uint(j)]{{.V}} || isNaN64(p[uint(i)]{{.V}}) && !isNaN64(p[uint(j)]{{.V}})
|
||||
{{ else if eq .Kind "time" }} return p[uint(i)]{{.V}}.Before(p[uint(j)]{{.V}})
|
||||
{{ else if eq .Kind "bytes" }} return bytes.Compare(p[uint(i)]{{.V}}, p[uint(j)]{{.V}}) == -1
|
||||
{{ else }} return p[uint(i)]{{.V}} < p[uint(j)]{{.V}}
|
||||
{{ end -}}
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{range $i, $v := sortables }}{{ $t := tshort $v }}
|
||||
type {{ $v }}Slice []{{ $t }}
|
||||
{{template "T" args "Kind" $v "Type" (print $v "Slice") "V" ""}}
|
||||
{{end}}
|
||||
|
||||
{{range $i, $v := sortablesplus }}{{ $t := tshort $v }}
|
||||
|
||||
type {{ $v }}Rv struct {
|
||||
v {{ $t }}
|
||||
r reflect.Value
|
||||
}
|
||||
type {{ $v }}RvSlice []{{ $v }}Rv
|
||||
{{template "T" args "Kind" $v "Type" (print $v "RvSlice") "V" ".v"}}
|
||||
|
||||
{{if eq $v "bytes" -}}
|
||||
type {{ $v }}Intf struct {
|
||||
v {{ $t }}
|
||||
i interface{}
|
||||
}
|
||||
type {{ $v }}IntfSlice []{{ $v }}Intf
|
||||
{{template "T" args "Kind" $v "Type" (print $v "IntfSlice") "V" ".v"}}
|
||||
{{end}}
|
||||
|
||||
{{end}}
|
|
@ -5,14 +5,17 @@
|
|||
# So it can process them (so we don't have to checkin the files).
|
||||
|
||||
# Ensure msgpack-python and cbor are installed first, using:
|
||||
# sudo apt-get install python-dev
|
||||
# sudo apt-get install python-pip
|
||||
# sudo apt install python-dev (may not be necessary)
|
||||
# sudo apt install python-pip # or python3-pip
|
||||
# pip install --user msgpack-python msgpack-rpc-python cbor
|
||||
|
||||
# Ensure all "string" keys are utf strings (else encoded as bytes)
|
||||
|
||||
from __future__ import print_function
|
||||
import cbor, msgpack, msgpackrpc, sys, os, threading
|
||||
|
||||
mylocaladdr="127.0.0.1" # localhost.localdomain localhost 127.0.0.1
|
||||
|
||||
def get_test_data_list():
|
||||
# get list with all primitive types, and a combo type
|
||||
l0 = [
|
||||
|
@ -30,11 +33,13 @@ def get_test_data_list():
|
|||
3232.0,
|
||||
6464.0,
|
||||
6464646464.0,
|
||||
160.0,
|
||||
1616.0,
|
||||
False,
|
||||
True,
|
||||
u"null",
|
||||
None,
|
||||
u"someday",
|
||||
u"some&day>some<day",
|
||||
1328176922000002000,
|
||||
u"",
|
||||
-2206187877999998000,
|
||||
|
@ -69,22 +74,20 @@ def build_test_data(destdir):
|
|||
for i in range(len(l)):
|
||||
# packer = msgpack.Packer()
|
||||
serialized = msgpack.dumps(l[i])
|
||||
f = open(os.path.join(destdir, str(i) + '.msgpack.golden'), 'wb')
|
||||
f.write(serialized)
|
||||
f.close()
|
||||
with open(os.path.join(destdir, str(i) + '.msgpack.golden'), 'wb') as f:
|
||||
f.write(serialized)
|
||||
serialized = cbor.dumps(l[i])
|
||||
f = open(os.path.join(destdir, str(i) + '.cbor.golden'), 'wb')
|
||||
f.write(serialized)
|
||||
f.close()
|
||||
with open(os.path.join(destdir, str(i) + '.cbor.golden'), 'wb') as f:
|
||||
f.write(serialized)
|
||||
|
||||
def doRpcServer(port, stopTimeSec):
|
||||
class EchoHandler(object):
|
||||
def Echo123(self, msg1, msg2, msg3):
|
||||
return ("1:%s 2:%s 3:%s" % (msg1, msg2, msg3))
|
||||
return ("1:%s 2:%s 3:%s" % (msg1.decode("utf-8"), msg2.decode("utf-8"), msg3.decode("utf-8")))
|
||||
def EchoStruct(self, msg):
|
||||
return ("%s" % msg)
|
||||
|
||||
addr = msgpackrpc.Address('localhost', port)
|
||||
addr = msgpackrpc.Address(mylocaladdr, port)
|
||||
server = msgpackrpc.Server(EchoHandler())
|
||||
server.listen(addr)
|
||||
# run thread to stop it after stopTimeSec seconds if > 0
|
||||
|
@ -96,17 +99,27 @@ def doRpcServer(port, stopTimeSec):
|
|||
server.start()
|
||||
|
||||
def doRpcClientToPythonSvc(port):
|
||||
address = msgpackrpc.Address('localhost', port)
|
||||
address = msgpackrpc.Address(mylocaladdr, port)
|
||||
client = msgpackrpc.Client(address, unpack_encoding='utf-8')
|
||||
print client.call("Echo123", "A1", "B2", "C3")
|
||||
print client.call("EchoStruct", {"A" :"Aa", "B":"Bb", "C":"Cc"})
|
||||
print(client.call("Echo123", "A1", "B2", "C3"))
|
||||
print(client.call("EchoStruct", {"A" :"Aa", "B":"Bb", "C":"Cc"}))
|
||||
|
||||
# def doCheckSocket(port):
|
||||
# print(">>>> port: ", port, " <<<<<")
|
||||
# sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
# result = sock.connect_ex(('127.0.0.1', port))
|
||||
# if result == 0:
|
||||
# print("\t>>>> Port is open")
|
||||
# else:
|
||||
# print("\t>>>> Port is not open")
|
||||
# sock.close()
|
||||
|
||||
def doRpcClientToGoSvc(port):
|
||||
# print ">>>> port: ", port, " <<<<<"
|
||||
address = msgpackrpc.Address('localhost', port)
|
||||
# doCheckSocket(port)
|
||||
address = msgpackrpc.Address(mylocaladdr, port)
|
||||
client = msgpackrpc.Client(address, unpack_encoding='utf-8')
|
||||
print client.call("TestRpcInt.Echo123", ["A1", "B2", "C3"])
|
||||
print client.call("TestRpcInt.EchoStruct", {"A" :"Aa", "B":"Bb", "C":"Cc"})
|
||||
print(client.call("TestRpcInt.Echo123", ["A1", "B2", "C3"]))
|
||||
print(client.call("TestRpcInt.EchoStruct", {"A" :"Aa", "B":"Bb", "C":"Cc"}))
|
||||
|
||||
def doMain(args):
|
||||
if len(args) == 2 and args[0] == "testdata":
|
||||
|
@ -123,4 +136,3 @@ def doMain(args):
|
|||
|
||||
if __name__ == "__main__":
|
||||
doMain(sys.argv[1:])
|
||||
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Run all the different permutations of all the tests.
|
||||
# This helps ensure that nothing gets broken.
|
||||
|
||||
_run() {
|
||||
# 1. VARIATIONS: regular (t), canonical (c), IO R/W (i),
|
||||
# binc-nosymbols (n), struct2array (s), intern string (e),
|
||||
# json-indent (d), circular (l)
|
||||
# 2. MODE: reflection (r), external (x), codecgen (g), unsafe (u), notfastpath (f)
|
||||
# 3. OPTIONS: verbose (v), reset (z), must (m),
|
||||
#
|
||||
# Use combinations of mode to get exactly what you want,
|
||||
# and then pass the variations you need.
|
||||
|
||||
ztags=""
|
||||
zargs=""
|
||||
local OPTIND
|
||||
OPTIND=1
|
||||
while getopts "_xurtcinsvgzmefdl" flag
|
||||
do
|
||||
case "x$flag" in
|
||||
'xr') ;;
|
||||
'xf') ztags="$ztags notfastpath" ;;
|
||||
'xg') ztags="$ztags codecgen" ;;
|
||||
'xx') ztags="$ztags x" ;;
|
||||
'xu') ztags="$ztags unsafe" ;;
|
||||
'xv') zargs="$zargs -tv" ;;
|
||||
'xz') zargs="$zargs -tr" ;;
|
||||
'xm') zargs="$zargs -tm" ;;
|
||||
'xl') zargs="$zargs -tl" ;;
|
||||
*) ;;
|
||||
esac
|
||||
done
|
||||
# shift $((OPTIND-1))
|
||||
printf '............. TAGS: %s .............\n' "$ztags"
|
||||
# echo ">>>>>>> TAGS: $ztags"
|
||||
|
||||
OPTIND=1
|
||||
while getopts "_xurtcinsvgzmefdl" flag
|
||||
do
|
||||
case "x$flag" in
|
||||
'xt') printf ">>>>>>> REGULAR : "; go test "-tags=$ztags" $zargs ; sleep 2 ;;
|
||||
'xc') printf ">>>>>>> CANONICAL : "; go test "-tags=$ztags" $zargs -tc; sleep 2 ;;
|
||||
'xi') printf ">>>>>>> I/O : "; go test "-tags=$ztags" $zargs -ti; sleep 2 ;;
|
||||
'xn') printf ">>>>>>> NO_SYMBOLS : "; go test "-tags=$ztags" -run=Binc $zargs -tn; sleep 2 ;;
|
||||
'xs') printf ">>>>>>> TO_ARRAY : "; go test "-tags=$ztags" $zargs -ts; sleep 2 ;;
|
||||
'xe') printf ">>>>>>> INTERN : "; go test "-tags=$ztags" $zargs -te; sleep 2 ;;
|
||||
'xd') printf ">>>>>>> INDENT : ";
|
||||
go test "-tags=$ztags" -run=JsonCodecsTable -td=-1 $zargs;
|
||||
go test "-tags=$ztags" -run=JsonCodecsTable -td=8 $zargs;
|
||||
sleep 2 ;;
|
||||
*) ;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND-1))
|
||||
|
||||
OPTIND=1
|
||||
}
|
||||
|
||||
# echo ">>>>>>> RUNNING VARIATIONS OF TESTS"
|
||||
if [[ "x$@" = "x" ]]; then
|
||||
# All: r, x, g, gu
|
||||
_run "-_tcinsed_ml" # regular
|
||||
_run "-_tcinsed_ml_z" # regular with reset
|
||||
_run "-_tcinsed_ml_f" # regular with no fastpath (notfastpath)
|
||||
_run "-x_tcinsed_ml" # external
|
||||
_run "-gx_tcinsed_ml" # codecgen: requires external
|
||||
_run "-gxu_tcinsed_ml" # codecgen + unsafe
|
||||
elif [[ "x$@" = "x-Z" ]]; then
|
||||
# Regular
|
||||
_run "-_tcinsed_ml" # regular
|
||||
_run "-_tcinsed_ml_z" # regular with reset
|
||||
elif [[ "x$@" = "x-F" ]]; then
|
||||
# regular with notfastpath
|
||||
_run "-_tcinsed_ml_f" # regular
|
||||
_run "-_tcinsed_ml_zf" # regular with reset
|
||||
else
|
||||
_run "$@"
|
||||
fi
|
|
@ -1,233 +0,0 @@
|
|||
// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
|
||||
// Use of this source code is governed by a MIT license found in the LICENSE file.
|
||||
|
||||
package codec
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
timeDigits = [...]byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
|
||||
timeExtEncFn = func(rv reflect.Value) (bs []byte, err error) {
|
||||
defer panicToErr(&err)
|
||||
bs = timeExt{}.WriteExt(rv.Interface())
|
||||
return
|
||||
}
|
||||
timeExtDecFn = func(rv reflect.Value, bs []byte) (err error) {
|
||||
defer panicToErr(&err)
|
||||
timeExt{}.ReadExt(rv.Interface(), bs)
|
||||
return
|
||||
}
|
||||
)
|
||||
|
||||
type timeExt struct{}
|
||||
|
||||
func (x timeExt) WriteExt(v interface{}) (bs []byte) {
|
||||
switch v2 := v.(type) {
|
||||
case time.Time:
|
||||
bs = encodeTime(v2)
|
||||
case *time.Time:
|
||||
bs = encodeTime(*v2)
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported format for time conversion: expecting time.Time; got %T", v2))
|
||||
}
|
||||
return
|
||||
}
|
||||
func (x timeExt) ReadExt(v interface{}, bs []byte) {
|
||||
tt, err := decodeTime(bs)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
*(v.(*time.Time)) = tt
|
||||
}
|
||||
|
||||
func (x timeExt) ConvertExt(v interface{}) interface{} {
|
||||
return x.WriteExt(v)
|
||||
}
|
||||
func (x timeExt) UpdateExt(v interface{}, src interface{}) {
|
||||
x.ReadExt(v, src.([]byte))
|
||||
}
|
||||
|
||||
// EncodeTime encodes a time.Time as a []byte, including
|
||||
// information on the instant in time and UTC offset.
|
||||
//
|
||||
// Format Description
|
||||
//
|
||||
// A timestamp is composed of 3 components:
|
||||
//
|
||||
// - secs: signed integer representing seconds since unix epoch
|
||||
// - nsces: unsigned integer representing fractional seconds as a
|
||||
// nanosecond offset within secs, in the range 0 <= nsecs < 1e9
|
||||
// - tz: signed integer representing timezone offset in minutes east of UTC,
|
||||
// and a dst (daylight savings time) flag
|
||||
//
|
||||
// When encoding a timestamp, the first byte is the descriptor, which
|
||||
// defines which components are encoded and how many bytes are used to
|
||||
// encode secs and nsecs components. *If secs/nsecs is 0 or tz is UTC, it
|
||||
// is not encoded in the byte array explicitly*.
|
||||
//
|
||||
// Descriptor 8 bits are of the form `A B C DDD EE`:
|
||||
// A: Is secs component encoded? 1 = true
|
||||
// B: Is nsecs component encoded? 1 = true
|
||||
// C: Is tz component encoded? 1 = true
|
||||
// DDD: Number of extra bytes for secs (range 0-7).
|
||||
// If A = 1, secs encoded in DDD+1 bytes.
|
||||
// If A = 0, secs is not encoded, and is assumed to be 0.
|
||||
// If A = 1, then we need at least 1 byte to encode secs.
|
||||
// DDD says the number of extra bytes beyond that 1.
|
||||
// E.g. if DDD=0, then secs is represented in 1 byte.
|
||||
// if DDD=2, then secs is represented in 3 bytes.
|
||||
// EE: Number of extra bytes for nsecs (range 0-3).
|
||||
// If B = 1, nsecs encoded in EE+1 bytes (similar to secs/DDD above)
|
||||
//
|
||||
// Following the descriptor bytes, subsequent bytes are:
|
||||
//
|
||||
// secs component encoded in `DDD + 1` bytes (if A == 1)
|
||||
// nsecs component encoded in `EE + 1` bytes (if B == 1)
|
||||
// tz component encoded in 2 bytes (if C == 1)
|
||||
//
|
||||
// secs and nsecs components are integers encoded in a BigEndian
|
||||
// 2-complement encoding format.
|
||||
//
|
||||
// tz component is encoded as 2 bytes (16 bits). Most significant bit 15 to
|
||||
// Least significant bit 0 are described below:
|
||||
//
|
||||
// Timezone offset has a range of -12:00 to +14:00 (ie -720 to +840 minutes).
|
||||
// Bit 15 = have\_dst: set to 1 if we set the dst flag.
|
||||
// Bit 14 = dst\_on: set to 1 if dst is in effect at the time, or 0 if not.
|
||||
// Bits 13..0 = timezone offset in minutes. It is a signed integer in Big Endian format.
|
||||
//
|
||||
func encodeTime(t time.Time) []byte {
|
||||
//t := rv.Interface().(time.Time)
|
||||
tsecs, tnsecs := t.Unix(), t.Nanosecond()
|
||||
var (
|
||||
bd byte
|
||||
btmp [8]byte
|
||||
bs [16]byte
|
||||
i int = 1
|
||||
)
|
||||
l := t.Location()
|
||||
if l == time.UTC {
|
||||
l = nil
|
||||
}
|
||||
if tsecs != 0 {
|
||||
bd = bd | 0x80
|
||||
bigen.PutUint64(btmp[:], uint64(tsecs))
|
||||
f := pruneSignExt(btmp[:], tsecs >= 0)
|
||||
bd = bd | (byte(7-f) << 2)
|
||||
copy(bs[i:], btmp[f:])
|
||||
i = i + (8 - f)
|
||||
}
|
||||
if tnsecs != 0 {
|
||||
bd = bd | 0x40
|
||||
bigen.PutUint32(btmp[:4], uint32(tnsecs))
|
||||
f := pruneSignExt(btmp[:4], true)
|
||||
bd = bd | byte(3-f)
|
||||
copy(bs[i:], btmp[f:4])
|
||||
i = i + (4 - f)
|
||||
}
|
||||
if l != nil {
|
||||
bd = bd | 0x20
|
||||
// Note that Go Libs do not give access to dst flag.
|
||||
_, zoneOffset := t.Zone()
|
||||
//zoneName, zoneOffset := t.Zone()
|
||||
zoneOffset /= 60
|
||||
z := uint16(zoneOffset)
|
||||
bigen.PutUint16(btmp[:2], z)
|
||||
// clear dst flags
|
||||
bs[i] = btmp[0] & 0x3f
|
||||
bs[i+1] = btmp[1]
|
||||
i = i + 2
|
||||
}
|
||||
bs[0] = bd
|
||||
return bs[0:i]
|
||||
}
|
||||
|
||||
// DecodeTime decodes a []byte into a time.Time.
|
||||
func decodeTime(bs []byte) (tt time.Time, err error) {
|
||||
bd := bs[0]
|
||||
var (
|
||||
tsec int64
|
||||
tnsec uint32
|
||||
tz uint16
|
||||
i byte = 1
|
||||
i2 byte
|
||||
n byte
|
||||
)
|
||||
if bd&(1<<7) != 0 {
|
||||
var btmp [8]byte
|
||||
n = ((bd >> 2) & 0x7) + 1
|
||||
i2 = i + n
|
||||
copy(btmp[8-n:], bs[i:i2])
|
||||
//if first bit of bs[i] is set, then fill btmp[0..8-n] with 0xff (ie sign extend it)
|
||||
if bs[i]&(1<<7) != 0 {
|
||||
copy(btmp[0:8-n], bsAll0xff)
|
||||
//for j,k := byte(0), 8-n; j < k; j++ { btmp[j] = 0xff }
|
||||
}
|
||||
i = i2
|
||||
tsec = int64(bigen.Uint64(btmp[:]))
|
||||
}
|
||||
if bd&(1<<6) != 0 {
|
||||
var btmp [4]byte
|
||||
n = (bd & 0x3) + 1
|
||||
i2 = i + n
|
||||
copy(btmp[4-n:], bs[i:i2])
|
||||
i = i2
|
||||
tnsec = bigen.Uint32(btmp[:])
|
||||
}
|
||||
if bd&(1<<5) == 0 {
|
||||
tt = time.Unix(tsec, int64(tnsec)).UTC()
|
||||
return
|
||||
}
|
||||
// In stdlib time.Parse, when a date is parsed without a zone name, it uses "" as zone name.
|
||||
// However, we need name here, so it can be shown when time is printed.
|
||||
// Zone name is in form: UTC-08:00.
|
||||
// Note that Go Libs do not give access to dst flag, so we ignore dst bits
|
||||
|
||||
i2 = i + 2
|
||||
tz = bigen.Uint16(bs[i:i2])
|
||||
i = i2
|
||||
// sign extend sign bit into top 2 MSB (which were dst bits):
|
||||
if tz&(1<<13) == 0 { // positive
|
||||
tz = tz & 0x3fff //clear 2 MSBs: dst bits
|
||||
} else { // negative
|
||||
tz = tz | 0xc000 //set 2 MSBs: dst bits
|
||||
//tzname[3] = '-' (TODO: verify. this works here)
|
||||
}
|
||||
tzint := int16(tz)
|
||||
if tzint == 0 {
|
||||
tt = time.Unix(tsec, int64(tnsec)).UTC()
|
||||
} else {
|
||||
// For Go Time, do not use a descriptive timezone.
|
||||
// It's unnecessary, and makes it harder to do a reflect.DeepEqual.
|
||||
// The Offset already tells what the offset should be, if not on UTC and unknown zone name.
|
||||
// var zoneName = timeLocUTCName(tzint)
|
||||
tt = time.Unix(tsec, int64(tnsec)).In(time.FixedZone("", int(tzint)*60))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func timeLocUTCName(tzint int16) string {
|
||||
if tzint == 0 {
|
||||
return "UTC"
|
||||
}
|
||||
var tzname = []byte("UTC+00:00")
|
||||
//tzname := fmt.Sprintf("UTC%s%02d:%02d", tzsign, tz/60, tz%60) //perf issue using Sprintf. inline below.
|
||||
//tzhr, tzmin := tz/60, tz%60 //faster if u convert to int first
|
||||
var tzhr, tzmin int16
|
||||
if tzint < 0 {
|
||||
tzname[3] = '-' // (TODO: verify. this works here)
|
||||
tzhr, tzmin = -tzint/60, (-tzint)%60
|
||||
} else {
|
||||
tzhr, tzmin = tzint/60, tzint%60
|
||||
}
|
||||
tzname[4] = timeDigits[tzhr/10]
|
||||
tzname[5] = timeDigits[tzhr%10]
|
||||
tzname[7] = timeDigits[tzmin/10]
|
||||
tzname[8] = timeDigits[tzmin%10]
|
||||
return string(tzname)
|
||||
//return time.FixedZone(string(tzname), int(tzint)*60)
|
||||
}
|
|
@ -0,0 +1,287 @@
|
|||
// 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"
|
||||
|
||||
// encWriter abstracts writing to a byte array or to an io.Writer.
|
||||
type encWriter interface {
|
||||
writeb([]byte)
|
||||
writestr(string)
|
||||
writeqstr(string) // write string wrapped in quotes ie "..."
|
||||
writen1(byte)
|
||||
|
||||
// add convenience functions for writing 2,4
|
||||
writen2(byte, byte)
|
||||
writen4([4]byte)
|
||||
writen8([8]byte)
|
||||
|
||||
end()
|
||||
}
|
||||
|
||||
// ---------------------------------------------
|
||||
|
||||
type bufioEncWriter struct {
|
||||
w io.Writer
|
||||
|
||||
buf []byte
|
||||
|
||||
n int
|
||||
|
||||
b [16]byte // scratch buffer and padding (cache-aligned)
|
||||
}
|
||||
|
||||
func (z *bufioEncWriter) reset(w io.Writer, bufsize int, blist *bytesFreelist) {
|
||||
z.w = w
|
||||
z.n = 0
|
||||
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)
|
||||
}
|
||||
if len(z.b) > bufsize {
|
||||
z.buf = z.b[:]
|
||||
} else {
|
||||
z.buf = blist.get(bufsize)
|
||||
}
|
||||
}
|
||||
z.buf = z.buf[:cap(z.buf)]
|
||||
}
|
||||
|
||||
func (z *bufioEncWriter) flushErr() (err error) {
|
||||
n, err := z.w.Write(z.buf[:z.n])
|
||||
z.n -= n
|
||||
if z.n > 0 {
|
||||
if err == nil {
|
||||
err = io.ErrShortWrite
|
||||
}
|
||||
if n > 0 {
|
||||
copy(z.buf, z.buf[n:z.n+n])
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (z *bufioEncWriter) flush() {
|
||||
halt.onerror(z.flushErr())
|
||||
}
|
||||
|
||||
func (z *bufioEncWriter) writeb(s []byte) {
|
||||
LOOP:
|
||||
a := len(z.buf) - z.n
|
||||
if len(s) > a {
|
||||
z.n += copy(z.buf[z.n:], s[:a])
|
||||
s = s[a:]
|
||||
z.flush()
|
||||
goto LOOP
|
||||
}
|
||||
z.n += copy(z.buf[z.n:], s)
|
||||
}
|
||||
|
||||
func (z *bufioEncWriter) writestr(s string) {
|
||||
// z.writeb(bytesView(s)) // inlined below
|
||||
LOOP:
|
||||
a := len(z.buf) - z.n
|
||||
if len(s) > a {
|
||||
z.n += copy(z.buf[z.n:], s[:a])
|
||||
s = s[a:]
|
||||
z.flush()
|
||||
goto LOOP
|
||||
}
|
||||
z.n += copy(z.buf[z.n:], s)
|
||||
}
|
||||
|
||||
func (z *bufioEncWriter) writeqstr(s string) {
|
||||
// z.writen1('"')
|
||||
// z.writestr(s)
|
||||
// z.writen1('"')
|
||||
|
||||
if z.n+len(s)+2 > len(z.buf) {
|
||||
z.flush()
|
||||
}
|
||||
z.buf[z.n] = '"'
|
||||
z.n++
|
||||
LOOP:
|
||||
a := len(z.buf) - z.n
|
||||
if len(s)+1 > a {
|
||||
z.n += copy(z.buf[z.n:], s[:a])
|
||||
s = s[a:]
|
||||
z.flush()
|
||||
goto LOOP
|
||||
}
|
||||
z.n += copy(z.buf[z.n:], s)
|
||||
z.buf[z.n] = '"'
|
||||
z.n++
|
||||
}
|
||||
|
||||
func (z *bufioEncWriter) writen1(b1 byte) {
|
||||
if 1 > len(z.buf)-z.n {
|
||||
z.flush()
|
||||
}
|
||||
z.buf[z.n] = b1
|
||||
z.n++
|
||||
}
|
||||
func (z *bufioEncWriter) writen2(b1, b2 byte) {
|
||||
if 2 > len(z.buf)-z.n {
|
||||
z.flush()
|
||||
}
|
||||
z.buf[z.n+1] = b2
|
||||
z.buf[z.n] = b1
|
||||
z.n += 2
|
||||
}
|
||||
func (z *bufioEncWriter) writen4(b [4]byte) {
|
||||
if 4 > len(z.buf)-z.n {
|
||||
z.flush()
|
||||
}
|
||||
copy(z.buf[z.n:], b[:])
|
||||
z.n += 4
|
||||
}
|
||||
|
||||
func (z *bufioEncWriter) writen8(b [8]byte) {
|
||||
if 8 > len(z.buf)-z.n {
|
||||
z.flush()
|
||||
}
|
||||
copy(z.buf[z.n:], b[:])
|
||||
z.n += 8
|
||||
}
|
||||
|
||||
func (z *bufioEncWriter) endErr() (err error) {
|
||||
if z.n > 0 {
|
||||
err = z.flushErr()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ---------------------------------------------
|
||||
|
||||
// bytesEncAppender implements encWriter and can write to an byte slice.
|
||||
type bytesEncAppender struct {
|
||||
b []byte
|
||||
out *[]byte
|
||||
}
|
||||
|
||||
func (z *bytesEncAppender) writeb(s []byte) {
|
||||
z.b = append(z.b, s...)
|
||||
}
|
||||
func (z *bytesEncAppender) writestr(s string) {
|
||||
z.b = append(z.b, s...)
|
||||
}
|
||||
func (z *bytesEncAppender) writeqstr(s string) {
|
||||
z.b = append(append(append(z.b, '"'), s...), '"')
|
||||
// z.b = append(z.b, '"')
|
||||
// z.b = append(z.b, s...)
|
||||
// z.b = append(z.b, '"')
|
||||
}
|
||||
func (z *bytesEncAppender) writen1(b1 byte) {
|
||||
z.b = append(z.b, b1)
|
||||
}
|
||||
func (z *bytesEncAppender) writen2(b1, b2 byte) {
|
||||
z.b = append(z.b, b1, b2)
|
||||
}
|
||||
func (z *bytesEncAppender) writen4(b [4]byte) {
|
||||
z.b = append(z.b, b[:]...)
|
||||
}
|
||||
func (z *bytesEncAppender) writen8(b [8]byte) {
|
||||
z.b = append(z.b, b[:]...)
|
||||
}
|
||||
func (z *bytesEncAppender) endErr() error {
|
||||
*(z.out) = z.b
|
||||
return nil
|
||||
}
|
||||
func (z *bytesEncAppender) reset(in []byte, out *[]byte) {
|
||||
z.b = in[:0]
|
||||
z.out = out
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
|
||||
type encWr struct {
|
||||
bytes bool // encoding to []byte
|
||||
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)
|
||||
wb bytesEncAppender
|
||||
wf *bufioEncWriter
|
||||
}
|
||||
|
||||
// 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) 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) 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 {
|
||||
z.wb.writen4(b)
|
||||
} else {
|
||||
z.wf.writen4(b)
|
||||
}
|
||||
}
|
||||
func (z *encWr) writen8(b [8]byte) {
|
||||
if z.bytes {
|
||||
z.wb.writen8(b)
|
||||
} else {
|
||||
z.wf.writen8(b)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
|
@ -360,7 +360,7 @@ github.com/hashicorp/hcl/v2/hclparse
|
|||
github.com/hashicorp/hcl/v2/hclsyntax
|
||||
github.com/hashicorp/hcl/v2/hclwrite
|
||||
github.com/hashicorp/hcl/v2/json
|
||||
# github.com/hashicorp/packer-plugin-sdk v0.0.11
|
||||
# github.com/hashicorp/packer-plugin-sdk v0.0.12
|
||||
github.com/hashicorp/packer-plugin-sdk/acctest
|
||||
github.com/hashicorp/packer-plugin-sdk/acctest/provisioneracc
|
||||
github.com/hashicorp/packer-plugin-sdk/acctest/testutils
|
||||
|
@ -585,7 +585,7 @@ github.com/ucloud/ucloud-sdk-go/ucloud/response
|
|||
github.com/ucloud/ucloud-sdk-go/ucloud/version
|
||||
# github.com/ufilesdk-dev/ufile-gosdk v0.0.0-20190830075812-b4dbc4ef43a6
|
||||
github.com/ufilesdk-dev/ufile-gosdk
|
||||
# github.com/ugorji/go v0.0.0-20151218193438-646ae4a518c1
|
||||
# github.com/ugorji/go/codec v1.2.4
|
||||
github.com/ugorji/go/codec
|
||||
# github.com/ulikunitz/xz v0.5.5
|
||||
github.com/ulikunitz/xz
|
||||
|
|
Loading…
Reference in New Issue