go mod vendor
This commit is contained in:
parent
991af72758
commit
1ac41e91c1
|
@ -9,12 +9,23 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"net/url"
|
"net/url"
|
||||||
"sort"
|
"sort"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Credential is the information of credential keys
|
// Credential is the information of credential keys
|
||||||
type Credential struct {
|
type Credential struct {
|
||||||
PublicKey string
|
// UCloud Public Key
|
||||||
|
PublicKey string
|
||||||
|
|
||||||
|
// UCloud Private Key
|
||||||
PrivateKey string
|
PrivateKey string
|
||||||
|
|
||||||
|
// UCloud STS token for temporary usage
|
||||||
|
SecurityToken string
|
||||||
|
|
||||||
|
// Time the credentials will expire.
|
||||||
|
CanExpire bool
|
||||||
|
Expires time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCredential will return credential config with default values
|
// NewCredential will return credential config with default values
|
||||||
|
@ -38,11 +49,18 @@ func (c *Credential) BuildCredentialedQuery(params map[string]string) string {
|
||||||
for k, v := range params {
|
for k, v := range params {
|
||||||
urlValues.Set(k, v)
|
urlValues.Set(k, v)
|
||||||
}
|
}
|
||||||
|
if len(c.SecurityToken) != 0 {
|
||||||
|
urlValues.Set("SecurityToken", c.SecurityToken)
|
||||||
|
}
|
||||||
urlValues.Set("PublicKey", c.PublicKey)
|
urlValues.Set("PublicKey", c.PublicKey)
|
||||||
urlValues.Set("Signature", c.verifyAc(urlValues))
|
urlValues.Set("Signature", c.verifyAc(urlValues))
|
||||||
return urlValues.Encode()
|
return urlValues.Encode()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Credential) IsExpired() bool {
|
||||||
|
return c.CanExpire && time.Now().After(c.Expires)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Credential) verifyAc(urlValues url.Values) string {
|
func (c *Credential) verifyAc(urlValues url.Values) string {
|
||||||
// sort keys
|
// sort keys
|
||||||
var keys []string
|
var keys []string
|
||||||
|
|
|
@ -4,6 +4,7 @@ Package ucloud is a package of utilities to setup ucloud sdk and improve using e
|
||||||
package ucloud
|
package ucloud
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ucloud/ucloud-sdk-go/private/utils"
|
"github.com/ucloud/ucloud-sdk-go/private/utils"
|
||||||
|
@ -71,7 +72,7 @@ func (c *Client) SetHttpClient(httpClient http.Client) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCredential will return the creadential config of client.
|
// GetCredential will return the credential config of client.
|
||||||
func (c *Client) GetCredential() *auth.Credential {
|
func (c *Client) GetCredential() *auth.Credential {
|
||||||
return c.credential
|
return c.credential
|
||||||
}
|
}
|
||||||
|
@ -108,6 +109,13 @@ func (c *Client) InvokeActionWithPatcher(action string, req request.Common, resp
|
||||||
req.SetRequestTime(time.Now())
|
req.SetRequestTime(time.Now())
|
||||||
resp.SetRequest(req)
|
resp.SetRequest(req)
|
||||||
|
|
||||||
|
if c.credential.CanExpire && c.credential.IsExpired() {
|
||||||
|
return uerr.NewClientError(
|
||||||
|
uerr.ErrCredentialExpired,
|
||||||
|
fmt.Errorf("credential is expired at %s", c.credential.Expires.Format(time.RFC3339)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
for _, handler := range c.requestHandlers {
|
for _, handler := range c.requestHandlers {
|
||||||
req, err = handler(c, req)
|
req, err = handler(c, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -142,7 +150,7 @@ func (c *Client) InvokeActionWithPatcher(action string, req request.Common, resp
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// use patch object to resolve the http response body
|
// use patch object to resolve the http response body
|
||||||
// in general, it will be fix common server error before server bugfix is released.
|
// in general, it will be fix common server error before server bug fix is released.
|
||||||
body := httpResp.GetBody()
|
body := httpResp.GetBody()
|
||||||
|
|
||||||
for _, patch := range patches {
|
for _, patch := range patches {
|
||||||
|
|
|
@ -20,6 +20,8 @@ var (
|
||||||
|
|
||||||
// ErrUnexpected is the error for any unexpected error
|
// ErrUnexpected is the error for any unexpected error
|
||||||
ErrUnexpected = "client.UnexpectedError"
|
ErrUnexpected = "client.UnexpectedError"
|
||||||
|
|
||||||
|
ErrCredentialExpired = "client.CredentialExpiredError"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ClientError is the ucloud common errorfor server response
|
// ClientError is the ucloud common errorfor server response
|
||||||
|
|
|
@ -4,4 +4,4 @@ Package version is the version of sdk
|
||||||
package version
|
package version
|
||||||
|
|
||||||
// Version see also semantic version: https://semver.org/
|
// Version see also semantic version: https://semver.org/
|
||||||
const Version = "0.11.1"
|
const Version = "0.12.0"
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
[查看文件信息](https://godoc.org/pkg/github.com/ufilesdk-dev/ufile-gosdk/#UFileRequest.HeadFile)
|
[查看文件信息](https://godoc.org/pkg/github.com/ufilesdk-dev/ufile-gosdk/#UFileRequest.HeadFile)
|
||||||
[下载文件](https://godoc.org/pkg/github.com/ufilesdk-dev/ufile-gosdk/#UFileRequest.DownloadFile)
|
[下载文件](https://godoc.org/pkg/github.com/ufilesdk-dev/ufile-gosdk/#UFileRequest.DownloadFile)
|
||||||
[比对本地与远程文件的 Etag](https://godoc.org/pkg/github.com/ufilesdk-dev/ufile-gosdk/#UFileRequest.CompareFileEtag)
|
[比对本地与远程文件的 Etag](https://godoc.org/pkg/github.com/ufilesdk-dev/ufile-gosdk/#UFileRequest.CompareFileEtag)
|
||||||
|
[拷贝文件](https://godoc.org/github.com/ufilesdk-dev/ufile-gosdk#UFileRequest.Copy)
|
||||||
|
[重命名文件](https://godoc.org/github.com/ufilesdk-dev/ufile-gosdk#UFileRequest.Rename)
|
||||||
[Put 带回调上传](https://godoc.org/pkg/github.com/ufilesdk-dev/ufile-gosdk/#UFileRequest.PutFileWithPolicy)
|
[Put 带回调上传](https://godoc.org/pkg/github.com/ufilesdk-dev/ufile-gosdk/#UFileRequest.PutFileWithPolicy)
|
||||||
[同步分片上传-带回调](https://godoc.org/pkg/github.com/ufilesdk-dev/ufile-gosdk/#UFileRequest.MPutWithPolicy),
|
[同步分片上传-带回调](https://godoc.org/pkg/github.com/ufilesdk-dev/ufile-gosdk/#UFileRequest.MPutWithPolicy),
|
||||||
[异步分片上传-带回调](https://godoc.org/pkg/github.com/ufilesdk-dev/ufile-gosdk/#UFileRequest.AsyncMPutWithPolicy)
|
[异步分片上传-带回调](https://godoc.org/pkg/github.com/ufilesdk-dev/ufile-gosdk/#UFileRequest.AsyncMPutWithPolicy)
|
||||||
|
|
|
@ -30,7 +30,7 @@ func NewAuth(publicKey, privateKey string) Auth {
|
||||||
//Authorization 构造一个主要用于上传文件的签名,返回 HMAC-Sh1 的签名字符串,可以直接填充到 HTTP authorization header 里面。
|
//Authorization 构造一个主要用于上传文件的签名,返回 HMAC-Sh1 的签名字符串,可以直接填充到 HTTP authorization header 里面。
|
||||||
//key 是传到 ufile 所使用的文件名,bucekt 是文件上传后存放的 bucket。
|
//key 是传到 ufile 所使用的文件名,bucekt 是文件上传后存放的 bucket。
|
||||||
//method 就是你当前这个 HTTP 请求的 Method。
|
//method 就是你当前这个 HTTP 请求的 Method。
|
||||||
//header 就是你当前这个 HTTP 的 header,我们主要拿里面的 content-type 来做签名 hash 计算。
|
//header 就是你当前这个 HTTP 的 header。
|
||||||
func (A Auth) Authorization(method, bucket, key string, header http.Header) string {
|
func (A Auth) Authorization(method, bucket, key string, header http.Header) string {
|
||||||
var sigData string
|
var sigData string
|
||||||
method = strings.ToUpper(method)
|
method = strings.ToUpper(method)
|
||||||
|
@ -40,6 +40,7 @@ func (A Auth) Authorization(method, bucket, key string, header http.Header) stri
|
||||||
date := header.Get("Date")
|
date := header.Get("Date")
|
||||||
|
|
||||||
sigData = method + "\n" + md5 + "\n" + contentType + "\n" + date + "\n"
|
sigData = method + "\n" + md5 + "\n" + contentType + "\n" + date + "\n"
|
||||||
|
sigData += A.CanonicalizedUcloudHeaders(header)
|
||||||
resource := "/" + bucket + "/" + key
|
resource := "/" + bucket + "/" + key
|
||||||
sigData += resource
|
sigData += resource
|
||||||
|
|
||||||
|
@ -114,3 +115,25 @@ func (A Auth) AuthorizationBucketMgr(query url.Values) string {
|
||||||
query.Add("Signature", fmt.Sprintf("%x", h.Sum(nil)))
|
query.Add("Signature", fmt.Sprintf("%x", h.Sum(nil)))
|
||||||
return query.Encode()
|
return query.Encode()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//CanonicalizedUcloudHeaders 用于将自定义请求报头规范化为string
|
||||||
|
//ucloudHeader 支持自定义请求头
|
||||||
|
func (A Auth) CanonicalizedUcloudHeaders(ucloudHeader http.Header) string {
|
||||||
|
keys := make([]string, 0)
|
||||||
|
headers := make(map[string]string, 0)
|
||||||
|
for k := range ucloudHeader {
|
||||||
|
newkey := strings.ToLower(k)
|
||||||
|
if strings.HasPrefix(newkey, "x-ufile-") || strings.HasPrefix(newkey, "x-ucloud-") {
|
||||||
|
headers[newkey] = strings.TrimSpace(ucloudHeader[k][0])
|
||||||
|
keys = append(keys, newkey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Strings(keys)
|
||||||
|
|
||||||
|
s := ""
|
||||||
|
for _, k := range keys {
|
||||||
|
v := headers[k]
|
||||||
|
s += k + ":" + v + "\n"
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
|
@ -378,3 +378,42 @@ func (u *UFileRequest) ClassSwitch(keyName string, storageClass string) (err err
|
||||||
req.Header.Add("authorization", authorization)
|
req.Header.Add("authorization", authorization)
|
||||||
return u.request(req)
|
return u.request(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Rename 重命名指定文件
|
||||||
|
//keyName 需要被重命名的源文件
|
||||||
|
//newKeyName 修改后的新文件名
|
||||||
|
//force 如果已存在同名文件,值为"true"则覆盖,否则会操作失败
|
||||||
|
func (u *UFileRequest) Rename(keyName, newKeyName, force string) (err error) {
|
||||||
|
|
||||||
|
query := url.Values{}
|
||||||
|
query.Add("newFileName", newKeyName)
|
||||||
|
query.Add("force", force)
|
||||||
|
reqURL := u.genFileURL(keyName) + "?" + query.Encode()
|
||||||
|
|
||||||
|
req, err := http.NewRequest("PUT", reqURL, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
authorization := u.Auth.Authorization("PUT", u.BucketName, keyName, req.Header)
|
||||||
|
req.Header.Add("authorization", authorization)
|
||||||
|
return u.request(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Copy 从同组织下的源Bucket中拷贝指定文件到目的Bucket中,并以新文件名命名
|
||||||
|
//dstkeyName 拷贝到目的Bucket后的新文件名
|
||||||
|
//srcBucketName 待拷贝文件所在的源Bucket名称
|
||||||
|
//srcKeyName 待拷贝文件名称
|
||||||
|
func (u *UFileRequest) Copy(dstkeyName, srcBucketName, srcKeyName string) (err error) {
|
||||||
|
|
||||||
|
reqURL := u.genFileURL(dstkeyName)
|
||||||
|
|
||||||
|
req, err := http.NewRequest("PUT", reqURL, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.Header.Add("X-Ufile-Copy-Source", "/" + srcBucketName + "/" + srcKeyName)
|
||||||
|
|
||||||
|
authorization := u.Auth.Authorization("PUT", u.BucketName, dstkeyName, req.Header)
|
||||||
|
req.Header.Add("authorization", authorization)
|
||||||
|
return u.request(req)
|
||||||
|
}
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
|
// 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.
|
// Use of this source code is governed by a MIT license found in the LICENSE file.
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Package codec provides a
|
High Performance, Feature-Rich Idiomatic Go codec/encoding library for
|
||||||
High Performance, Feature-Rich Idiomatic Go 1.4+ codec/encoding library
|
binc, msgpack, cbor, json.
|
||||||
for binc, msgpack, cbor, json.
|
|
||||||
|
|
||||||
Supported Serialization formats are:
|
Supported Serialization formats are:
|
||||||
|
|
||||||
|
@ -12,17 +11,21 @@ Supported Serialization formats are:
|
||||||
- binc: http://github.com/ugorji/binc
|
- binc: http://github.com/ugorji/binc
|
||||||
- cbor: http://cbor.io http://tools.ietf.org/html/rfc7049
|
- cbor: http://cbor.io http://tools.ietf.org/html/rfc7049
|
||||||
- json: http://json.org http://tools.ietf.org/html/rfc7159
|
- json: http://json.org http://tools.ietf.org/html/rfc7159
|
||||||
- simple:
|
- simple:
|
||||||
|
|
||||||
To install:
|
To install:
|
||||||
|
|
||||||
go get github.com/ugorji/go/codec
|
go get github.com/ugorji/go/codec
|
||||||
|
|
||||||
This package will carefully use 'unsafe' for performance reasons in specific places.
|
This package understands the 'unsafe' tag, to allow using unsafe semantics:
|
||||||
You can build without unsafe use by passing the safe or appengine tag
|
|
||||||
i.e. 'go install -tags=safe ...'. Note that unsafe is only supported for the last 3
|
- When decoding into a struct, you need to read the field name as a string
|
||||||
go sdk versions e.g. current go release is go 1.9, so we support unsafe use only from
|
so you can find the struct field it is mapped to.
|
||||||
go 1.7+ . This is because supporting unsafe requires knowledge of implementation details.
|
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
|
||||||
|
|
||||||
For detailed usage information, read the primer at http://ugorji.net/blog/go-codec-primer .
|
For detailed usage information, read the primer at http://ugorji.net/blog/go-codec-primer .
|
||||||
|
|
||||||
|
@ -32,16 +35,12 @@ the standard library (ie json, xml, gob, etc).
|
||||||
Rich Feature Set includes:
|
Rich Feature Set includes:
|
||||||
|
|
||||||
- Simple but extremely powerful and feature-rich API
|
- Simple but extremely powerful and feature-rich API
|
||||||
- Support for go1.4 and above, while selectively using newer APIs for later releases
|
|
||||||
- Excellent code coverage ( > 90% )
|
|
||||||
- Very High Performance.
|
- Very High Performance.
|
||||||
Our extensive benchmarks show us outperforming Gob, Json, Bson, etc by 2-4X.
|
Our extensive benchmarks show us outperforming Gob, Json, Bson, etc by 2-4X.
|
||||||
- Careful selected use of 'unsafe' for targeted performance gains.
|
- Multiple conversions:
|
||||||
100% mode exists where 'unsafe' is not used at all.
|
Package coerces types where appropriate
|
||||||
- Lock-free (sans mutex) concurrency for scaling to 100's of cores
|
e.g. decode an int in the stream into a float, etc.
|
||||||
- Coerce types where appropriate
|
- Corner Cases:
|
||||||
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
|
Overflows, nil maps/slices, nil values in streams are handled correctly
|
||||||
- Standard field renaming via tags
|
- Standard field renaming via tags
|
||||||
- Support for omitting empty fields during an encoding
|
- Support for omitting empty fields during an encoding
|
||||||
|
@ -49,21 +48,15 @@ Rich Feature Set includes:
|
||||||
(struct, slice, map, primitives, pointers, interface{}, etc)
|
(struct, slice, map, primitives, pointers, interface{}, etc)
|
||||||
- Extensions to support efficient encoding/decoding of any named types
|
- Extensions to support efficient encoding/decoding of any named types
|
||||||
- Support encoding.(Binary|Text)(M|Unm)arshaler interfaces
|
- Support encoding.(Binary|Text)(M|Unm)arshaler interfaces
|
||||||
- Support IsZero() bool to determine if a value is a zero value.
|
|
||||||
Analogous to time.Time.IsZero() bool.
|
|
||||||
- Decoding without a schema (into a interface{}).
|
- Decoding without a schema (into a interface{}).
|
||||||
Includes Options to configure what specific map or slice type to use
|
Includes Options to configure what specific map or slice type to use
|
||||||
when decoding an encoded list or map into a nil interface{}
|
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
|
- 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
|
- Comprehensive support for anonymous fields
|
||||||
- Fast (no-reflection) encoding/decoding of common maps and slices
|
- Fast (no-reflection) encoding/decoding of common maps and slices
|
||||||
- Code-generation for faster performance.
|
- Code-generation for faster performance.
|
||||||
- Support binary (e.g. messagepack, cbor) and text (e.g. json) formats
|
- Support binary (e.g. messagepack, cbor) and text (e.g. json) formats
|
||||||
- Support indefinite-length formats to enable true streaming
|
- Support indefinite-length formats to enable true streaming
|
||||||
(for formats which support it e.g. json, cbor)
|
(for formats which support it e.g. json, cbor)
|
||||||
- Support canonical encoding, where a value is ALWAYS encoded as same sequence of bytes.
|
- Support canonical encoding, where a value is ALWAYS encoded as same sequence of bytes.
|
||||||
This mostly applies to maps, where iteration order is non-deterministic.
|
This mostly applies to maps, where iteration order is non-deterministic.
|
||||||
|
@ -75,12 +68,12 @@ Rich Feature Set includes:
|
||||||
- Encode/Decode from/to chan types (for iterative streaming support)
|
- Encode/Decode from/to chan types (for iterative streaming support)
|
||||||
- Drop-in replacement for encoding/json. `json:` key in struct tag supported.
|
- Drop-in replacement for encoding/json. `json:` key in struct tag supported.
|
||||||
- Provides a RPC Server and Client Codec for net/rpc communication protocol.
|
- Provides a RPC Server and Client Codec for net/rpc communication protocol.
|
||||||
- Handle unique idiosyncrasies of codecs e.g.
|
- Handle unique idiosynchracies of codecs e.g.
|
||||||
- For messagepack, configure how ambiguities in handling raw bytes are resolved
|
- For messagepack, configure how ambiguities in handling raw bytes are resolved
|
||||||
- For messagepack, provide rpc server/client codec to support
|
- For messagepack, provide rpc server/client codec to support
|
||||||
msgpack-rpc protocol defined at:
|
msgpack-rpc protocol defined at:
|
||||||
https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md
|
https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md
|
||||||
|
|
||||||
Extension Support
|
Extension Support
|
||||||
|
|
||||||
Users can register a function to handle the encoding or decoding of
|
Users can register a function to handle the encoding or decoding of
|
||||||
|
@ -99,27 +92,6 @@ 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
|
would be encoded as a string. However, with extension support, you can
|
||||||
encode any of these however you like.
|
encode any of these however you like.
|
||||||
|
|
||||||
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 type a codec.Selfer?
|
|
||||||
- is there an extension registered for the type?
|
|
||||||
- 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?
|
|
||||||
- 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
|
||||||
|
|
||||||
RPC Client and Server Codecs are implemented, so the codecs can be used
|
RPC Client and Server Codecs are implemented, so the codecs can be used
|
||||||
|
@ -188,77 +160,40 @@ Sample usage model:
|
||||||
//OR rpcCodec := codec.MsgpackSpecRpc.ClientCodec(conn, h)
|
//OR rpcCodec := codec.MsgpackSpecRpc.ClientCodec(conn, h)
|
||||||
client := rpc.NewClientWithCodec(rpcCodec)
|
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
|
|
||||||
|
|
||||||
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
|
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:
|
// TODO:
|
||||||
// - For Go 1.11, when mid-stack inlining is enabled,
|
|
||||||
// we should use committed functions for writeXXX and readXXX calls.
|
|
||||||
// This involves uncommenting the methods for decReaderSwitch and encWriterSwitch
|
|
||||||
// and using those (decReaderSwitch and encWriterSwitch) in all handles
|
|
||||||
// instead of encWriter and decReader.
|
|
||||||
// The benefit is that, for the (En|De)coder over []byte, the encWriter/decReader
|
|
||||||
// will be inlined, giving a performance bump for that typical case.
|
|
||||||
// However, it will only be inlined if mid-stack inlining is enabled,
|
|
||||||
// as we call panic to raise errors, and panic currently prevents inlining.
|
|
||||||
//
|
//
|
||||||
// PUNTED:
|
// - optimization for codecgen:
|
||||||
// - To make Handle comparable, make extHandle in BasicHandle a non-embedded pointer,
|
// if len of entity is <= 3 words, then support a value receiver for encode.
|
||||||
// and use overlay methods on *BasicHandle to call through to extHandle after initializing
|
// - (En|De)coder should store an error when it occurs.
|
||||||
// the "xh *extHandle" to point to a real slice.
|
// Until reset, subsequent calls return that error that was stored.
|
||||||
//
|
// This means that free panics must go away.
|
||||||
// BEFORE EACH RELEASE:
|
// All errors must be raised through errorf method.
|
||||||
// - Look through and fix padding for each type, to eliminate false sharing
|
// - Decoding using a chan is good, but incurs concurrency costs.
|
||||||
// - critical shared objects that are read many times
|
// This is because there's no fast way to use a channel without it
|
||||||
// TypeInfos
|
// having to switch goroutines constantly.
|
||||||
// - pooled objects:
|
// Callback pattern is still the best. Maybe cnsider supporting something like:
|
||||||
// decNaked, decNakedContainers, codecFner, typeInfoLoadArray,
|
// type X struct {
|
||||||
// - small objects allocated independently, that we read/use much across threads:
|
// Name string
|
||||||
// codecFn, typeInfo
|
// Ys []Y
|
||||||
// - Objects allocated independently and used a lot
|
// Ys chan <- Y
|
||||||
// Decoder, Encoder,
|
// Ys func(Y) -> call this function for each entry
|
||||||
// xxxHandle, xxxEncDriver, xxxDecDriver (xxx = json, msgpack, cbor, binc, simple)
|
// }
|
||||||
// - In all above, arrange values modified together to be close to each other.
|
// - Consider adding a isZeroer interface { isZero() bool }
|
||||||
//
|
// It is used within isEmpty, for omitEmpty support.
|
||||||
// For all of these, either ensure that they occupy full cache lines,
|
// - Consider making Handle used AS-IS within the encoding/decoding session.
|
||||||
// or ensure that the things just past the cache line boundary are hardly read/written
|
// This means that we don't cache Handle information within the (En|De)coder,
|
||||||
// e.g. JsonHandle.RawBytesExt - which is copied into json(En|De)cDriver at init
|
// except we really need it at Reset(...)
|
||||||
//
|
// - Consider adding math/big support
|
||||||
// Occupying full cache lines means they occupy 8*N words (where N is an integer).
|
// - Consider reducing the size of the generated functions:
|
||||||
// Check this out by running: ./run.sh -z
|
// Maybe use one loop, and put the conditionals in the loop.
|
||||||
// - look at those tagged ****, meaning they are not occupying full cache lines
|
// for ... { if cLen > 0 { if j == cLen { break } } else if dd.CheckBreak() { break } }
|
||||||
// - look at those tagged <<<<, meaning they are larger than 32 words (something to watch)
|
|
||||||
// - Run "golint -min_confidence 0.81"
|
|
||||||
|
|
|
@ -15,11 +15,17 @@ To install:
|
||||||
|
|
||||||
go get github.com/ugorji/go/codec
|
go get github.com/ugorji/go/codec
|
||||||
|
|
||||||
This package will carefully use 'unsafe' for performance reasons in specific places.
|
This package understands the `unsafe` tag, to allow using unsafe semantics:
|
||||||
You can build without unsafe use by passing the safe or appengine tag
|
|
||||||
i.e. 'go install -tags=safe ...'. Note that unsafe is only supported for the last 3
|
- When decoding into a struct, you need to read the field name as a string
|
||||||
go sdk versions e.g. current go release is go 1.9, so we support unsafe use only from
|
so you can find the struct field it is mapped to.
|
||||||
go 1.7+ . This is because supporting unsafe requires knowledge of implementation details.
|
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
|
Online documentation: http://godoc.org/github.com/ugorji/go/codec
|
||||||
Detailed Usage/How-to Primer: http://ugorji.net/blog/go-codec-primer
|
Detailed Usage/How-to Primer: http://ugorji.net/blog/go-codec-primer
|
||||||
|
@ -30,15 +36,11 @@ the standard library (ie json, xml, gob, etc).
|
||||||
Rich Feature Set includes:
|
Rich Feature Set includes:
|
||||||
|
|
||||||
- Simple but extremely powerful and feature-rich API
|
- Simple but extremely powerful and feature-rich API
|
||||||
- Support for go1.4 and above, while selectively using newer APIs for later releases
|
|
||||||
- Excellent code coverage ( > 90% )
|
|
||||||
- Very High Performance.
|
- Very High Performance.
|
||||||
Our extensive benchmarks show us outperforming Gob, Json, Bson, etc by 2-4X.
|
Our extensive benchmarks show us outperforming Gob, Json, Bson, etc by 2-4X.
|
||||||
- Careful selected use of 'unsafe' for targeted performance gains.
|
- Multiple conversions:
|
||||||
100% mode exists where 'unsafe' is not used at all.
|
Package coerces types where appropriate
|
||||||
- Lock-free (sans mutex) concurrency for scaling to 100's of cores
|
e.g. decode an int in the stream into a float, etc.
|
||||||
- Coerce types where appropriate
|
|
||||||
e.g. decode an int in the stream into a float, decode numbers from formatted strings, etc
|
|
||||||
- Corner Cases:
|
- Corner Cases:
|
||||||
Overflows, nil maps/slices, nil values in streams are handled correctly
|
Overflows, nil maps/slices, nil values in streams are handled correctly
|
||||||
- Standard field renaming via tags
|
- Standard field renaming via tags
|
||||||
|
@ -47,16 +49,10 @@ Rich Feature Set includes:
|
||||||
(struct, slice, map, primitives, pointers, interface{}, etc)
|
(struct, slice, map, primitives, pointers, interface{}, etc)
|
||||||
- Extensions to support efficient encoding/decoding of any named types
|
- Extensions to support efficient encoding/decoding of any named types
|
||||||
- Support encoding.(Binary|Text)(M|Unm)arshaler interfaces
|
- Support encoding.(Binary|Text)(M|Unm)arshaler interfaces
|
||||||
- Support IsZero() bool to determine if a value is a zero value.
|
|
||||||
Analogous to time.Time.IsZero() bool.
|
|
||||||
- Decoding without a schema (into a interface{}).
|
- Decoding without a schema (into a interface{}).
|
||||||
Includes Options to configure what specific map or slice type to use
|
Includes Options to configure what specific map or slice type to use
|
||||||
when decoding an encoded list or map into a nil interface{}
|
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
|
- 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
|
- Comprehensive support for anonymous fields
|
||||||
- Fast (no-reflection) encoding/decoding of common maps and slices
|
- Fast (no-reflection) encoding/decoding of common maps and slices
|
||||||
- Code-generation for faster performance.
|
- Code-generation for faster performance.
|
||||||
|
@ -72,7 +68,7 @@ Rich Feature Set includes:
|
||||||
- Encode/Decode from/to chan types (for iterative streaming support)
|
- Encode/Decode from/to chan types (for iterative streaming support)
|
||||||
- Drop-in replacement for encoding/json. `json:` key in struct tag supported.
|
- Drop-in replacement for encoding/json. `json:` key in struct tag supported.
|
||||||
- Provides a RPC Server and Client Codec for net/rpc communication protocol.
|
- Provides a RPC Server and Client Codec for net/rpc communication protocol.
|
||||||
- Handle unique idiosyncrasies of codecs e.g.
|
- Handle unique idiosynchracies of codecs e.g.
|
||||||
- For messagepack, configure how ambiguities in handling raw bytes are resolved
|
- For messagepack, configure how ambiguities in handling raw bytes are resolved
|
||||||
- For messagepack, provide rpc server/client codec to support
|
- For messagepack, provide rpc server/client codec to support
|
||||||
msgpack-rpc protocol defined at:
|
msgpack-rpc protocol defined at:
|
||||||
|
@ -96,27 +92,6 @@ 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
|
would be encoded as a string. However, with extension support, you can
|
||||||
encode any of these however you like.
|
encode any of these however you like.
|
||||||
|
|
||||||
## 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 type a codec.Selfer?
|
|
||||||
- is there an extension registered for the type?
|
|
||||||
- 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?
|
|
||||||
- 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
|
||||||
|
|
||||||
RPC Client and Server Codecs are implemented, so the codecs can be used
|
RPC Client and Server Codecs are implemented, so the codecs can be used
|
||||||
|
@ -171,36 +146,3 @@ Typical usage model:
|
||||||
//OR rpcCodec := codec.MsgpackSpecRpc.ClientCodec(conn, h)
|
//OR rpcCodec := codec.MsgpackSpecRpc.ClientCodec(conn, h)
|
||||||
client := rpc.NewClientWithCodec(rpcCodec)
|
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
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
|
// 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.
|
// Use of this source code is governed by a MIT license found in the LICENSE file.
|
||||||
|
|
||||||
package codec
|
package codec
|
||||||
|
@ -55,77 +55,39 @@ const (
|
||||||
// others not currently supported
|
// others not currently supported
|
||||||
)
|
)
|
||||||
|
|
||||||
func bincdesc(vd, vs byte) string {
|
|
||||||
switch vd {
|
|
||||||
case bincVdSpecial:
|
|
||||||
switch vs {
|
|
||||||
case bincSpNil:
|
|
||||||
return "nil"
|
|
||||||
case bincSpFalse:
|
|
||||||
return "false"
|
|
||||||
case bincSpTrue:
|
|
||||||
return "true"
|
|
||||||
case bincSpNan, bincSpPosInf, bincSpNegInf, bincSpZeroFloat:
|
|
||||||
return "float"
|
|
||||||
case bincSpZero:
|
|
||||||
return "uint"
|
|
||||||
case bincSpNegOne:
|
|
||||||
return "int"
|
|
||||||
default:
|
|
||||||
return "unknown"
|
|
||||||
}
|
|
||||||
case bincVdSmallInt, bincVdPosInt:
|
|
||||||
return "uint"
|
|
||||||
case bincVdNegInt:
|
|
||||||
return "int"
|
|
||||||
case bincVdFloat:
|
|
||||||
return "float"
|
|
||||||
case bincVdSymbol:
|
|
||||||
return "string"
|
|
||||||
case bincVdString:
|
|
||||||
return "string"
|
|
||||||
case bincVdByteArray:
|
|
||||||
return "bytes"
|
|
||||||
case bincVdTimestamp:
|
|
||||||
return "time"
|
|
||||||
case bincVdCustomExt:
|
|
||||||
return "ext"
|
|
||||||
case bincVdArray:
|
|
||||||
return "array"
|
|
||||||
case bincVdMap:
|
|
||||||
return "map"
|
|
||||||
default:
|
|
||||||
return "unknown"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type bincEncDriver struct {
|
type bincEncDriver struct {
|
||||||
e *Encoder
|
e *Encoder
|
||||||
h *BincHandle
|
|
||||||
w encWriter
|
w encWriter
|
||||||
m map[string]uint16 // symbols
|
m map[string]uint16 // symbols
|
||||||
b [16]byte // scratch, used for encoding numbers - bigendian style
|
b [scratchByteArrayLen]byte
|
||||||
s uint16 // symbols sequencer
|
s uint16 // symbols sequencer
|
||||||
// c containerState
|
encNoSeparator
|
||||||
encDriverTrackContainerWriter
|
}
|
||||||
noBuiltInTypes
|
|
||||||
// encNoSeparator
|
func (e *bincEncDriver) IsBuiltinType(rt uintptr) bool {
|
||||||
|
return rt == timeTypId
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *bincEncDriver) EncodeBuiltin(rt uintptr, v interface{}) {
|
||||||
|
if rt == timeTypId {
|
||||||
|
var bs []byte
|
||||||
|
switch x := v.(type) {
|
||||||
|
case time.Time:
|
||||||
|
bs = encodeTime(x)
|
||||||
|
case *time.Time:
|
||||||
|
bs = encodeTime(*x)
|
||||||
|
default:
|
||||||
|
e.e.errorf("binc error encoding builtin: expect time.Time, received %T", v)
|
||||||
|
}
|
||||||
|
e.w.writen1(bincVdTimestamp<<4 | uint8(len(bs)))
|
||||||
|
e.w.writeb(bs)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *bincEncDriver) EncodeNil() {
|
func (e *bincEncDriver) EncodeNil() {
|
||||||
e.w.writen1(bincVdSpecial<<4 | bincSpNil)
|
e.w.writen1(bincVdSpecial<<4 | bincSpNil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *bincEncDriver) EncodeTime(t time.Time) {
|
|
||||||
if t.IsZero() {
|
|
||||||
e.EncodeNil()
|
|
||||||
} else {
|
|
||||||
bs := bincEncodeTime(t)
|
|
||||||
e.w.writen1(bincVdTimestamp<<4 | uint8(len(bs)))
|
|
||||||
e.w.writeb(bs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *bincEncDriver) EncodeBool(b bool) {
|
func (e *bincEncDriver) EncodeBool(b bool) {
|
||||||
if b {
|
if b {
|
||||||
e.w.writen1(bincVdSpecial<<4 | bincSpTrue)
|
e.w.writen1(bincVdSpecial<<4 | bincSpTrue)
|
||||||
|
@ -233,21 +195,15 @@ func (e *bincEncDriver) encodeExtPreamble(xtag byte, length int) {
|
||||||
e.w.writen1(xtag)
|
e.w.writen1(xtag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *bincEncDriver) WriteArrayStart(length int) {
|
func (e *bincEncDriver) EncodeArrayStart(length int) {
|
||||||
e.encLen(bincVdArray<<4, uint64(length))
|
e.encLen(bincVdArray<<4, uint64(length))
|
||||||
e.c = containerArrayStart
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *bincEncDriver) WriteMapStart(length int) {
|
func (e *bincEncDriver) EncodeMapStart(length int) {
|
||||||
e.encLen(bincVdMap<<4, uint64(length))
|
e.encLen(bincVdMap<<4, uint64(length))
|
||||||
e.c = containerMapStart
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *bincEncDriver) EncodeString(c charEncoding, v string) {
|
func (e *bincEncDriver) EncodeString(c charEncoding, v string) {
|
||||||
if e.c == containerMapKey && c == cUTF8 && (e.h.AsSymbols == 0 || e.h.AsSymbols == 1) {
|
|
||||||
e.EncodeSymbol(v)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
l := uint64(len(v))
|
l := uint64(len(v))
|
||||||
e.encBytesLen(c, l)
|
e.encBytesLen(c, l)
|
||||||
if l > 0 {
|
if l > 0 {
|
||||||
|
@ -257,7 +213,7 @@ func (e *bincEncDriver) EncodeString(c charEncoding, v string) {
|
||||||
|
|
||||||
func (e *bincEncDriver) EncodeSymbol(v string) {
|
func (e *bincEncDriver) EncodeSymbol(v string) {
|
||||||
// if WriteSymbolsNoRefs {
|
// if WriteSymbolsNoRefs {
|
||||||
// e.encodeString(cUTF8, v)
|
// e.encodeString(c_UTF8, v)
|
||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
@ -267,10 +223,10 @@ func (e *bincEncDriver) EncodeSymbol(v string) {
|
||||||
|
|
||||||
l := len(v)
|
l := len(v)
|
||||||
if l == 0 {
|
if l == 0 {
|
||||||
e.encBytesLen(cUTF8, 0)
|
e.encBytesLen(c_UTF8, 0)
|
||||||
return
|
return
|
||||||
} else if l == 1 {
|
} else if l == 1 {
|
||||||
e.encBytesLen(cUTF8, 1)
|
e.encBytesLen(c_UTF8, 1)
|
||||||
e.w.writen1(v[0])
|
e.w.writen1(v[0])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -320,10 +276,6 @@ func (e *bincEncDriver) EncodeSymbol(v string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *bincEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
|
func (e *bincEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
|
||||||
if v == nil {
|
|
||||||
e.EncodeNil()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
l := uint64(len(v))
|
l := uint64(len(v))
|
||||||
e.encBytesLen(c, l)
|
e.encBytesLen(c, l)
|
||||||
if l > 0 {
|
if l > 0 {
|
||||||
|
@ -333,7 +285,7 @@ func (e *bincEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
|
||||||
|
|
||||||
func (e *bincEncDriver) encBytesLen(c charEncoding, length uint64) {
|
func (e *bincEncDriver) encBytesLen(c charEncoding, length uint64) {
|
||||||
//TODO: support bincUnicodeOther (for now, just use string or bytearray)
|
//TODO: support bincUnicodeOther (for now, just use string or bytearray)
|
||||||
if c == cRAW {
|
if c == c_RAW {
|
||||||
e.encLen(bincVdByteArray<<4, length)
|
e.encLen(bincVdByteArray<<4, length)
|
||||||
} else {
|
} else {
|
||||||
e.encLen(bincVdString<<4, length)
|
e.encLen(bincVdString<<4, length)
|
||||||
|
@ -372,9 +324,6 @@ type bincDecSymbol struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type bincDecDriver struct {
|
type bincDecDriver struct {
|
||||||
decDriverNoopContainerReader
|
|
||||||
noBuiltInTypes
|
|
||||||
|
|
||||||
d *Decoder
|
d *Decoder
|
||||||
h *BincHandle
|
h *BincHandle
|
||||||
r decReader
|
r decReader
|
||||||
|
@ -383,15 +332,13 @@ type bincDecDriver struct {
|
||||||
bd byte
|
bd byte
|
||||||
vd byte
|
vd byte
|
||||||
vs byte
|
vs byte
|
||||||
_ [3]byte // padding
|
noStreamingCodec
|
||||||
|
decNoSeparator
|
||||||
|
b [scratchByteArrayLen]byte
|
||||||
|
|
||||||
// linear searching on this slice is ok,
|
// linear searching on this slice is ok,
|
||||||
// because we typically expect < 32 symbols in each stream.
|
// because we typically expect < 32 symbols in each stream.
|
||||||
s []bincDecSymbol
|
s []bincDecSymbol
|
||||||
|
|
||||||
// noStreamingCodec
|
|
||||||
// decNoSeparator
|
|
||||||
|
|
||||||
b [8 * 8]byte // scratch
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *bincDecDriver) readNextBd() {
|
func (d *bincDecDriver) readNextBd() {
|
||||||
|
@ -401,17 +348,7 @@ func (d *bincDecDriver) readNextBd() {
|
||||||
d.bdRead = true
|
d.bdRead = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *bincDecDriver) uncacheRead() {
|
|
||||||
if d.bdRead {
|
|
||||||
d.r.unreadn1()
|
|
||||||
d.bdRead = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *bincDecDriver) ContainerType() (vt valueType) {
|
func (d *bincDecDriver) ContainerType() (vt valueType) {
|
||||||
if !d.bdRead {
|
|
||||||
d.readNextBd()
|
|
||||||
}
|
|
||||||
if d.vd == bincVdSpecial && d.vs == bincSpNil {
|
if d.vd == bincVdSpecial && d.vs == bincSpNil {
|
||||||
return valueTypeNil
|
return valueTypeNil
|
||||||
} else if d.vd == bincVdByteArray {
|
} else if d.vd == bincVdByteArray {
|
||||||
|
@ -422,10 +359,9 @@ func (d *bincDecDriver) ContainerType() (vt valueType) {
|
||||||
return valueTypeArray
|
return valueTypeArray
|
||||||
} else if d.vd == bincVdMap {
|
} else if d.vd == bincVdMap {
|
||||||
return valueTypeMap
|
return valueTypeMap
|
||||||
|
} else {
|
||||||
|
// d.d.errorf("isContainerType: unsupported parameter: %v", vt)
|
||||||
}
|
}
|
||||||
// else {
|
|
||||||
// d.d.errorf("isContainerType: unsupported parameter: %v", vt)
|
|
||||||
// }
|
|
||||||
return valueTypeUnset
|
return valueTypeUnset
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,24 +376,27 @@ func (d *bincDecDriver) TryDecodeAsNil() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *bincDecDriver) DecodeTime() (t time.Time) {
|
func (d *bincDecDriver) IsBuiltinType(rt uintptr) bool {
|
||||||
|
return rt == timeTypId
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *bincDecDriver) DecodeBuiltin(rt uintptr, v interface{}) {
|
||||||
if !d.bdRead {
|
if !d.bdRead {
|
||||||
d.readNextBd()
|
d.readNextBd()
|
||||||
}
|
}
|
||||||
if d.bd == bincVdSpecial<<4|bincSpNil {
|
if rt == timeTypId {
|
||||||
|
if d.vd != bincVdTimestamp {
|
||||||
|
d.d.errorf("Invalid d.vd. Expecting 0x%x. Received: 0x%x", bincVdTimestamp, d.vd)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tt, err := decodeTime(d.r.readx(int(d.vs)))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
var vt *time.Time = v.(*time.Time)
|
||||||
|
*vt = tt
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
return
|
|
||||||
}
|
}
|
||||||
if d.vd != bincVdTimestamp {
|
|
||||||
d.d.errorf("cannot decode time - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t, err := bincDecodeTime(d.r.readx(int(d.vs)))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
d.bdRead = false
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *bincDecDriver) decFloatPre(vs, defaultLen byte) {
|
func (d *bincDecDriver) decFloatPre(vs, defaultLen byte) {
|
||||||
|
@ -466,7 +405,7 @@ func (d *bincDecDriver) decFloatPre(vs, defaultLen byte) {
|
||||||
} else {
|
} else {
|
||||||
l := d.r.readn1()
|
l := d.r.readn1()
|
||||||
if l > 8 {
|
if l > 8 {
|
||||||
d.d.errorf("cannot read float - at most 8 bytes used to represent float - received %v bytes", l)
|
d.d.errorf("At most 8 bytes used to represent float. Received: %v bytes", l)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for i := l; i < 8; i++ {
|
for i := l; i < 8; i++ {
|
||||||
|
@ -485,7 +424,7 @@ func (d *bincDecDriver) decFloat() (f float64) {
|
||||||
d.decFloatPre(d.vs, 8)
|
d.decFloatPre(d.vs, 8)
|
||||||
f = math.Float64frombits(bigen.Uint64(d.b[0:8]))
|
f = math.Float64frombits(bigen.Uint64(d.b[0:8]))
|
||||||
} else {
|
} else {
|
||||||
d.d.errorf("read float - only float32 and float64 are supported - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
|
d.d.errorf("only float32 and float64 are supported. d.vd: 0x%x, d.vs: 0x%x", d.vd, d.vs)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -542,38 +481,49 @@ func (d *bincDecDriver) decCheckInteger() (ui uint64, neg bool) {
|
||||||
neg = true
|
neg = true
|
||||||
ui = 1
|
ui = 1
|
||||||
} else {
|
} else {
|
||||||
d.d.errorf("integer decode fails - invalid special value from descriptor %x-%x/%s",
|
d.d.errorf("numeric decode fails for special value: d.vs: 0x%x", d.vs)
|
||||||
d.vd, d.vs, bincdesc(d.vd, d.vs))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
d.d.errorf("integer can only be decoded from int/uint. d.bd: 0x%x, d.vd: 0x%x", d.bd, d.vd)
|
d.d.errorf("number can only be decoded from uint or int values. d.bd: 0x%x, d.vd: 0x%x", d.bd, d.vd)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *bincDecDriver) DecodeInt64() (i int64) {
|
func (d *bincDecDriver) DecodeInt(bitsize uint8) (i int64) {
|
||||||
ui, neg := d.decCheckInteger()
|
ui, neg := d.decCheckInteger()
|
||||||
i = chkOvf.SignedIntV(ui)
|
i, overflow := chkOvf.SignedInt(ui)
|
||||||
|
if overflow {
|
||||||
|
d.d.errorf("simple: overflow converting %v to signed integer", ui)
|
||||||
|
return
|
||||||
|
}
|
||||||
if neg {
|
if neg {
|
||||||
i = -i
|
i = -i
|
||||||
}
|
}
|
||||||
d.bdRead = false
|
if chkOvf.Int(i, bitsize) {
|
||||||
return
|
d.d.errorf("binc: overflow integer: %v", i)
|
||||||
}
|
|
||||||
|
|
||||||
func (d *bincDecDriver) DecodeUint64() (ui uint64) {
|
|
||||||
ui, neg := d.decCheckInteger()
|
|
||||||
if neg {
|
|
||||||
d.d.errorf("assigning negative signed value to unsigned integer type")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *bincDecDriver) DecodeFloat64() (f float64) {
|
func (d *bincDecDriver) DecodeUint(bitsize uint8) (ui uint64) {
|
||||||
|
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("binc: overflow integer: %v", ui)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
d.bdRead = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *bincDecDriver) DecodeFloat(chkOverflow32 bool) (f float64) {
|
||||||
if !d.bdRead {
|
if !d.bdRead {
|
||||||
d.readNextBd()
|
d.readNextBd()
|
||||||
}
|
}
|
||||||
|
@ -589,14 +539,17 @@ func (d *bincDecDriver) DecodeFloat64() (f float64) {
|
||||||
} else if vs == bincSpNegInf {
|
} else if vs == bincSpNegInf {
|
||||||
return math.Inf(-1)
|
return math.Inf(-1)
|
||||||
} else {
|
} else {
|
||||||
d.d.errorf("float - invalid special value from descriptor %x-%x/%s",
|
d.d.errorf("Invalid d.vs decoding float where d.vd=bincVdSpecial: %v", d.vs)
|
||||||
d.vd, d.vs, bincdesc(d.vd, d.vs))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else if vd == bincVdFloat {
|
} else if vd == bincVdFloat {
|
||||||
f = d.decFloat()
|
f = d.decFloat()
|
||||||
} else {
|
} else {
|
||||||
f = float64(d.DecodeInt64())
|
f = float64(d.DecodeInt(64))
|
||||||
|
}
|
||||||
|
if chkOverflow32 && chkOvf.Float32(f) {
|
||||||
|
d.d.errorf("binc: float32 overflow: %v", f)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
return
|
return
|
||||||
|
@ -612,7 +565,7 @@ func (d *bincDecDriver) DecodeBool() (b bool) {
|
||||||
} else if bd == (bincVdSpecial | bincSpTrue) {
|
} else if bd == (bincVdSpecial | bincSpTrue) {
|
||||||
b = true
|
b = true
|
||||||
} else {
|
} else {
|
||||||
d.d.errorf("bool - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
|
d.d.errorf("Invalid single-byte value for bool: %s: %x", msgBadDesc, d.bd)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
|
@ -620,11 +573,8 @@ func (d *bincDecDriver) DecodeBool() (b bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *bincDecDriver) ReadMapStart() (length int) {
|
func (d *bincDecDriver) ReadMapStart() (length int) {
|
||||||
if !d.bdRead {
|
|
||||||
d.readNextBd()
|
|
||||||
}
|
|
||||||
if d.vd != bincVdMap {
|
if d.vd != bincVdMap {
|
||||||
d.d.errorf("map - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
|
d.d.errorf("Invalid d.vd for map. Expecting 0x%x. Got: 0x%x", bincVdMap, d.vd)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
length = d.decLen()
|
length = d.decLen()
|
||||||
|
@ -633,11 +583,8 @@ func (d *bincDecDriver) ReadMapStart() (length int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *bincDecDriver) ReadArrayStart() (length int) {
|
func (d *bincDecDriver) ReadArrayStart() (length int) {
|
||||||
if !d.bdRead {
|
|
||||||
d.readNextBd()
|
|
||||||
}
|
|
||||||
if d.vd != bincVdArray {
|
if d.vd != bincVdArray {
|
||||||
d.d.errorf("array - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
|
d.d.errorf("Invalid d.vd for array. Expecting 0x%x. Got: 0x%x", bincVdArray, d.vd)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
length = d.decLen()
|
length = d.decLen()
|
||||||
|
@ -668,8 +615,7 @@ func (d *bincDecDriver) decLenNumber() (v uint64) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *bincDecDriver) decStringAndBytes(bs []byte, withString, zerocopy bool) (
|
func (d *bincDecDriver) decStringAndBytes(bs []byte, withString, zerocopy bool) (bs2 []byte, s string) {
|
||||||
bs2 []byte, s string) {
|
|
||||||
if !d.bdRead {
|
if !d.bdRead {
|
||||||
d.readNextBd()
|
d.readNextBd()
|
||||||
}
|
}
|
||||||
|
@ -677,7 +623,7 @@ func (d *bincDecDriver) decStringAndBytes(bs []byte, withString, zerocopy bool)
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var slen = -1
|
var slen int = -1
|
||||||
// var ok bool
|
// var ok bool
|
||||||
switch d.vd {
|
switch d.vd {
|
||||||
case bincVdString, bincVdByteArray:
|
case bincVdString, bincVdByteArray:
|
||||||
|
@ -686,12 +632,12 @@ func (d *bincDecDriver) decStringAndBytes(bs []byte, withString, zerocopy bool)
|
||||||
if d.br {
|
if d.br {
|
||||||
bs2 = d.r.readx(slen)
|
bs2 = d.r.readx(slen)
|
||||||
} else if len(bs) == 0 {
|
} else if len(bs) == 0 {
|
||||||
bs2 = decByteSlice(d.r, slen, d.d.h.MaxInitLen, d.b[:])
|
bs2 = decByteSlice(d.r, slen, d.b[:])
|
||||||
} else {
|
} else {
|
||||||
bs2 = decByteSlice(d.r, slen, d.d.h.MaxInitLen, bs)
|
bs2 = decByteSlice(d.r, slen, bs)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bs2 = decByteSlice(d.r, slen, d.d.h.MaxInitLen, bs)
|
bs2 = decByteSlice(d.r, slen, bs)
|
||||||
}
|
}
|
||||||
if withString {
|
if withString {
|
||||||
s = string(bs2)
|
s = string(bs2)
|
||||||
|
@ -743,14 +689,15 @@ func (d *bincDecDriver) decStringAndBytes(bs []byte, withString, zerocopy bool)
|
||||||
// since using symbols, do not store any part of
|
// since using symbols, do not store any part of
|
||||||
// the parameter bs in the map, as it might be a shared buffer.
|
// the parameter bs in the map, as it might be a shared buffer.
|
||||||
// bs2 = decByteSlice(d.r, slen, bs)
|
// bs2 = decByteSlice(d.r, slen, bs)
|
||||||
bs2 = decByteSlice(d.r, slen, d.d.h.MaxInitLen, nil)
|
bs2 = decByteSlice(d.r, slen, nil)
|
||||||
if withString {
|
if withString {
|
||||||
s = string(bs2)
|
s = string(bs2)
|
||||||
}
|
}
|
||||||
d.s = append(d.s, bincDecSymbol{i: symbol, s: s, b: bs2})
|
d.s = append(d.s, bincDecSymbol{i: symbol, s: s, b: bs2})
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
d.d.errorf("string/bytes - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
|
d.d.errorf("Invalid d.vd. Expecting string:0x%x, bytearray:0x%x or symbol: 0x%x. Got: 0x%x",
|
||||||
|
bincVdString, bincVdByteArray, bincVdSymbol, d.vd)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
|
@ -758,19 +705,18 @@ func (d *bincDecDriver) decStringAndBytes(bs []byte, withString, zerocopy bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *bincDecDriver) DecodeString() (s string) {
|
func (d *bincDecDriver) DecodeString() (s string) {
|
||||||
// DecodeBytes does not accommodate symbols, whose impl stores string version in map.
|
// DecodeBytes does not accomodate symbols, whose impl stores string version in map.
|
||||||
// Use decStringAndBytes directly.
|
// Use decStringAndBytes directly.
|
||||||
// return string(d.DecodeBytes(d.b[:], true, true))
|
// return string(d.DecodeBytes(d.b[:], true, true))
|
||||||
_, s = d.decStringAndBytes(d.b[:], true, true)
|
_, s = d.decStringAndBytes(d.b[:], true, true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *bincDecDriver) DecodeStringAsBytes() (s []byte) {
|
func (d *bincDecDriver) DecodeBytes(bs []byte, isstring, zerocopy bool) (bsOut []byte) {
|
||||||
s, _ = d.decStringAndBytes(d.b[:], false, true)
|
if isstring {
|
||||||
return
|
bsOut, _ = d.decStringAndBytes(bs, false, zerocopy)
|
||||||
}
|
return
|
||||||
|
}
|
||||||
func (d *bincDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
|
|
||||||
if !d.bdRead {
|
if !d.bdRead {
|
||||||
d.readNextBd()
|
d.readNextBd()
|
||||||
}
|
}
|
||||||
|
@ -778,16 +724,12 @@ func (d *bincDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// check if an "array" of uint8's (see ContainerType for how to infer if an array)
|
|
||||||
if d.vd == bincVdArray {
|
|
||||||
bsOut, _ = fastpathTV.DecSliceUint8V(bs, true, d.d)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var clen int
|
var clen int
|
||||||
if d.vd == bincVdString || d.vd == bincVdByteArray {
|
if d.vd == bincVdString || d.vd == bincVdByteArray {
|
||||||
clen = d.decLen()
|
clen = d.decLen()
|
||||||
} else {
|
} else {
|
||||||
d.d.errorf("bytes - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
|
d.d.errorf("Invalid d.vd for bytes. Expecting string:0x%x or bytearray:0x%x. Got: 0x%x",
|
||||||
|
bincVdString, bincVdByteArray, d.vd)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
|
@ -798,12 +740,12 @@ func (d *bincDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
|
||||||
bs = d.b[:]
|
bs = d.b[:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return decByteSlice(d.r, clen, d.d.h.MaxInitLen, bs)
|
return decByteSlice(d.r, clen, bs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *bincDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) {
|
func (d *bincDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) {
|
||||||
if xtag > 0xff {
|
if xtag > 0xff {
|
||||||
d.d.errorf("ext: tag must be <= 0xff; got: %v", xtag)
|
d.d.errorf("decodeExt: tag must be <= 0xff; got: %v", xtag)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
realxtag1, xbs := d.decodeExtV(ext != nil, uint8(xtag))
|
realxtag1, xbs := d.decodeExtV(ext != nil, uint8(xtag))
|
||||||
|
@ -826,14 +768,14 @@ func (d *bincDecDriver) decodeExtV(verifyTag bool, tag byte) (xtag byte, xbs []b
|
||||||
l := d.decLen()
|
l := d.decLen()
|
||||||
xtag = d.r.readn1()
|
xtag = d.r.readn1()
|
||||||
if verifyTag && xtag != tag {
|
if verifyTag && xtag != tag {
|
||||||
d.d.errorf("wrong extension tag - got %b, expecting: %v", xtag, tag)
|
d.d.errorf("Wrong extension tag. Got %b. Expecting: %v", xtag, tag)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
xbs = d.r.readx(l)
|
xbs = d.r.readx(l)
|
||||||
} else if d.vd == bincVdByteArray {
|
} else if d.vd == bincVdByteArray {
|
||||||
xbs = d.DecodeBytes(nil, true)
|
xbs = d.DecodeBytes(nil, false, true)
|
||||||
} else {
|
} else {
|
||||||
d.d.errorf("ext - expecting extensions or byte array - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
|
d.d.errorf("Invalid d.vd for extensions (Expecting extensions or byte array). Got: 0x%x", d.vd)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
|
@ -845,7 +787,7 @@ func (d *bincDecDriver) DecodeNaked() {
|
||||||
d.readNextBd()
|
d.readNextBd()
|
||||||
}
|
}
|
||||||
|
|
||||||
n := d.d.n
|
n := &d.d.n
|
||||||
var decodeFurther bool
|
var decodeFurther bool
|
||||||
|
|
||||||
switch d.vd {
|
switch d.vd {
|
||||||
|
@ -878,7 +820,7 @@ func (d *bincDecDriver) DecodeNaked() {
|
||||||
n.v = valueTypeInt
|
n.v = valueTypeInt
|
||||||
n.i = int64(-1) // int8(-1)
|
n.i = int64(-1) // int8(-1)
|
||||||
default:
|
default:
|
||||||
d.d.errorf("cannot infer value - unrecognized special value from descriptor %x-%x/%s", d.vd, d.vs, bincdesc(d.vd, d.vs))
|
d.d.errorf("decodeNaked: Unrecognized special value 0x%x", d.vs)
|
||||||
}
|
}
|
||||||
case bincVdSmallInt:
|
case bincVdSmallInt:
|
||||||
n.v = valueTypeUint
|
n.v = valueTypeUint
|
||||||
|
@ -900,10 +842,10 @@ func (d *bincDecDriver) DecodeNaked() {
|
||||||
n.s = d.DecodeString()
|
n.s = d.DecodeString()
|
||||||
case bincVdByteArray:
|
case bincVdByteArray:
|
||||||
n.v = valueTypeBytes
|
n.v = valueTypeBytes
|
||||||
n.l = d.DecodeBytes(nil, false)
|
n.l = d.DecodeBytes(nil, false, false)
|
||||||
case bincVdTimestamp:
|
case bincVdTimestamp:
|
||||||
n.v = valueTypeTime
|
n.v = valueTypeTimestamp
|
||||||
tt, err := bincDecodeTime(d.r.readx(int(d.vs)))
|
tt, err := decodeTime(d.r.readx(int(d.vs)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -920,7 +862,7 @@ func (d *bincDecDriver) DecodeNaked() {
|
||||||
n.v = valueTypeMap
|
n.v = valueTypeMap
|
||||||
decodeFurther = true
|
decodeFurther = true
|
||||||
default:
|
default:
|
||||||
d.d.errorf("cannot infer value - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
|
d.d.errorf("decodeNaked: Unrecognized d.vd: 0x%x", d.vd)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !decodeFurther {
|
if !decodeFurther {
|
||||||
|
@ -950,219 +892,31 @@ func (d *bincDecDriver) DecodeNaked() {
|
||||||
type BincHandle struct {
|
type BincHandle struct {
|
||||||
BasicHandle
|
BasicHandle
|
||||||
binaryEncodingType
|
binaryEncodingType
|
||||||
noElemSeparators
|
|
||||||
|
|
||||||
// AsSymbols defines what should be encoded as symbols.
|
|
||||||
//
|
|
||||||
// Encoding as symbols can reduce the encoded size significantly.
|
|
||||||
//
|
|
||||||
// However, during decoding, each string to be encoded as a symbol must
|
|
||||||
// be checked to see if it has been seen before. Consequently, encoding time
|
|
||||||
// will increase if using symbols, because string comparisons has a clear cost.
|
|
||||||
//
|
|
||||||
// Values:
|
|
||||||
// - 0: default: library uses best judgement
|
|
||||||
// - 1: use symbols
|
|
||||||
// - 2: do not use symbols
|
|
||||||
AsSymbols uint8
|
|
||||||
|
|
||||||
// AsSymbols: may later on introduce more options ...
|
|
||||||
// - m: map keys
|
|
||||||
// - s: struct fields
|
|
||||||
// - n: none
|
|
||||||
// - a: all: same as m, s, ...
|
|
||||||
|
|
||||||
// _ [1]uint64 // padding
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name returns the name of the handle: binc
|
|
||||||
func (h *BincHandle) Name() string { return "binc" }
|
|
||||||
|
|
||||||
// SetBytesExt sets an extension
|
|
||||||
func (h *BincHandle) SetBytesExt(rt reflect.Type, tag uint64, ext BytesExt) (err error) {
|
func (h *BincHandle) SetBytesExt(rt reflect.Type, tag uint64, ext BytesExt) (err error) {
|
||||||
return h.SetExt(rt, tag, &extWrapper{ext, interfaceExtFailer{}})
|
return h.SetExt(rt, tag, &setExtWrapper{b: ext})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *BincHandle) newEncDriver(e *Encoder) encDriver {
|
func (h *BincHandle) newEncDriver(e *Encoder) encDriver {
|
||||||
return &bincEncDriver{e: e, h: h, w: e.w}
|
return &bincEncDriver{e: e, w: e.w}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *BincHandle) newDecDriver(d *Decoder) decDriver {
|
func (h *BincHandle) newDecDriver(d *Decoder) decDriver {
|
||||||
return &bincDecDriver{d: d, h: h, r: d.r, br: d.bytes}
|
return &bincDecDriver{d: d, r: d.r, h: h, br: d.bytes}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *bincEncDriver) reset() {
|
func (e *bincEncDriver) reset() {
|
||||||
e.w = e.e.w
|
e.w = e.e.w
|
||||||
e.s = 0
|
e.s = 0
|
||||||
e.c = 0
|
|
||||||
e.m = nil
|
e.m = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *bincDecDriver) reset() {
|
func (d *bincDecDriver) reset() {
|
||||||
d.r, d.br = d.d.r, d.d.bytes
|
d.r = d.d.r
|
||||||
d.s = nil
|
d.s = nil
|
||||||
d.bd, d.bdRead, d.vd, d.vs = 0, false, 0, 0
|
d.bd, d.bdRead, d.vd, d.vs = 0, false, 0, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// var timeDigits = [...]byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
|
|
||||||
|
|
||||||
// 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 bincEncodeTime(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]
|
|
||||||
}
|
|
||||||
|
|
||||||
// bincDecodeTime decodes a []byte into a time.Time.
|
|
||||||
func bincDecodeTime(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
|
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ decDriver = (*bincDecDriver)(nil)
|
var _ decDriver = (*bincDecDriver)(nil)
|
||||||
var _ encDriver = (*bincEncDriver)(nil)
|
var _ encDriver = (*bincEncDriver)(nil)
|
||||||
|
|
|
@ -1,220 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Run all the different permutations of all the tests and other things
|
|
||||||
# This helps ensure that nothing gets broken.
|
|
||||||
|
|
||||||
_tests() {
|
|
||||||
local gover=$( go version | cut -f 3 -d ' ' )
|
|
||||||
# note that codecgen requires fastpath, so you cannot do "codecgen notfastpath"
|
|
||||||
local a=( "" "safe" "notfastpath" "notfastpath safe" "codecgen" "codecgen safe" )
|
|
||||||
for i in "${a[@]}"
|
|
||||||
do
|
|
||||||
echo ">>>> TAGS: $i"
|
|
||||||
local i2=${i:-default}
|
|
||||||
case $gover in
|
|
||||||
go1.[0-6]*) go vet -printfuncs "errorf" "$@" &&
|
|
||||||
go test ${zargs[*]} -vet off -tags "$i" "$@" ;;
|
|
||||||
*) go vet -printfuncs "errorf" "$@" &&
|
|
||||||
go test ${zargs[*]} -vet off -tags "alltests $i" -run "Suite" -coverprofile "${i2// /-}.cov.out" "$@" ;;
|
|
||||||
esac
|
|
||||||
if [[ "$?" != 0 ]]; then return 1; fi
|
|
||||||
done
|
|
||||||
echo "++++++++ TEST SUITES ALL PASSED ++++++++"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# 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-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
|
|
||||||
\`
|
|
||||||
|
|
||||||
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
|
|
||||||
import "io"
|
|
||||||
func GenInternalGoFile(r io.Reader, w io.Writer) error {
|
|
||||||
return genInternalGoFile(r, w)
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
cat > gen-from-tmpl.generated.go <<EOF
|
|
||||||
//+build ignore
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import "${zpkg}"
|
|
||||||
import "os"
|
|
||||||
|
|
||||||
func run(fnameIn, fnameOut string) {
|
|
||||||
println("____ " + fnameIn + " --> " + fnameOut + " ______")
|
|
||||||
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)
|
|
||||||
if err != nil { panic(err) }
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
run("fast-path.go.tmpl", "fast-path.generated.go")
|
|
||||||
run("gen-helper.go.tmpl", "gen-helper.generated.go")
|
|
||||||
run("mammoth-test.go.tmpl", "mammoth_generated_test.go")
|
|
||||||
run("mammoth2-test.go.tmpl", "mammoth2_generated_test.go")
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# explicitly return 0 if this passes, else return 1
|
|
||||||
go run -tags "notfastpath safe codecgen.exec" gen-from-tmpl.generated.go &&
|
|
||||||
rm -f gen-from-tmpl.*generated.go &&
|
|
||||||
return 0
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
_codegenerators() {
|
|
||||||
if ! [[ $zforce ||
|
|
||||||
$(_ng "values_codecgen${zsfx}") ]]; then return 0; fi
|
|
||||||
|
|
||||||
# Note: ensure you run the codecgen for this codebase (using $zgobase/bin/codecgen)
|
|
||||||
local c9="codecgen-scratch.go"
|
|
||||||
true &&
|
|
||||||
echo "codecgen ... " &&
|
|
||||||
$zgobase/bin/codecgen -rt codecgen -t 'codecgen generated' -o values_codecgen${zsfx} -d 19780 $zfin $zfin2 &&
|
|
||||||
cp mammoth2_generated_test.go $c9 &&
|
|
||||||
$zgobase/bin/codecgen -t '!notfastpath' -o mammoth2_codecgen${zsfx} -d 19781 mammoth2_generated_test.go &&
|
|
||||||
rm -f $c9 &&
|
|
||||||
echo "generators done!"
|
|
||||||
}
|
|
||||||
|
|
||||||
_prebuild() {
|
|
||||||
echo "prebuild: zforce: $zforce , zexternal: $zexternal"
|
|
||||||
zmydir=`pwd`
|
|
||||||
zfin="test_values.generated.go"
|
|
||||||
zfin2="test_values_flex.generated.go"
|
|
||||||
zsfx="_generated_test.go"
|
|
||||||
# zpkg="ugorji.net/codec"
|
|
||||||
zpkg=${zmydir##*/src/}
|
|
||||||
zgobase=${zmydir%%/src/*}
|
|
||||||
# rm -f *_generated_test.go
|
|
||||||
rm -f codecgen-*.go &&
|
|
||||||
_build &&
|
|
||||||
cp $zmydir/values_test.go $zmydir/$zfin &&
|
|
||||||
cp $zmydir/values_flex_test.go $zmydir/$zfin2 &&
|
|
||||||
_codegenerators &&
|
|
||||||
if [[ "$(type -t _codegenerators_external )" = "function" ]]; then _codegenerators_external ; fi &&
|
|
||||||
if [[ $zforce ]]; then go install ${zargs[*]} .; fi &&
|
|
||||||
echo "prebuild done successfully"
|
|
||||||
rm -f $zmydir/$zfin $zmydir/$zfin2
|
|
||||||
}
|
|
||||||
|
|
||||||
_make() {
|
|
||||||
zforce=1
|
|
||||||
zexternal=1
|
|
||||||
( cd codecgen && go install ${zargs[*]} . ) && _prebuild && go install ${zargs[*]} .
|
|
||||||
unset zforce zexternal
|
|
||||||
}
|
|
||||||
|
|
||||||
_clean() {
|
|
||||||
rm -f gen-from-tmpl.*generated.go \
|
|
||||||
codecgen-*.go \
|
|
||||||
test_values.generated.go test_values_flex.generated.go
|
|
||||||
}
|
|
||||||
|
|
||||||
_usage() {
|
|
||||||
cat <<EOF
|
|
||||||
primary usage: $0
|
|
||||||
-[tmpfxnld] for [tests, make, prebuild (force) (external), inlining diagnostics, mid-stack inlining, race detector]
|
|
||||||
EOF
|
|
||||||
if [[ "$(type -t _usage_run)" = "function" ]]; then _usage_run ; fi
|
|
||||||
}
|
|
||||||
|
|
||||||
_main() {
|
|
||||||
if [[ -z "$1" ]]; then _usage; return 1; fi
|
|
||||||
local x
|
|
||||||
unset zforce zexternal
|
|
||||||
zargs=()
|
|
||||||
while getopts ":ctbqmnrgupfxlzd" flag
|
|
||||||
do
|
|
||||||
case "x$flag" in
|
|
||||||
'xf') zforce=1 ;;
|
|
||||||
'xx') zexternal=1 ;;
|
|
||||||
'xl') zargs+=("-gcflags"); zargs+=("-l=4") ;;
|
|
||||||
'xn') zargs+=("-gcflags"); zargs+=("-m") ;;
|
|
||||||
'xd') zargs+=("-race") ;;
|
|
||||||
x\?) _usage; return 1 ;;
|
|
||||||
*) x=$flag ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
shift $((OPTIND-1))
|
|
||||||
case "x$x" in
|
|
||||||
'xt') _tests "$@" ;;
|
|
||||||
'xq') _benchquick "$@" ;;
|
|
||||||
'xb') _bench "$@" ;;
|
|
||||||
'xm') _make "$@" ;;
|
|
||||||
'xr') _release "$@" ;;
|
|
||||||
'xg') _go ;;
|
|
||||||
'xu') _githubupdate ;;
|
|
||||||
'xp') _prebuild "$@" ;;
|
|
||||||
'xc') _clean "$@" ;;
|
|
||||||
'xz') _analyze "$@" ;;
|
|
||||||
esac
|
|
||||||
unset zforce zexternal
|
|
||||||
}
|
|
||||||
|
|
||||||
[ "." = `dirname $0` ] && _main "$@"
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
|
// 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.
|
// Use of this source code is governed by a MIT license found in the LICENSE file.
|
||||||
|
|
||||||
package codec
|
package codec
|
||||||
|
@ -6,7 +6,6 @@ package codec
|
||||||
import (
|
import (
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -39,8 +38,6 @@ const (
|
||||||
cborBdBreak = 0xff
|
cborBdBreak = 0xff
|
||||||
)
|
)
|
||||||
|
|
||||||
// These define some in-stream descriptors for
|
|
||||||
// manual encoding e.g. when doing explicit indefinite-length
|
|
||||||
const (
|
const (
|
||||||
CborStreamBytes byte = 0x5f
|
CborStreamBytes byte = 0x5f
|
||||||
CborStreamString = 0x7f
|
CborStreamString = 0x7f
|
||||||
|
@ -60,56 +57,15 @@ const (
|
||||||
cborBaseSimple = 0xe0
|
cborBaseSimple = 0xe0
|
||||||
)
|
)
|
||||||
|
|
||||||
func cbordesc(bd byte) string {
|
|
||||||
switch bd {
|
|
||||||
case cborBdNil:
|
|
||||||
return "nil"
|
|
||||||
case cborBdFalse:
|
|
||||||
return "false"
|
|
||||||
case cborBdTrue:
|
|
||||||
return "true"
|
|
||||||
case cborBdFloat16, cborBdFloat32, cborBdFloat64:
|
|
||||||
return "float"
|
|
||||||
case cborBdIndefiniteBytes:
|
|
||||||
return "bytes*"
|
|
||||||
case cborBdIndefiniteString:
|
|
||||||
return "string*"
|
|
||||||
case cborBdIndefiniteArray:
|
|
||||||
return "array*"
|
|
||||||
case cborBdIndefiniteMap:
|
|
||||||
return "map*"
|
|
||||||
default:
|
|
||||||
switch {
|
|
||||||
case bd >= cborBaseUint && bd < cborBaseNegInt:
|
|
||||||
return "(u)int"
|
|
||||||
case bd >= cborBaseNegInt && bd < cborBaseBytes:
|
|
||||||
return "int"
|
|
||||||
case bd >= cborBaseBytes && bd < cborBaseString:
|
|
||||||
return "bytes"
|
|
||||||
case bd >= cborBaseString && bd < cborBaseArray:
|
|
||||||
return "string"
|
|
||||||
case bd >= cborBaseArray && bd < cborBaseMap:
|
|
||||||
return "array"
|
|
||||||
case bd >= cborBaseMap && bd < cborBaseTag:
|
|
||||||
return "map"
|
|
||||||
case bd >= cborBaseTag && bd < cborBaseSimple:
|
|
||||||
return "ext"
|
|
||||||
default:
|
|
||||||
return "unknown"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------------------
|
// -------------------
|
||||||
|
|
||||||
type cborEncDriver struct {
|
type cborEncDriver struct {
|
||||||
noBuiltInTypes
|
noBuiltInTypes
|
||||||
encDriverNoopContainerWriter
|
encNoSeparator
|
||||||
e *Encoder
|
e *Encoder
|
||||||
w encWriter
|
w encWriter
|
||||||
h *CborHandle
|
h *CborHandle
|
||||||
x [8]byte
|
x [8]byte
|
||||||
// _ [3]uint64 // padding
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *cborEncDriver) EncodeNil() {
|
func (e *cborEncDriver) EncodeNil() {
|
||||||
|
@ -167,24 +123,6 @@ func (e *cborEncDriver) encLen(bd byte, length int) {
|
||||||
e.encUint(uint64(length), bd)
|
e.encUint(uint64(length), bd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *cborEncDriver) EncodeTime(t time.Time) {
|
|
||||||
if t.IsZero() {
|
|
||||||
e.EncodeNil()
|
|
||||||
} else if e.h.TimeRFC3339 {
|
|
||||||
e.encUint(0, cborBaseTag)
|
|
||||||
e.EncodeString(cUTF8, t.Format(time.RFC3339Nano))
|
|
||||||
} else {
|
|
||||||
e.encUint(1, cborBaseTag)
|
|
||||||
t = t.UTC().Round(time.Microsecond)
|
|
||||||
sec, nsec := t.Unix(), uint64(t.Nanosecond())
|
|
||||||
if nsec == 0 {
|
|
||||||
e.EncodeInt(sec)
|
|
||||||
} else {
|
|
||||||
e.EncodeFloat64(float64(sec) + float64(nsec)/1e9)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *cborEncDriver) EncodeExt(rv interface{}, xtag uint64, ext Ext, en *Encoder) {
|
func (e *cborEncDriver) EncodeExt(rv interface{}, xtag uint64, ext Ext, en *Encoder) {
|
||||||
e.encUint(uint64(xtag), cborBaseTag)
|
e.encUint(uint64(xtag), cborBaseTag)
|
||||||
if v := ext.ConvertExt(rv); v == nil {
|
if v := ext.ConvertExt(rv); v == nil {
|
||||||
|
@ -196,89 +134,39 @@ func (e *cborEncDriver) EncodeExt(rv interface{}, xtag uint64, ext Ext, en *Enco
|
||||||
|
|
||||||
func (e *cborEncDriver) EncodeRawExt(re *RawExt, en *Encoder) {
|
func (e *cborEncDriver) EncodeRawExt(re *RawExt, en *Encoder) {
|
||||||
e.encUint(uint64(re.Tag), cborBaseTag)
|
e.encUint(uint64(re.Tag), cborBaseTag)
|
||||||
// only encodes re.Value (never re.Data)
|
if re.Data != nil {
|
||||||
// if false && re.Data != nil {
|
en.encode(re.Data)
|
||||||
// en.encode(re.Data)
|
} else if re.Value == nil {
|
||||||
// } else if re.Value != nil {
|
|
||||||
if re.Value != nil {
|
|
||||||
en.encode(re.Value)
|
|
||||||
} else {
|
|
||||||
e.EncodeNil()
|
e.EncodeNil()
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *cborEncDriver) WriteArrayStart(length int) {
|
|
||||||
if e.h.IndefiniteLength {
|
|
||||||
e.w.writen1(cborBdIndefiniteArray)
|
|
||||||
} else {
|
} else {
|
||||||
e.encLen(cborBaseArray, length)
|
en.encode(re.Value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *cborEncDriver) WriteMapStart(length int) {
|
func (e *cborEncDriver) EncodeArrayStart(length int) {
|
||||||
if e.h.IndefiniteLength {
|
e.encLen(cborBaseArray, length)
|
||||||
e.w.writen1(cborBdIndefiniteMap)
|
|
||||||
} else {
|
|
||||||
e.encLen(cborBaseMap, length)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *cborEncDriver) WriteMapEnd() {
|
func (e *cborEncDriver) EncodeMapStart(length int) {
|
||||||
if e.h.IndefiniteLength {
|
e.encLen(cborBaseMap, length)
|
||||||
e.w.writen1(cborBdBreak)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *cborEncDriver) WriteArrayEnd() {
|
|
||||||
if e.h.IndefiniteLength {
|
|
||||||
e.w.writen1(cborBdBreak)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *cborEncDriver) EncodeString(c charEncoding, v string) {
|
func (e *cborEncDriver) EncodeString(c charEncoding, v string) {
|
||||||
e.encStringBytesS(cborBaseString, v)
|
e.encLen(cborBaseString, len(v))
|
||||||
|
e.w.writestr(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *cborEncDriver) EncodeSymbol(v string) {
|
||||||
|
e.EncodeString(c_UTF8, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *cborEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
|
func (e *cborEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
|
||||||
if v == nil {
|
if c == c_RAW {
|
||||||
e.EncodeNil()
|
e.encLen(cborBaseBytes, len(v))
|
||||||
} else if c == cRAW {
|
|
||||||
e.encStringBytesS(cborBaseBytes, stringView(v))
|
|
||||||
} else {
|
} else {
|
||||||
e.encStringBytesS(cborBaseString, stringView(v))
|
e.encLen(cborBaseString, len(v))
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *cborEncDriver) encStringBytesS(bb byte, v string) {
|
|
||||||
if e.h.IndefiniteLength {
|
|
||||||
if bb == cborBaseBytes {
|
|
||||||
e.w.writen1(cborBdIndefiniteBytes)
|
|
||||||
} else {
|
|
||||||
e.w.writen1(cborBdIndefiniteString)
|
|
||||||
}
|
|
||||||
blen := len(v) / 4
|
|
||||||
if blen == 0 {
|
|
||||||
blen = 64
|
|
||||||
} else if blen > 1024 {
|
|
||||||
blen = 1024
|
|
||||||
}
|
|
||||||
for i := 0; i < len(v); {
|
|
||||||
var v2 string
|
|
||||||
i2 := i + blen
|
|
||||||
if i2 < len(v) {
|
|
||||||
v2 = v[i:i2]
|
|
||||||
} else {
|
|
||||||
v2 = v[i:]
|
|
||||||
}
|
|
||||||
e.encLen(bb, len(v2))
|
|
||||||
e.w.writestr(v2)
|
|
||||||
i = i2
|
|
||||||
}
|
|
||||||
e.w.writen1(cborBdBreak)
|
|
||||||
} else {
|
|
||||||
e.encLen(bb, len(v))
|
|
||||||
e.w.writestr(v)
|
|
||||||
}
|
}
|
||||||
|
e.w.writeb(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------
|
// ----------------------
|
||||||
|
@ -287,13 +175,12 @@ type cborDecDriver struct {
|
||||||
d *Decoder
|
d *Decoder
|
||||||
h *CborHandle
|
h *CborHandle
|
||||||
r decReader
|
r decReader
|
||||||
|
b [scratchByteArrayLen]byte
|
||||||
br bool // bytes reader
|
br bool // bytes reader
|
||||||
bdRead bool
|
bdRead bool
|
||||||
bd byte
|
bd byte
|
||||||
noBuiltInTypes
|
noBuiltInTypes
|
||||||
// decNoSeparator
|
decNoSeparator
|
||||||
decDriverNoopContainerReader
|
|
||||||
// _ [3]uint64 // padding
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *cborDecDriver) readNextBd() {
|
func (d *cborDecDriver) readNextBd() {
|
||||||
|
@ -301,17 +188,7 @@ func (d *cborDecDriver) readNextBd() {
|
||||||
d.bdRead = true
|
d.bdRead = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *cborDecDriver) uncacheRead() {
|
|
||||||
if d.bdRead {
|
|
||||||
d.r.unreadn1()
|
|
||||||
d.bdRead = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *cborDecDriver) ContainerType() (vt valueType) {
|
func (d *cborDecDriver) ContainerType() (vt valueType) {
|
||||||
if !d.bdRead {
|
|
||||||
d.readNextBd()
|
|
||||||
}
|
|
||||||
if d.bd == cborBdNil {
|
if d.bd == cborBdNil {
|
||||||
return valueTypeNil
|
return valueTypeNil
|
||||||
} else if d.bd == cborBdIndefiniteBytes || (d.bd >= cborBaseBytes && d.bd < cborBaseString) {
|
} else if d.bd == cborBdIndefiniteBytes || (d.bd >= cborBaseBytes && d.bd < cborBaseString) {
|
||||||
|
@ -322,10 +199,9 @@ func (d *cborDecDriver) ContainerType() (vt valueType) {
|
||||||
return valueTypeArray
|
return valueTypeArray
|
||||||
} else if d.bd == cborBdIndefiniteMap || (d.bd >= cborBaseMap && d.bd < cborBaseTag) {
|
} else if d.bd == cborBdIndefiniteMap || (d.bd >= cborBaseMap && d.bd < cborBaseTag) {
|
||||||
return valueTypeMap
|
return valueTypeMap
|
||||||
|
} else {
|
||||||
|
// d.d.errorf("isContainerType: unsupported parameter: %v", vt)
|
||||||
}
|
}
|
||||||
// else {
|
|
||||||
// d.d.errorf("isContainerType: unsupported parameter: %v", vt)
|
|
||||||
// }
|
|
||||||
return valueTypeUnset
|
return valueTypeUnset
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,7 +242,7 @@ func (d *cborDecDriver) decUint() (ui uint64) {
|
||||||
} else if v == 0x1b {
|
} else if v == 0x1b {
|
||||||
ui = uint64(bigen.Uint64(d.r.readx(8)))
|
ui = uint64(bigen.Uint64(d.r.readx(8)))
|
||||||
} else {
|
} else {
|
||||||
d.d.errorf("invalid descriptor decoding uint: %x/%s", d.bd, cbordesc(d.bd))
|
d.d.errorf("decUint: Invalid descriptor: %v", d.bd)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -382,36 +258,52 @@ func (d *cborDecDriver) decCheckInteger() (neg bool) {
|
||||||
} else if major == cborMajorNegInt {
|
} else if major == cborMajorNegInt {
|
||||||
neg = true
|
neg = true
|
||||||
} else {
|
} else {
|
||||||
d.d.errorf("not an integer - invalid major %v from descriptor %x/%s", major, d.bd, cbordesc(d.bd))
|
d.d.errorf("invalid major: %v (bd: %v)", major, d.bd)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *cborDecDriver) DecodeInt64() (i int64) {
|
func (d *cborDecDriver) DecodeInt(bitsize uint8) (i int64) {
|
||||||
neg := d.decCheckInteger()
|
neg := d.decCheckInteger()
|
||||||
ui := d.decUint()
|
ui := d.decUint()
|
||||||
// check if this number can be converted to an int without overflow
|
// check if this number can be converted to an int without overflow
|
||||||
|
var overflow bool
|
||||||
if neg {
|
if neg {
|
||||||
i = -(chkOvf.SignedIntV(ui + 1))
|
if i, overflow = chkOvf.SignedInt(ui + 1); overflow {
|
||||||
|
d.d.errorf("cbor: overflow converting %v to signed integer", ui+1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
i = -i
|
||||||
} else {
|
} else {
|
||||||
i = chkOvf.SignedIntV(ui)
|
if i, overflow = chkOvf.SignedInt(ui); overflow {
|
||||||
|
d.d.errorf("cbor: overflow converting %v to signed integer", ui)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if chkOvf.Int(i, bitsize) {
|
||||||
|
d.d.errorf("cbor: overflow integer: %v", i)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *cborDecDriver) DecodeUint64() (ui uint64) {
|
func (d *cborDecDriver) DecodeUint(bitsize uint8) (ui uint64) {
|
||||||
if d.decCheckInteger() {
|
if d.decCheckInteger() {
|
||||||
d.d.errorf("assigning negative signed value to unsigned type")
|
d.d.errorf("Assigning negative signed value to unsigned type")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ui = d.decUint()
|
ui = d.decUint()
|
||||||
|
if chkOvf.Uint(ui, bitsize) {
|
||||||
|
d.d.errorf("cbor: overflow integer: %v", ui)
|
||||||
|
return
|
||||||
|
}
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *cborDecDriver) DecodeFloat64() (f float64) {
|
func (d *cborDecDriver) DecodeFloat(chkOverflow32 bool) (f float64) {
|
||||||
if !d.bdRead {
|
if !d.bdRead {
|
||||||
d.readNextBd()
|
d.readNextBd()
|
||||||
}
|
}
|
||||||
|
@ -422,9 +314,13 @@ func (d *cborDecDriver) DecodeFloat64() (f float64) {
|
||||||
} else if bd == cborBdFloat64 {
|
} else if bd == cborBdFloat64 {
|
||||||
f = math.Float64frombits(bigen.Uint64(d.r.readx(8)))
|
f = math.Float64frombits(bigen.Uint64(d.r.readx(8)))
|
||||||
} else if bd >= cborBaseUint && bd < cborBaseBytes {
|
} else if bd >= cborBaseUint && bd < cborBaseBytes {
|
||||||
f = float64(d.DecodeInt64())
|
f = float64(d.DecodeInt(64))
|
||||||
} else {
|
} else {
|
||||||
d.d.errorf("float only valid from float16/32/64 - invalid descriptor %x/%s", bd, cbordesc(bd))
|
d.d.errorf("Float only valid from float16/32/64: Invalid descriptor: %v", bd)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if chkOverflow32 && chkOvf.Float32(f) {
|
||||||
|
d.d.errorf("cbor: float32 overflow: %v", f)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
|
@ -440,7 +336,7 @@ func (d *cborDecDriver) DecodeBool() (b bool) {
|
||||||
b = true
|
b = true
|
||||||
} else if bd == cborBdFalse {
|
} else if bd == cborBdFalse {
|
||||||
} else {
|
} else {
|
||||||
d.d.errorf("not bool - %s %x/%s", msgBadDesc, d.bd, cbordesc(d.bd))
|
d.d.errorf("Invalid single-byte value for bool: %s: %x", msgBadDesc, d.bd)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
|
@ -448,9 +344,6 @@ func (d *cborDecDriver) DecodeBool() (b bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *cborDecDriver) ReadMapStart() (length int) {
|
func (d *cborDecDriver) ReadMapStart() (length int) {
|
||||||
if !d.bdRead {
|
|
||||||
d.readNextBd()
|
|
||||||
}
|
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
if d.bd == cborBdIndefiniteMap {
|
if d.bd == cborBdIndefiniteMap {
|
||||||
return -1
|
return -1
|
||||||
|
@ -459,9 +352,6 @@ func (d *cborDecDriver) ReadMapStart() (length int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *cborDecDriver) ReadArrayStart() (length int) {
|
func (d *cborDecDriver) ReadArrayStart() (length int) {
|
||||||
if !d.bdRead {
|
|
||||||
d.readNextBd()
|
|
||||||
}
|
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
if d.bd == cborBdIndefiniteArray {
|
if d.bd == cborBdIndefiniteArray {
|
||||||
return -1
|
return -1
|
||||||
|
@ -480,8 +370,7 @@ func (d *cborDecDriver) decAppendIndefiniteBytes(bs []byte) []byte {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if major := d.bd >> 5; major != cborMajorBytes && major != cborMajorText {
|
if major := d.bd >> 5; major != cborMajorBytes && major != cborMajorText {
|
||||||
d.d.errorf("expect bytes/string major type in indefinite string/bytes;"+
|
d.d.errorf("cbor: expect bytes or string major type in indefinite string/bytes; got: %v, byte: %v", major, d.bd)
|
||||||
" got major %v from descriptor %x/%x", major, d.bd, cbordesc(d.bd))
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
n := d.decLen()
|
n := d.decLen()
|
||||||
|
@ -502,7 +391,7 @@ func (d *cborDecDriver) decAppendIndefiniteBytes(bs []byte) []byte {
|
||||||
return bs
|
return bs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *cborDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
|
func (d *cborDecDriver) DecodeBytes(bs []byte, isstring, zerocopy bool) (bsOut []byte) {
|
||||||
if !d.bdRead {
|
if !d.bdRead {
|
||||||
d.readNextBd()
|
d.readNextBd()
|
||||||
}
|
}
|
||||||
|
@ -511,84 +400,25 @@ func (d *cborDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if d.bd == cborBdIndefiniteBytes || d.bd == cborBdIndefiniteString {
|
if d.bd == cborBdIndefiniteBytes || d.bd == cborBdIndefiniteString {
|
||||||
d.bdRead = false
|
|
||||||
if bs == nil {
|
if bs == nil {
|
||||||
if zerocopy {
|
return d.decAppendIndefiniteBytes(nil)
|
||||||
return d.decAppendIndefiniteBytes(d.d.b[:0])
|
|
||||||
}
|
|
||||||
return d.decAppendIndefiniteBytes(zeroByteSlice)
|
|
||||||
}
|
}
|
||||||
return d.decAppendIndefiniteBytes(bs[:0])
|
return d.decAppendIndefiniteBytes(bs[:0])
|
||||||
}
|
}
|
||||||
// check if an "array" of uint8's (see ContainerType for how to infer if an array)
|
|
||||||
if d.bd == cborBdIndefiniteArray || (d.bd >= cborBaseArray && d.bd < cborBaseMap) {
|
|
||||||
bsOut, _ = fastpathTV.DecSliceUint8V(bs, true, d.d)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
clen := d.decLen()
|
clen := d.decLen()
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
if zerocopy {
|
if zerocopy {
|
||||||
if d.br {
|
if d.br {
|
||||||
return d.r.readx(clen)
|
return d.r.readx(clen)
|
||||||
} else if len(bs) == 0 {
|
} else if len(bs) == 0 {
|
||||||
bs = d.d.b[:]
|
bs = d.b[:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return decByteSlice(d.r, clen, d.h.MaxInitLen, bs)
|
return decByteSlice(d.r, clen, bs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *cborDecDriver) DecodeString() (s string) {
|
func (d *cborDecDriver) DecodeString() (s string) {
|
||||||
return string(d.DecodeBytes(d.d.b[:], true))
|
return string(d.DecodeBytes(d.b[:], true, true))
|
||||||
}
|
|
||||||
|
|
||||||
func (d *cborDecDriver) DecodeStringAsBytes() (s []byte) {
|
|
||||||
return d.DecodeBytes(d.d.b[:], true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *cborDecDriver) DecodeTime() (t time.Time) {
|
|
||||||
if !d.bdRead {
|
|
||||||
d.readNextBd()
|
|
||||||
}
|
|
||||||
if d.bd == cborBdNil || d.bd == cborBdUndefined {
|
|
||||||
d.bdRead = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
xtag := d.decUint()
|
|
||||||
d.bdRead = false
|
|
||||||
return d.decodeTime(xtag)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *cborDecDriver) decodeTime(xtag uint64) (t time.Time) {
|
|
||||||
if !d.bdRead {
|
|
||||||
d.readNextBd()
|
|
||||||
}
|
|
||||||
switch xtag {
|
|
||||||
case 0:
|
|
||||||
var err error
|
|
||||||
if t, err = time.Parse(time.RFC3339, stringView(d.DecodeStringAsBytes())); err != nil {
|
|
||||||
d.d.errorv(err)
|
|
||||||
}
|
|
||||||
case 1:
|
|
||||||
// decode an int64 or a float, and infer time.Time from there.
|
|
||||||
// for floats, round to microseconds, as that is what is guaranteed to fit well.
|
|
||||||
switch {
|
|
||||||
case d.bd == cborBdFloat16, d.bd == cborBdFloat32:
|
|
||||||
f1, f2 := math.Modf(d.DecodeFloat64())
|
|
||||||
t = time.Unix(int64(f1), int64(f2*1e9))
|
|
||||||
case d.bd == cborBdFloat64:
|
|
||||||
f1, f2 := math.Modf(d.DecodeFloat64())
|
|
||||||
t = time.Unix(int64(f1), int64(f2*1e9))
|
|
||||||
case d.bd >= cborBaseUint && d.bd < cborBaseNegInt,
|
|
||||||
d.bd >= cborBaseNegInt && d.bd < cborBaseBytes:
|
|
||||||
t = time.Unix(d.DecodeInt64(), 0)
|
|
||||||
default:
|
|
||||||
d.d.errorf("time.Time can only be decoded from a number (or RFC3339 string)")
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
d.d.errorf("invalid tag for time.Time - expecting 0 or 1, got 0x%x", xtag)
|
|
||||||
}
|
|
||||||
t = t.UTC().Round(time.Microsecond)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *cborDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) {
|
func (d *cborDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) {
|
||||||
|
@ -619,7 +449,7 @@ func (d *cborDecDriver) DecodeNaked() {
|
||||||
d.readNextBd()
|
d.readNextBd()
|
||||||
}
|
}
|
||||||
|
|
||||||
n := d.d.n
|
n := &d.d.n
|
||||||
var decodeFurther bool
|
var decodeFurther bool
|
||||||
|
|
||||||
switch d.bd {
|
switch d.bd {
|
||||||
|
@ -631,12 +461,15 @@ func (d *cborDecDriver) DecodeNaked() {
|
||||||
case cborBdTrue:
|
case cborBdTrue:
|
||||||
n.v = valueTypeBool
|
n.v = valueTypeBool
|
||||||
n.b = true
|
n.b = true
|
||||||
case cborBdFloat16, cborBdFloat32, cborBdFloat64:
|
case cborBdFloat16, cborBdFloat32:
|
||||||
n.v = valueTypeFloat
|
n.v = valueTypeFloat
|
||||||
n.f = d.DecodeFloat64()
|
n.f = d.DecodeFloat(true)
|
||||||
|
case cborBdFloat64:
|
||||||
|
n.v = valueTypeFloat
|
||||||
|
n.f = d.DecodeFloat(false)
|
||||||
case cborBdIndefiniteBytes:
|
case cborBdIndefiniteBytes:
|
||||||
n.v = valueTypeBytes
|
n.v = valueTypeBytes
|
||||||
n.l = d.DecodeBytes(nil, false)
|
n.l = d.DecodeBytes(nil, false, false)
|
||||||
case cborBdIndefiniteString:
|
case cborBdIndefiniteString:
|
||||||
n.v = valueTypeString
|
n.v = valueTypeString
|
||||||
n.s = d.DecodeString()
|
n.s = d.DecodeString()
|
||||||
|
@ -651,17 +484,17 @@ func (d *cborDecDriver) DecodeNaked() {
|
||||||
case d.bd >= cborBaseUint && d.bd < cborBaseNegInt:
|
case d.bd >= cborBaseUint && d.bd < cborBaseNegInt:
|
||||||
if d.h.SignedInteger {
|
if d.h.SignedInteger {
|
||||||
n.v = valueTypeInt
|
n.v = valueTypeInt
|
||||||
n.i = d.DecodeInt64()
|
n.i = d.DecodeInt(64)
|
||||||
} else {
|
} else {
|
||||||
n.v = valueTypeUint
|
n.v = valueTypeUint
|
||||||
n.u = d.DecodeUint64()
|
n.u = d.DecodeUint(64)
|
||||||
}
|
}
|
||||||
case d.bd >= cborBaseNegInt && d.bd < cborBaseBytes:
|
case d.bd >= cborBaseNegInt && d.bd < cborBaseBytes:
|
||||||
n.v = valueTypeInt
|
n.v = valueTypeInt
|
||||||
n.i = d.DecodeInt64()
|
n.i = d.DecodeInt(64)
|
||||||
case d.bd >= cborBaseBytes && d.bd < cborBaseString:
|
case d.bd >= cborBaseBytes && d.bd < cborBaseString:
|
||||||
n.v = valueTypeBytes
|
n.v = valueTypeBytes
|
||||||
n.l = d.DecodeBytes(nil, false)
|
n.l = d.DecodeBytes(nil, false, false)
|
||||||
case d.bd >= cborBaseString && d.bd < cborBaseArray:
|
case d.bd >= cborBaseString && d.bd < cborBaseArray:
|
||||||
n.v = valueTypeString
|
n.v = valueTypeString
|
||||||
n.s = d.DecodeString()
|
n.s = d.DecodeString()
|
||||||
|
@ -675,11 +508,6 @@ func (d *cborDecDriver) DecodeNaked() {
|
||||||
n.v = valueTypeExt
|
n.v = valueTypeExt
|
||||||
n.u = d.decUint()
|
n.u = d.decUint()
|
||||||
n.l = nil
|
n.l = nil
|
||||||
if n.u == 0 || n.u == 1 {
|
|
||||||
d.bdRead = false
|
|
||||||
n.v = valueTypeTime
|
|
||||||
n.t = d.decodeTime(n.u)
|
|
||||||
}
|
|
||||||
// d.bdRead = false
|
// d.bdRead = false
|
||||||
// d.d.decode(&re.Value) // handled by decode itself.
|
// d.d.decode(&re.Value) // handled by decode itself.
|
||||||
// decodeFurther = true
|
// decodeFurther = true
|
||||||
|
@ -710,29 +538,30 @@ func (d *cborDecDriver) DecodeNaked() {
|
||||||
//
|
//
|
||||||
// None of the optional extensions (with tags) defined in the spec are supported out-of-the-box.
|
// None of the optional extensions (with tags) defined in the spec are supported out-of-the-box.
|
||||||
// Users can implement them as needed (using SetExt), including spec-documented ones:
|
// Users can implement them as needed (using SetExt), including spec-documented ones:
|
||||||
// - timestamp, BigNum, BigFloat, Decimals,
|
// - timestamp, BigNum, BigFloat, Decimals, Encoded Text (e.g. URL, regexp, base64, MIME Message), etc.
|
||||||
// - Encoded Text (e.g. URL, regexp, base64, MIME Message), etc.
|
//
|
||||||
|
// To encode with indefinite lengths (streaming), users will use
|
||||||
|
// (Must)Encode methods of *Encoder, along with writing CborStreamXXX constants.
|
||||||
|
//
|
||||||
|
// For example, to encode "one-byte" as an indefinite length string:
|
||||||
|
// var buf bytes.Buffer
|
||||||
|
// e := NewEncoder(&buf, new(CborHandle))
|
||||||
|
// buf.WriteByte(CborStreamString)
|
||||||
|
// e.MustEncode("one-")
|
||||||
|
// e.MustEncode("byte")
|
||||||
|
// buf.WriteByte(CborStreamBreak)
|
||||||
|
// encodedBytes := buf.Bytes()
|
||||||
|
// var vv interface{}
|
||||||
|
// NewDecoderBytes(buf.Bytes(), new(CborHandle)).MustDecode(&vv)
|
||||||
|
// // Now, vv contains the same string "one-byte"
|
||||||
|
//
|
||||||
type CborHandle struct {
|
type CborHandle struct {
|
||||||
binaryEncodingType
|
binaryEncodingType
|
||||||
noElemSeparators
|
|
||||||
BasicHandle
|
BasicHandle
|
||||||
|
|
||||||
// IndefiniteLength=true, means that we encode using indefinitelength
|
|
||||||
IndefiniteLength bool
|
|
||||||
|
|
||||||
// TimeRFC3339 says to encode time.Time using RFC3339 format.
|
|
||||||
// If unset, we encode time.Time using seconds past epoch.
|
|
||||||
TimeRFC3339 bool
|
|
||||||
|
|
||||||
// _ [1]uint64 // padding
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name returns the name of the handle: cbor
|
|
||||||
func (h *CborHandle) Name() string { return "cbor" }
|
|
||||||
|
|
||||||
// SetInterfaceExt sets an extension
|
|
||||||
func (h *CborHandle) SetInterfaceExt(rt reflect.Type, tag uint64, ext InterfaceExt) (err error) {
|
func (h *CborHandle) SetInterfaceExt(rt reflect.Type, tag uint64, ext InterfaceExt) (err error) {
|
||||||
return h.SetExt(rt, tag, &extWrapper{bytesExtFailer{}, ext})
|
return h.SetExt(rt, tag, &setExtWrapper{i: ext})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *CborHandle) newEncDriver(e *Encoder) encDriver {
|
func (h *CborHandle) newEncDriver(e *Encoder) encDriver {
|
||||||
|
@ -740,7 +569,7 @@ func (h *CborHandle) newEncDriver(e *Encoder) encDriver {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *CborHandle) newDecDriver(d *Decoder) decDriver {
|
func (h *CborHandle) newDecDriver(d *Decoder) decDriver {
|
||||||
return &cborDecDriver{d: d, h: h, r: d.r, br: d.bytes}
|
return &cborDecDriver{d: d, r: d.r, h: h, br: d.bytes}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *cborEncDriver) reset() {
|
func (e *cborEncDriver) reset() {
|
||||||
|
@ -748,7 +577,7 @@ func (e *cborEncDriver) reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *cborDecDriver) reset() {
|
func (d *cborDecDriver) reset() {
|
||||||
d.r, d.br = d.d.r, d.d.bytes
|
d.r = d.d.r
|
||||||
d.bd, d.bdRead = 0, false
|
d.bd, d.bdRead = 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -3,7 +3,10 @@
|
||||||
// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
|
// 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.
|
// Use of this source code is governed by a MIT license found in the LICENSE file.
|
||||||
|
|
||||||
// Code generated from fast-path.go.tmpl - DO NOT EDIT.
|
// ************************************************************
|
||||||
|
// DO NOT EDIT.
|
||||||
|
// THIS FILE IS AUTO-GENERATED from fast-path.go.tmpl
|
||||||
|
// ************************************************************
|
||||||
|
|
||||||
package codec
|
package codec
|
||||||
|
|
||||||
|
@ -15,19 +18,19 @@ package codec
|
||||||
// This file can be omitted without causing a build failure.
|
// This file can be omitted without causing a build failure.
|
||||||
//
|
//
|
||||||
// The advantage of fast paths is:
|
// The advantage of fast paths is:
|
||||||
// - Many calls bypass reflection altogether
|
// - Many calls bypass reflection altogether
|
||||||
//
|
//
|
||||||
// Currently support
|
// Currently support
|
||||||
// - slice of all builtin types,
|
// - slice of all builtin types,
|
||||||
// - map of all builtin types to string or interface value
|
// - map of all builtin types to string or interface value
|
||||||
// - symmetrical maps of all builtin types (e.g. str-str, uint8-uint8)
|
// - symetrical maps of all builtin types (e.g. str-str, uint8-uint8)
|
||||||
// This should provide adequate "typical" implementations.
|
// This should provide adequate "typical" implementations.
|
||||||
//
|
//
|
||||||
// Note that fast track decode functions must handle values for which an address cannot be obtained.
|
// Note that fast track decode functions must handle values for which an address cannot be obtained.
|
||||||
// For example:
|
// For example:
|
||||||
// m2 := map[string]int{}
|
// m2 := map[string]int{}
|
||||||
// p2 := []interface{}{m2}
|
// p2 := []interface{}{m2}
|
||||||
// // decoding into p2 will bomb if fast track functions do not treat like unaddressable.
|
// // decoding into p2 will bomb if fast track functions do not treat like unaddressable.
|
||||||
//
|
//
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -35,7 +38,8 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
)
|
)
|
||||||
|
|
||||||
const fastpathEnabled = true
|
const fastpathCheckNilFalse = false // for reflect
|
||||||
|
const fastpathCheckNilTrue = true // for type switch
|
||||||
|
|
||||||
type fastpathT struct {}
|
type fastpathT struct {}
|
||||||
|
|
||||||
|
@ -44,8 +48,8 @@ var fastpathTV fastpathT
|
||||||
type fastpathE struct {
|
type fastpathE struct {
|
||||||
rtid uintptr
|
rtid uintptr
|
||||||
rt reflect.Type
|
rt reflect.Type
|
||||||
encfn func(*Encoder, *codecFnInfo, reflect.Value)
|
encfn func(*encFnInfo, reflect.Value)
|
||||||
decfn func(*Decoder, *codecFnInfo, reflect.Value)
|
decfn func(*decFnInfo, reflect.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
type fastpathA [{{ .FastpathLen }}]fastpathE
|
type fastpathA [{{ .FastpathLen }}]fastpathE
|
||||||
|
@ -77,22 +81,23 @@ var fastpathAV fastpathA
|
||||||
|
|
||||||
// due to possible initialization loop error, make fastpath in an init()
|
// due to possible initialization loop error, make fastpath in an init()
|
||||||
func init() {
|
func init() {
|
||||||
|
if !fastpathEnabled {
|
||||||
|
return
|
||||||
|
}
|
||||||
i := 0
|
i := 0
|
||||||
fn := func(v interface{},
|
fn := func(v interface{}, fe func(*encFnInfo, reflect.Value), fd func(*decFnInfo, reflect.Value)) (f fastpathE) {
|
||||||
fe func(*Encoder, *codecFnInfo, reflect.Value),
|
|
||||||
fd func(*Decoder, *codecFnInfo, reflect.Value)) (f fastpathE) {
|
|
||||||
xrt := reflect.TypeOf(v)
|
xrt := reflect.TypeOf(v)
|
||||||
xptr := rt2id(xrt)
|
xptr := reflect.ValueOf(xrt).Pointer()
|
||||||
fastpathAV[i] = fastpathE{xptr, xrt, fe, fd}
|
fastpathAV[i] = fastpathE{xptr, xrt, fe, fd}
|
||||||
i++
|
i++
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
{{/* do not register []uint8 in fast-path */}}
|
|
||||||
{{range .Values}}{{if not .Primitive}}{{if not .MapKey }}{{if ne .Elem "uint8"}}
|
{{range .Values}}{{if not .Primitive}}{{if not .MapKey }}
|
||||||
fn([]{{ .Elem }}(nil), (*Encoder).{{ .MethodNamePfx "fastpathEnc" false }}R, (*Decoder).{{ .MethodNamePfx "fastpathDec" false }}R){{end}}{{end}}{{end}}{{end}}
|
fn([]{{ .Elem }}(nil), (*encFnInfo).{{ .MethodNamePfx "fastpathEnc" false }}R, (*decFnInfo).{{ .MethodNamePfx "fastpathDec" false }}R){{end}}{{end}}{{end}}
|
||||||
|
|
||||||
{{range .Values}}{{if not .Primitive}}{{if .MapKey }}
|
{{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}}
|
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(fastpathAV[:]))
|
||||||
}
|
}
|
||||||
|
@ -101,150 +106,128 @@ func init() {
|
||||||
|
|
||||||
// -- -- fast path type switch
|
// -- -- fast path type switch
|
||||||
func fastpathEncodeTypeSwitch(iv interface{}, e *Encoder) bool {
|
func fastpathEncodeTypeSwitch(iv interface{}, e *Encoder) bool {
|
||||||
|
if !fastpathEnabled {
|
||||||
|
return false
|
||||||
|
}
|
||||||
switch v := iv.(type) {
|
switch v := iv.(type) {
|
||||||
|
{{range .Values}}{{if not .Primitive}}{{if not .MapKey }}
|
||||||
{{range .Values}}{{if not .Primitive}}{{if not .MapKey }}{{if ne .Elem "uint8"}}
|
case []{{ .Elem }}:{{else}}
|
||||||
case []{{ .Elem }}:
|
case map[{{ .MapKey }}]{{ .Elem }}:{{end}}
|
||||||
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, e)
|
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, fastpathCheckNilTrue, e){{if not .MapKey }}
|
||||||
case *[]{{ .Elem }}:
|
case *[]{{ .Elem }}:{{else}}
|
||||||
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, e){{/*
|
case *map[{{ .MapKey }}]{{ .Elem }}:{{end}}
|
||||||
*/}}{{end}}{{end}}{{end}}{{end}}
|
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, fastpathCheckNilTrue, e)
|
||||||
|
{{end}}{{end}}
|
||||||
{{range .Values}}{{if not .Primitive}}{{if .MapKey }}
|
|
||||||
case map[{{ .MapKey }}]{{ .Elem }}:
|
|
||||||
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, e)
|
|
||||||
case *map[{{ .MapKey }}]{{ .Elem }}:
|
|
||||||
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, e){{/*
|
|
||||||
*/}}{{end}}{{end}}{{end}}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
_ = v // workaround https://github.com/golang/go/issues/12927 seen in go1.4
|
_ = v // TODO: workaround https://github.com/golang/go/issues/12927 (remove after go 1.6 release)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
{{/*
|
|
||||||
**** removing this block, as they are never called directly ****
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
**** removing this block, as they are never called directly ****
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func fastpathEncodeTypeSwitchSlice(iv interface{}, e *Encoder) bool {
|
func fastpathEncodeTypeSwitchSlice(iv interface{}, e *Encoder) bool {
|
||||||
|
if !fastpathEnabled {
|
||||||
|
return false
|
||||||
|
}
|
||||||
switch v := iv.(type) {
|
switch v := iv.(type) {
|
||||||
{{range .Values}}{{if not .Primitive}}{{if not .MapKey }}
|
{{range .Values}}{{if not .Primitive}}{{if not .MapKey }}
|
||||||
case []{{ .Elem }}:
|
case []{{ .Elem }}:
|
||||||
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, e)
|
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, fastpathCheckNilTrue, e)
|
||||||
case *[]{{ .Elem }}:
|
case *[]{{ .Elem }}:
|
||||||
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, e)
|
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, fastpathCheckNilTrue, e)
|
||||||
{{end}}{{end}}{{end}}
|
{{end}}{{end}}{{end}}
|
||||||
default:
|
default:
|
||||||
_ = v // workaround https://github.com/golang/go/issues/12927 seen in go1.4
|
_ = v // TODO: workaround https://github.com/golang/go/issues/12927 (remove after go 1.6 release)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func fastpathEncodeTypeSwitchMap(iv interface{}, e *Encoder) bool {
|
func fastpathEncodeTypeSwitchMap(iv interface{}, e *Encoder) bool {
|
||||||
|
if !fastpathEnabled {
|
||||||
|
return false
|
||||||
|
}
|
||||||
switch v := iv.(type) {
|
switch v := iv.(type) {
|
||||||
{{range .Values}}{{if not .Primitive}}{{if .MapKey }}
|
{{range .Values}}{{if not .Primitive}}{{if .MapKey }}
|
||||||
case map[{{ .MapKey }}]{{ .Elem }}:
|
case map[{{ .MapKey }}]{{ .Elem }}:
|
||||||
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, e)
|
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, fastpathCheckNilTrue, e)
|
||||||
case *map[{{ .MapKey }}]{{ .Elem }}:
|
case *map[{{ .MapKey }}]{{ .Elem }}:
|
||||||
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, e)
|
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, fastpathCheckNilTrue, e)
|
||||||
{{end}}{{end}}{{end}}
|
{{end}}{{end}}{{end}}
|
||||||
default:
|
default:
|
||||||
_ = v // workaround https://github.com/golang/go/issues/12927 seen in go1.4
|
_ = v // TODO: workaround https://github.com/golang/go/issues/12927 (remove after go 1.6 release)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
**** removing this block, as they are never called directly ****
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
**** removing this block, as they are never called directly ****
|
|
||||||
*/}}
|
|
||||||
|
|
||||||
// -- -- fast path functions
|
// -- -- fast path functions
|
||||||
{{range .Values}}{{if not .Primitive}}{{if not .MapKey }}
|
{{range .Values}}{{if not .Primitive}}{{if not .MapKey }}
|
||||||
func (e *Encoder) {{ .MethodNamePfx "fastpathEnc" false }}R(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
|
func (f *encFnInfo) {{ .MethodNamePfx "fastpathEnc" false }}R(rv reflect.Value) {
|
||||||
if f.ti.mbs {
|
if f.ti.mbs {
|
||||||
fastpathTV.{{ .MethodNamePfx "EncAsMap" false }}V(rv2i(rv).([]{{ .Elem }}), e)
|
fastpathTV.{{ .MethodNamePfx "EncAsMap" false }}V(rv.Interface().([]{{ .Elem }}), fastpathCheckNilFalse, f.e)
|
||||||
} else {
|
} else {
|
||||||
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(rv2i(rv).([]{{ .Elem }}), e)
|
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(rv.Interface().([]{{ .Elem }}), fastpathCheckNilFalse, f.e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (_ fastpathT) {{ .MethodNamePfx "Enc" false }}V(v []{{ .Elem }}, e *Encoder) {
|
func (_ fastpathT) {{ .MethodNamePfx "Enc" false }}V(v []{{ .Elem }}, checkNil bool, e *Encoder) {
|
||||||
if v == nil { e.e.EncodeNil(); return }
|
ee := e.e
|
||||||
ee, esep := e.e, e.hh.hasElemSeparators()
|
cr := e.cr
|
||||||
ee.WriteArrayStart(len(v))
|
if checkNil && v == nil {
|
||||||
if esep {
|
ee.EncodeNil()
|
||||||
for _, v2 := range v {
|
return
|
||||||
ee.WriteArrayElem()
|
}
|
||||||
{{ encmd .Elem "v2"}}
|
ee.EncodeArrayStart(len(v))
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for _, v2 := range v {
|
|
||||||
{{ encmd .Elem "v2"}}
|
|
||||||
}
|
|
||||||
} {{/*
|
|
||||||
for _, v2 := range v {
|
for _, v2 := range v {
|
||||||
if esep { ee.WriteArrayElem() }
|
if cr != nil { cr.sendContainerState(containerArrayElem) }
|
||||||
{{ encmd .Elem "v2"}}
|
{{ encmd .Elem "v2"}}
|
||||||
} */}}
|
}
|
||||||
ee.WriteArrayEnd()
|
if cr != nil { cr.sendContainerState(containerArrayEnd) }{{/* ee.EncodeEnd() */}}
|
||||||
}
|
}
|
||||||
func (_ fastpathT) {{ .MethodNamePfx "EncAsMap" false }}V(v []{{ .Elem }}, e *Encoder) {
|
|
||||||
ee, esep := e.e, e.hh.hasElemSeparators()
|
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
|
||||||
|
}
|
||||||
if len(v)%2 == 1 {
|
if len(v)%2 == 1 {
|
||||||
e.errorf("mapBySlice requires even slice length, but got %v", len(v))
|
e.errorf("mapBySlice requires even slice length, but got %v", len(v))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ee.WriteMapStart(len(v) / 2)
|
ee.EncodeMapStart(len(v) / 2)
|
||||||
if esep {
|
|
||||||
for j, v2 := range v {
|
|
||||||
if j%2 == 0 {
|
|
||||||
ee.WriteMapElemKey()
|
|
||||||
} else {
|
|
||||||
ee.WriteMapElemValue()
|
|
||||||
}
|
|
||||||
{{ encmd .Elem "v2"}}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for _, v2 := range v {
|
|
||||||
{{ encmd .Elem "v2"}}
|
|
||||||
}
|
|
||||||
} {{/*
|
|
||||||
for j, v2 := range v {
|
for j, v2 := range v {
|
||||||
if esep {
|
if cr != nil {
|
||||||
if j%2 == 0 {
|
if j%2 == 0 {
|
||||||
ee.WriteMapElemKey()
|
cr.sendContainerState(containerMapKey)
|
||||||
} else {
|
} else {
|
||||||
ee.WriteMapElemValue()
|
cr.sendContainerState(containerMapValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{{ encmd .Elem "v2"}}
|
{{ encmd .Elem "v2"}}
|
||||||
} */}}
|
}
|
||||||
ee.WriteMapEnd()
|
if cr != nil { cr.sendContainerState(containerMapEnd) }
|
||||||
}
|
}
|
||||||
|
|
||||||
{{end}}{{end}}{{end}}
|
{{end}}{{end}}{{end}}
|
||||||
|
|
||||||
{{range .Values}}{{if not .Primitive}}{{if .MapKey }}
|
{{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 (f *encFnInfo) {{ .MethodNamePfx "fastpathEnc" false }}R(rv reflect.Value) {
|
||||||
|
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(rv.Interface().(map[{{ .MapKey }}]{{ .Elem }}), fastpathCheckNilFalse, f.e)
|
||||||
}
|
}
|
||||||
func (_ fastpathT) {{ .MethodNamePfx "Enc" false }}V(v map[{{ .MapKey }}]{{ .Elem }}, e *Encoder) {
|
func (_ fastpathT) {{ .MethodNamePfx "Enc" false }}V(v map[{{ .MapKey }}]{{ .Elem }}, checkNil bool, e *Encoder) {
|
||||||
if v == nil { e.e.EncodeNil(); return }
|
ee := e.e
|
||||||
ee, esep := e.e, e.hh.hasElemSeparators()
|
cr := e.cr
|
||||||
ee.WriteMapStart(len(v))
|
if checkNil && v == nil {
|
||||||
if e.h.Canonical {
|
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
|
{{if eq .MapKey "interface{}"}}{{/* out of band
|
||||||
*/}}var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding
|
*/}}var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding
|
||||||
e2 := NewEncoderBytes(&mksv, e.hh)
|
e2 := NewEncoderBytes(&mksv, e.hh)
|
||||||
|
@ -260,126 +243,66 @@ func (_ fastpathT) {{ .MethodNamePfx "Enc" false }}V(v map[{{ .MapKey }}]{{ .Ele
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
sort.Sort(bytesISlice(v2))
|
sort.Sort(bytesISlice(v2))
|
||||||
if esep {
|
|
||||||
for j := range v2 {
|
|
||||||
ee.WriteMapElemKey()
|
|
||||||
e.asis(v2[j].v)
|
|
||||||
ee.WriteMapElemValue()
|
|
||||||
e.encode(v[v2[j].i])
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for j := range v2 {
|
|
||||||
e.asis(v2[j].v)
|
|
||||||
e.encode(v[v2[j].i])
|
|
||||||
}
|
|
||||||
} {{/*
|
|
||||||
for j := range v2 {
|
for j := range v2 {
|
||||||
if esep { ee.WriteMapElemKey() }
|
if cr != nil { cr.sendContainerState(containerMapKey) }
|
||||||
e.asis(v2[j].v)
|
e.asis(v2[j].v)
|
||||||
if esep { ee.WriteMapElemValue() }
|
if cr != nil { cr.sendContainerState(containerMapValue) }
|
||||||
e.encode(v[v2[j].i])
|
e.encode(v[v2[j].i])
|
||||||
} */}} {{else}}{{ $x := sorttype .MapKey true}}v2 := make([]{{ $x }}, len(v))
|
} {{else}}{{ $x := sorttype .MapKey true}}v2 := make([]{{ $x }}, len(v))
|
||||||
var i int
|
var i int
|
||||||
for k, _ := range v {
|
for k, _ := range v {
|
||||||
v2[i] = {{ $x }}(k)
|
v2[i] = {{ $x }}(k)
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
sort.Sort({{ sorttype .MapKey false}}(v2))
|
sort.Sort({{ sorttype .MapKey false}}(v2))
|
||||||
if esep {
|
|
||||||
for _, k2 := range v2 {
|
|
||||||
ee.WriteMapElemKey()
|
|
||||||
{{if eq .MapKey "string"}}ee.EncodeString(cUTF8, k2){{else}}{{ $y := printf "%s(k2)" .MapKey }}{{ encmd .MapKey $y }}{{end}}
|
|
||||||
ee.WriteMapElemValue()
|
|
||||||
{{ $y := printf "v[%s(k2)]" .MapKey }}{{ encmd .Elem $y }}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for _, k2 := range v2 {
|
|
||||||
{{if eq .MapKey "string"}}ee.EncodeString(cUTF8, k2){{else}}{{ $y := printf "%s(k2)" .MapKey }}{{ encmd .MapKey $y }}{{end}}
|
|
||||||
{{ $y := printf "v[%s(k2)]" .MapKey }}{{ encmd .Elem $y }}
|
|
||||||
}
|
|
||||||
} {{/*
|
|
||||||
for _, k2 := range v2 {
|
for _, k2 := range v2 {
|
||||||
if esep { ee.WriteMapElemKey() }
|
if cr != nil { cr.sendContainerState(containerMapKey) }
|
||||||
{{if eq .MapKey "string"}}ee.EncodeString(cUTF8, k2){{else}}{{ $y := printf "%s(k2)" .MapKey }}{{ encmd .MapKey $y }}{{end}}
|
{{if eq .MapKey "string"}}if asSymbols {
|
||||||
if esep { ee.WriteMapElemValue() }
|
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 }}
|
{{ $y := printf "v[%s(k2)]" .MapKey }}{{ encmd .Elem $y }}
|
||||||
} */}} {{end}}
|
} {{end}}
|
||||||
} else {
|
} else {
|
||||||
if esep {
|
|
||||||
for k2, v2 := range v {
|
|
||||||
ee.WriteMapElemKey()
|
|
||||||
{{if eq .MapKey "string"}}ee.EncodeString(cUTF8, k2){{else}}{{ encmd .MapKey "k2"}}{{end}}
|
|
||||||
ee.WriteMapElemValue()
|
|
||||||
{{ encmd .Elem "v2"}}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for k2, v2 := range v {
|
|
||||||
{{if eq .MapKey "string"}}ee.EncodeString(cUTF8, k2){{else}}{{ encmd .MapKey "k2"}}{{end}}
|
|
||||||
{{ encmd .Elem "v2"}}
|
|
||||||
}
|
|
||||||
} {{/*
|
|
||||||
for k2, v2 := range v {
|
for k2, v2 := range v {
|
||||||
if esep { ee.WriteMapElemKey() }
|
if cr != nil { cr.sendContainerState(containerMapKey) }
|
||||||
{{if eq .MapKey "string"}}ee.EncodeString(cUTF8, k2){{else}}{{ encmd .MapKey "k2"}}{{end}}
|
{{if eq .MapKey "string"}}if asSymbols {
|
||||||
if esep { ee.WriteMapElemValue() }
|
ee.EncodeSymbol(k2)
|
||||||
|
} else {
|
||||||
|
ee.EncodeString(c_UTF8, k2)
|
||||||
|
}{{else}}{{ encmd .MapKey "k2"}}{{end}}
|
||||||
|
if cr != nil { cr.sendContainerState(containerMapValue) }
|
||||||
{{ encmd .Elem "v2"}}
|
{{ encmd .Elem "v2"}}
|
||||||
} */}}
|
}
|
||||||
}
|
}
|
||||||
ee.WriteMapEnd()
|
if cr != nil { cr.sendContainerState(containerMapEnd) }{{/* ee.EncodeEnd() */}}
|
||||||
}
|
}
|
||||||
|
|
||||||
{{end}}{{end}}{{end}}
|
{{end}}{{end}}{{end}}
|
||||||
|
|
||||||
// -- decode
|
// -- decode
|
||||||
|
|
||||||
// -- -- fast path type switch
|
// -- -- fast path type switch
|
||||||
func fastpathDecodeTypeSwitch(iv interface{}, d *Decoder) bool {
|
func fastpathDecodeTypeSwitch(iv interface{}, d *Decoder) bool {
|
||||||
var changed bool
|
if !fastpathEnabled {
|
||||||
switch v := iv.(type) {
|
|
||||||
{{range .Values}}{{if not .Primitive}}{{if not .MapKey }}{{if ne .Elem "uint8"}}
|
|
||||||
case []{{ .Elem }}:
|
|
||||||
var v2 []{{ .Elem }}
|
|
||||||
v2, changed = fastpathTV.{{ .MethodNamePfx "Dec" false }}V(v, false, d)
|
|
||||||
if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
|
|
||||||
copy(v, v2)
|
|
||||||
}
|
|
||||||
case *[]{{ .Elem }}:
|
|
||||||
var v2 []{{ .Elem }}
|
|
||||||
v2, changed = fastpathTV.{{ .MethodNamePfx "Dec" false }}V(*v, true, d)
|
|
||||||
if changed {
|
|
||||||
*v = v2
|
|
||||||
}{{/*
|
|
||||||
*/}}{{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 }}:
|
|
||||||
fastpathTV.{{ .MethodNamePfx "Dec" false }}V(v, false, d)
|
|
||||||
case *map[{{ .MapKey }}]{{ .Elem }}:
|
|
||||||
var v2 map[{{ .MapKey }}]{{ .Elem }}
|
|
||||||
v2, changed = fastpathTV.{{ .MethodNamePfx "Dec" false }}V(*v, true, d)
|
|
||||||
if changed {
|
|
||||||
*v = v2
|
|
||||||
}{{/*
|
|
||||||
*/}}{{end}}{{end}}{{end}}
|
|
||||||
default:
|
|
||||||
_ = v // workaround https://github.com/golang/go/issues/12927 seen in go1.4
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func fastpathDecodeSetZeroTypeSwitch(iv interface{}) bool {
|
|
||||||
switch v := iv.(type) {
|
switch v := iv.(type) {
|
||||||
{{range .Values}}{{if not .Primitive}}{{if not .MapKey }}
|
{{range .Values}}{{if not .Primitive}}{{if not .MapKey }}
|
||||||
case *[]{{ .Elem }}:
|
case []{{ .Elem }}:{{else}}
|
||||||
*v = nil {{/*
|
case map[{{ .MapKey }}]{{ .Elem }}:{{end}}
|
||||||
*/}}{{end}}{{end}}{{end}}
|
fastpathTV.{{ .MethodNamePfx "Dec" false }}V(v, fastpathCheckNilFalse, false, d){{if not .MapKey }}
|
||||||
{{range .Values}}{{if not .Primitive}}{{if .MapKey }}
|
case *[]{{ .Elem }}:{{else}}
|
||||||
case *map[{{ .MapKey }}]{{ .Elem }}:
|
case *map[{{ .MapKey }}]{{ .Elem }}:{{end}}
|
||||||
*v = nil {{/*
|
v2, changed2 := fastpathTV.{{ .MethodNamePfx "Dec" false }}V(*v, fastpathCheckNilFalse, true, d)
|
||||||
*/}}{{end}}{{end}}{{end}}
|
if changed2 {
|
||||||
|
*v = v2
|
||||||
|
}
|
||||||
|
{{end}}{{end}}
|
||||||
default:
|
default:
|
||||||
_ = v // workaround https://github.com/golang/go/issues/12927 seen in go1.4
|
_ = v // TODO: workaround https://github.com/golang/go/issues/12927 (remove after go 1.6 release)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
@ -393,152 +316,225 @@ Slices can change if they
|
||||||
- are addressable (from a ptr)
|
- are addressable (from a ptr)
|
||||||
- are settable (e.g. contained in an interface{})
|
- are settable (e.g. contained in an interface{})
|
||||||
*/}}
|
*/}}
|
||||||
func (d *Decoder) {{ .MethodNamePfx "fastpathDec" false }}R(f *codecFnInfo, rv reflect.Value) {
|
func (f *decFnInfo) {{ .MethodNamePfx "fastpathDec" false }}R(rv reflect.Value) {
|
||||||
if array := f.seq == seqTypeArray; !array && rv.Kind() == reflect.Ptr {
|
array := f.seq == seqTypeArray
|
||||||
vp := rv2i(rv).(*[]{{ .Elem }})
|
if !array && rv.CanAddr() { {{/* // CanSet => CanAddr + Exported */}}
|
||||||
v, changed := fastpathTV.{{ .MethodNamePfx "Dec" false }}V(*vp, !array, d)
|
vp := rv.Addr().Interface().(*[]{{ .Elem }})
|
||||||
if changed { *vp = v }
|
v, changed := fastpathTV.{{ .MethodNamePfx "Dec" false }}V(*vp, fastpathCheckNilFalse, !array, f.d)
|
||||||
|
if changed {
|
||||||
|
*vp = v
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
v := rv2i(rv).([]{{ .Elem }})
|
v := rv.Interface().([]{{ .Elem }})
|
||||||
v2, changed := fastpathTV.{{ .MethodNamePfx "Dec" false }}V(v, !array, d)
|
fastpathTV.{{ .MethodNamePfx "Dec" false }}V(v, fastpathCheckNilFalse, false, f.d)
|
||||||
if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
|
|
||||||
copy(v, v2)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (f fastpathT) {{ .MethodNamePfx "Dec" false }}X(vp *[]{{ .Elem }}, d *Decoder) {
|
|
||||||
v, changed := f.{{ .MethodNamePfx "Dec" false }}V(*vp, true, d)
|
func (f fastpathT) {{ .MethodNamePfx "Dec" false }}X(vp *[]{{ .Elem }}, checkNil bool, d *Decoder) {
|
||||||
if changed { *vp = v }
|
v, changed := f.{{ .MethodNamePfx "Dec" false }}V(*vp, checkNil, true, d)
|
||||||
|
if changed {
|
||||||
|
*vp = v
|
||||||
|
}
|
||||||
}
|
}
|
||||||
func (_ fastpathT) {{ .MethodNamePfx "Dec" false }}V(v []{{ .Elem }}, canChange bool, d *Decoder) (_ []{{ .Elem }}, changed bool) {
|
func (_ fastpathT) {{ .MethodNamePfx "Dec" false }}V(v []{{ .Elem }}, checkNil bool, canChange bool, d *Decoder) (_ []{{ .Elem }}, changed bool) {
|
||||||
dd := d.d{{/*
|
dd := d.d
|
||||||
// if dd.isContainerType(valueTypeNil) { dd.TryDecodeAsNil()
|
{{/* // if dd.isContainerType(valueTypeNil) { dd.TryDecodeAsNil() */}}
|
||||||
*/}}
|
if checkNil && dd.TryDecodeAsNil() {
|
||||||
|
if v != nil {
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
return nil, changed
|
||||||
|
}
|
||||||
|
|
||||||
slh, containerLenS := d.decSliceHelperStart()
|
slh, containerLenS := d.decSliceHelperStart()
|
||||||
if containerLenS == 0 {
|
if containerLenS == 0 {
|
||||||
if canChange {
|
if canChange {
|
||||||
if v == nil { v = []{{ .Elem }}{} } else if len(v) != 0 { v = v[:0] }
|
if v == nil {
|
||||||
|
v = []{{ .Elem }}{}
|
||||||
|
} else if len(v) != 0 {
|
||||||
|
v = v[:0]
|
||||||
|
}
|
||||||
changed = true
|
changed = true
|
||||||
}
|
}
|
||||||
slh.End()
|
slh.End()
|
||||||
return v, changed
|
return v, changed
|
||||||
}
|
}
|
||||||
hasLen := containerLenS > 0
|
|
||||||
var xlen int
|
if containerLenS > 0 {
|
||||||
if hasLen && canChange {
|
x2read := containerLenS
|
||||||
|
var xtrunc bool
|
||||||
if containerLenS > cap(v) {
|
if containerLenS > cap(v) {
|
||||||
xlen = decInferLen(containerLenS, d.h.MaxInitLen, {{ .Size }})
|
if canChange { {{/*
|
||||||
if xlen <= cap(v) {
|
// fast-path is for "basic" immutable types, so no need to copy them over
|
||||||
v = v[:xlen]
|
// s := make([]{{ .Elem }}, decInferLen(containerLenS, d.h.MaxInitLen))
|
||||||
} else {
|
// copy(s, v[:cap(v)])
|
||||||
v = make([]{{ .Elem }}, xlen)
|
// v = s */}}
|
||||||
}
|
var xlen int
|
||||||
changed = true
|
xlen, xtrunc = decInferLen(containerLenS, d.h.MaxInitLen, {{ .Size }})
|
||||||
} else if containerLenS != len(v) {
|
if xtrunc {
|
||||||
v = v[:containerLenS]
|
if xlen <= cap(v) {
|
||||||
changed = true
|
v = v[:xlen]
|
||||||
}
|
} else {
|
||||||
}
|
v = make([]{{ .Elem }}, xlen)
|
||||||
j := 0
|
}
|
||||||
for ; (hasLen && j < containerLenS) || !(hasLen || dd.CheckBreak()); j++ {
|
} else {
|
||||||
if j == 0 && len(v) == 0 && canChange {
|
v = make([]{{ .Elem }}, xlen)
|
||||||
if hasLen {
|
}
|
||||||
xlen = decInferLen(containerLenS, d.h.MaxInitLen, {{ .Size }})
|
|
||||||
} else {
|
|
||||||
xlen = 8
|
|
||||||
}
|
|
||||||
v = make([]{{ .Elem }}, xlen)
|
|
||||||
changed = true
|
|
||||||
}
|
|
||||||
// if indefinite, etc, then expand the slice if necessary
|
|
||||||
var decodeIntoBlank bool
|
|
||||||
if j >= len(v) {
|
|
||||||
if canChange {
|
|
||||||
v = append(v, {{ zerocmd .Elem }})
|
|
||||||
changed = true
|
changed = true
|
||||||
} else {
|
} else {
|
||||||
d.arrayCannotExpand(len(v), j+1)
|
d.arrayCannotExpand(len(v), containerLenS)
|
||||||
decodeIntoBlank = true
|
|
||||||
}
|
}
|
||||||
}
|
x2read = len(v)
|
||||||
slh.ElemContainerState(j)
|
} else if containerLenS != len(v) {
|
||||||
if decodeIntoBlank {
|
if canChange {
|
||||||
d.swallow()
|
v = v[:containerLenS]
|
||||||
} else if dd.TryDecodeAsNil() {
|
changed = true
|
||||||
v[j] = {{ zerocmd .Elem }}
|
}
|
||||||
} else {
|
} {{/* // 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 eq .Elem "interface{}" }}d.decode(&v[j]){{ else }}v[j] = {{ decmd .Elem }}{{ end }}
|
||||||
}
|
}
|
||||||
}
|
if xtrunc { {{/* // means canChange=true, changed=true already. */}}
|
||||||
if canChange {
|
for ; j < containerLenS; j++ {
|
||||||
if j < len(v) {
|
v = append(v, {{ zerocmd .Elem }})
|
||||||
v = v[:j]
|
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)
|
||||||
changed = true
|
changed = true
|
||||||
} else if j == 0 && v == nil {
|
}
|
||||||
v = make([]{{ .Elem }}, 0)
|
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]
|
||||||
changed = true
|
changed = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
slh.End()
|
slh.End()
|
||||||
return v, changed
|
return v, changed
|
||||||
}
|
}
|
||||||
|
|
||||||
{{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
|
Maps can change if they are
|
||||||
- addressable (from a ptr)
|
- addressable (from a ptr)
|
||||||
- settable (e.g. contained in an interface{})
|
- settable (e.g. contained in an interface{})
|
||||||
*/}}
|
*/}}
|
||||||
func (d *Decoder) {{ .MethodNamePfx "fastpathDec" false }}R(f *codecFnInfo, rv reflect.Value) {
|
func (f *decFnInfo) {{ .MethodNamePfx "fastpathDec" false }}R(rv reflect.Value) {
|
||||||
if rv.Kind() == reflect.Ptr {
|
if rv.CanAddr() {
|
||||||
vp := rv2i(rv).(*map[{{ .MapKey }}]{{ .Elem }})
|
vp := rv.Addr().Interface().(*map[{{ .MapKey }}]{{ .Elem }})
|
||||||
v, changed := fastpathTV.{{ .MethodNamePfx "Dec" false }}V(*vp, true, d);
|
v, changed := fastpathTV.{{ .MethodNamePfx "Dec" false }}V(*vp, fastpathCheckNilFalse, true, f.d)
|
||||||
if changed { *vp = v }
|
if changed {
|
||||||
|
*vp = v
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
fastpathTV.{{ .MethodNamePfx "Dec" false }}V(rv2i(rv).(map[{{ .MapKey }}]{{ .Elem }}), false, d)
|
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 }}, d *Decoder) {
|
func (f fastpathT) {{ .MethodNamePfx "Dec" false }}X(vp *map[{{ .MapKey }}]{{ .Elem }}, checkNil bool, d *Decoder) {
|
||||||
v, changed := f.{{ .MethodNamePfx "Dec" false }}V(*vp, true, d)
|
v, changed := f.{{ .MethodNamePfx "Dec" false }}V(*vp, checkNil, true, d)
|
||||||
if changed { *vp = v }
|
if changed {
|
||||||
|
*vp = v
|
||||||
|
}
|
||||||
}
|
}
|
||||||
func (_ fastpathT) {{ .MethodNamePfx "Dec" false }}V(v map[{{ .MapKey }}]{{ .Elem }}, canChange bool,
|
func (_ fastpathT) {{ .MethodNamePfx "Dec" false }}V(v map[{{ .MapKey }}]{{ .Elem }}, checkNil bool, canChange bool,
|
||||||
d *Decoder) (_ map[{{ .MapKey }}]{{ .Elem }}, changed bool) {
|
d *Decoder) (_ map[{{ .MapKey }}]{{ .Elem }}, changed bool) {
|
||||||
dd, esep := d.d, d.hh.hasElemSeparators(){{/*
|
dd := d.d
|
||||||
// if dd.isContainerType(valueTypeNil) {dd.TryDecodeAsNil()
|
cr := d.cr
|
||||||
*/}}
|
{{/* // if dd.isContainerType(valueTypeNil) {dd.TryDecodeAsNil() */}}
|
||||||
|
if checkNil && dd.TryDecodeAsNil() {
|
||||||
|
if v != nil {
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
return nil, changed
|
||||||
|
}
|
||||||
|
|
||||||
containerLen := dd.ReadMapStart()
|
containerLen := dd.ReadMapStart()
|
||||||
if canChange && v == nil {
|
if canChange && v == nil {
|
||||||
xlen := decInferLen(containerLen, d.h.MaxInitLen, {{ .Size }})
|
xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, {{ .Size }})
|
||||||
v = make(map[{{ .MapKey }}]{{ .Elem }}, xlen)
|
v = make(map[{{ .MapKey }}]{{ .Elem }}, xlen)
|
||||||
changed = true
|
changed = true
|
||||||
}
|
}
|
||||||
if containerLen == 0 {
|
{{ if eq .Elem "interface{}" }}mapGet := !d.h.MapValueReset && !d.h.InterfaceReset{{end}}
|
||||||
dd.ReadMapEnd()
|
var mk {{ .MapKey }}
|
||||||
return v, changed
|
|
||||||
}
|
|
||||||
{{ if eq .Elem "interface{}" }}mapGet := v != nil && !d.h.MapValueReset && !d.h.InterfaceReset
|
|
||||||
{{end}}var mk {{ .MapKey }}
|
|
||||||
var mv {{ .Elem }}
|
var mv {{ .Elem }}
|
||||||
hasLen := containerLen > 0
|
if containerLen > 0 {
|
||||||
for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
|
for j := 0; j < containerLen; j++ {
|
||||||
if esep { dd.ReadMapElemKey() }
|
if cr != nil { cr.sendContainerState(containerMapKey) }
|
||||||
{{ if eq .MapKey "interface{}" }}mk = nil
|
{{ if eq .MapKey "interface{}" }}mk = nil
|
||||||
d.decode(&mk)
|
d.decode(&mk)
|
||||||
if bv, bok := mk.([]byte); bok {
|
if bv, bok := mk.([]byte); bok {
|
||||||
mk = d.string(bv) {{/* // maps cannot have []byte as key. switch to string. */}}
|
mk = d.string(bv) {{/* // maps cannot have []byte as key. switch to string. */}}
|
||||||
}{{ else }}mk = {{ decmd .MapKey }}{{ end }}
|
}{{ else }}mk = {{ decmd .MapKey }}{{ end }}
|
||||||
if esep { dd.ReadMapElemValue() }
|
if cr != nil { cr.sendContainerState(containerMapValue) }
|
||||||
if dd.TryDecodeAsNil() {
|
{{ if eq .Elem "interface{}" }}if mapGet { mv = v[mk] } else { mv = nil }
|
||||||
if v == nil {} else if d.h.DeleteOnNilMapValue { delete(v, mk) } else { v[mk] = {{ zerocmd .Elem }} }
|
d.decode(&mv){{ else }}mv = {{ decmd .Elem }}{{ end }}
|
||||||
continue
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
{{ 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 }
|
|
||||||
}
|
}
|
||||||
dd.ReadMapEnd()
|
if cr != nil { cr.sendContainerState(containerMapEnd) }
|
||||||
return v, changed
|
return v, changed
|
||||||
}
|
}
|
||||||
|
|
||||||
{{end}}{{end}}{{end}}
|
{{end}}{{end}}{{end}}
|
||||||
|
|
|
@ -1,14 +1,9 @@
|
||||||
// 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.
|
|
||||||
|
|
||||||
// +build notfastpath
|
// +build notfastpath
|
||||||
|
|
||||||
package codec
|
package codec
|
||||||
|
|
||||||
import "reflect"
|
import "reflect"
|
||||||
|
|
||||||
const fastpathEnabled = false
|
|
||||||
|
|
||||||
// The generated fast-path code is very large, and adds a few seconds to the build time.
|
// 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
|
// This causes test execution, execution of small tools which use codec, etc
|
||||||
// to take a long time.
|
// to take a long time.
|
||||||
|
@ -21,27 +16,17 @@ func fastpathDecodeTypeSwitch(iv interface{}, d *Decoder) bool { return fal
|
||||||
func fastpathEncodeTypeSwitch(iv interface{}, e *Encoder) bool { return false }
|
func fastpathEncodeTypeSwitch(iv interface{}, e *Encoder) bool { return false }
|
||||||
func fastpathEncodeTypeSwitchSlice(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 fastpathEncodeTypeSwitchMap(iv interface{}, e *Encoder) bool { return false }
|
||||||
func fastpathDecodeSetZeroTypeSwitch(iv interface{}) bool { return false }
|
|
||||||
|
|
||||||
type fastpathT struct{}
|
type fastpathT struct{}
|
||||||
type fastpathE struct {
|
type fastpathE struct {
|
||||||
rtid uintptr
|
rtid uintptr
|
||||||
rt reflect.Type
|
rt reflect.Type
|
||||||
encfn func(*Encoder, *codecFnInfo, reflect.Value)
|
encfn func(*encFnInfo, reflect.Value)
|
||||||
decfn func(*Decoder, *codecFnInfo, reflect.Value)
|
decfn func(*decFnInfo, reflect.Value)
|
||||||
}
|
}
|
||||||
type fastpathA [0]fastpathE
|
type fastpathA [0]fastpathE
|
||||||
|
|
||||||
func (x fastpathA) index(rtid uintptr) int { return -1 }
|
func (x fastpathA) index(rtid uintptr) int { return -1 }
|
||||||
|
|
||||||
func (_ fastpathT) DecSliceUint8V(v []uint8, canChange bool, d *Decoder) (_ []uint8, changed bool) {
|
|
||||||
fn := d.cfer().get(uint8SliceTyp, true, true)
|
|
||||||
d.kSlice(&fn.i, reflect.ValueOf(&v).Elem())
|
|
||||||
return v, true
|
|
||||||
}
|
|
||||||
|
|
||||||
var fastpathAV fastpathA
|
var fastpathAV fastpathA
|
||||||
var fastpathTV fastpathT
|
var fastpathTV fastpathT
|
||||||
|
|
||||||
// ----
|
|
||||||
type TestMammoth2Wrapper struct{} // to allow testMammoth work in notfastpath mode
|
|
||||||
|
|
|
@ -9,68 +9,94 @@ if {{var "l"}} == 0 {
|
||||||
} else if len({{var "v"}}) != 0 {
|
} else if len({{var "v"}}) != 0 {
|
||||||
{{var "v"}} = {{var "v"}}[:0]
|
{{var "v"}} = {{var "v"}}[:0]
|
||||||
{{var "c"}} = true
|
{{var "c"}} = true
|
||||||
} {{else if isChan }}if {{var "v"}} == nil {
|
} {{end}} {{if isChan }}if {{var "v"}} == nil {
|
||||||
{{var "v"}} = make({{ .CTyp }}, 0)
|
{{var "v"}} = make({{ .CTyp }}, 0)
|
||||||
{{var "c"}} = true
|
{{var "c"}} = true
|
||||||
} {{end}}
|
} {{end}}
|
||||||
} else {
|
} else if {{var "l"}} > 0 {
|
||||||
{{var "hl"}} := {{var "l"}} > 0
|
{{if isChan }}if {{var "v"}} == nil {
|
||||||
var {{var "rl"}} int
|
{{var "rl"}}, _ = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})
|
||||||
_ = {{var "rl"}}
|
{{var "v"}} = make({{ .CTyp }}, {{var "rl"}})
|
||||||
{{if isSlice }} if {{var "hl"}} {
|
{{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"}})
|
||||||
if {{var "l"}} > cap({{var "v"}}) {
|
if {{var "l"}} > cap({{var "v"}}) {
|
||||||
{{var "rl"}} = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})
|
{{if isArray }}z.DecArrayCannotExpand(len({{var "v"}}), {{var "l"}})
|
||||||
if {{var "rl"}} <= cap({{var "v"}}) {
|
{{ else }}{{if not .Immutable }}
|
||||||
{{var "v"}} = {{var "v"}}[:{{var "rl"}}]
|
{{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"}})
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
{{var "v"}} = make([]{{ .Typ }}, {{var "rl"}})
|
{{var "v"}} = make([]{{ .Typ }}, {{var "rl"}})
|
||||||
}
|
}
|
||||||
{{var "c"}} = true
|
{{var "c"}} = true
|
||||||
} else if {{var "l"}} != len({{var "v"}}) {
|
{{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"}}) {
|
||||||
{{var "v"}} = {{var "v"}}[:{{var "l"}}]
|
{{var "v"}} = {{var "v"}}[:{{var "l"}}]
|
||||||
{{var "c"}} = true
|
{{var "c"}} = true
|
||||||
}
|
} {{end}} {{/* end isSlice:47 */}}
|
||||||
} {{end}}
|
{{var "j"}} := 0
|
||||||
var {{var "j"}} int
|
for ; {{var "j"}} < {{var "rr"}} ; {{var "j"}}++ {
|
||||||
// var {{var "dn"}} bool
|
|
||||||
for ; ({{var "hl"}} && {{var "j"}} < {{var "l"}}) || !({{var "hl"}} || r.CheckBreak()); {{var "j"}}++ {
|
|
||||||
{{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}}
|
|
||||||
{{var "h"}}.ElemContainerState({{var "j"}})
|
{{var "h"}}.ElemContainerState({{var "j"}})
|
||||||
{{/* {{var "dn"}} = r.TryDecodeAsNil() */}}{{/* commented out, as decLineVar handles this already each time */}}
|
{{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }}
|
||||||
{{if isChan}}{{ $x := printf "%[1]vvcx%[2]v" .TempVar .Rand }}var {{$x}} {{ .Typ }}
|
}
|
||||||
{{ decLineVar $x }}
|
{{if isArray }}for ; {{var "j"}} < {{var "l"}} ; {{var "j"}}++ {
|
||||||
{{var "v"}} <- {{ $x }}
|
{{var "h"}}.ElemContainerState({{var "j"}})
|
||||||
// println(">>>> sending ", {{ $x }}, " into ", {{var "v"}}) // TODO: remove this
|
z.DecSwallow()
|
||||||
{{else}}{{/* // if indefinite, etc, then expand the slice if necessary */}}
|
}
|
||||||
var {{var "db"}} bool
|
{{ else }}if {{var "rt"}} {
|
||||||
if {{var "j"}} >= len({{var "v"}}) {
|
for ; {{var "j"}} < {{var "l"}} ; {{var "j"}}++ {
|
||||||
{{if isSlice }} {{var "v"}} = append({{var "v"}}, {{ zero }})
|
{{var "v"}} = append({{var "v"}}, {{ zero}})
|
||||||
{{var "c"}} = true
|
{{var "h"}}.ElemContainerState({{var "j"}})
|
||||||
{{else}} z.DecArrayCannotExpand(len(v), {{var "j"}}+1); {{var "db"}} = true
|
|
||||||
{{end}}
|
|
||||||
}
|
|
||||||
if {{var "db"}} {
|
|
||||||
z.DecSwallow()
|
|
||||||
} else {
|
|
||||||
{{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }}
|
{{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }}
|
||||||
}
|
}
|
||||||
{{end}}
|
} {{end}} {{/* end isArray:56 */}}
|
||||||
|
{{end}} {{/* end isChan:16 */}}
|
||||||
|
} else { {{/* len < 0 */}}
|
||||||
|
{{var "j"}} := 0
|
||||||
|
for ; !r.CheckBreak(); {{var "j"}}++ {
|
||||||
|
{{if isChan }}
|
||||||
|
{{var "h"}}.ElemContainerState({{var "j"}})
|
||||||
|
var {{var "t"}} {{ .Typ }}
|
||||||
|
{{ $x := printf "%st%s" .TempVar .Rand }}{{ decLineVar $x }}
|
||||||
|
{{var "v"}} <- {{var "t"}}
|
||||||
|
{{ else }}
|
||||||
|
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}}
|
||||||
|
}
|
||||||
|
{{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 {
|
||||||
|
z.DecSwallow()
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
}
|
}
|
||||||
{{if isSlice}} if {{var "j"}} < len({{var "v"}}) {
|
{{if isSlice }}if {{var "j"}} < len({{var "v"}}) {
|
||||||
{{var "v"}} = {{var "v"}}[:{{var "j"}}]
|
{{var "v"}} = {{var "v"}}[:{{var "j"}}]
|
||||||
{{var "c"}} = true
|
{{var "c"}} = true
|
||||||
} else if {{var "j"}} == 0 && {{var "v"}} == nil {
|
} else if {{var "j"}} == 0 && {{var "v"}} == nil {
|
||||||
{{var "v"}} = make([]{{ .Typ }}, 0)
|
{{var "v"}} = []{{ .Typ }}{}
|
||||||
{{var "c"}} = true
|
{{var "c"}} = true
|
||||||
} {{end}}
|
}{{end}}
|
||||||
}
|
}
|
||||||
{{var "h"}}.End()
|
{{var "h"}}.End()
|
||||||
{{if not isArray }}if {{var "c"}} {
|
{{if not isArray }}if {{var "c"}} {
|
||||||
|
|
|
@ -2,22 +2,21 @@
|
||||||
{{var "l"}} := r.ReadMapStart()
|
{{var "l"}} := r.ReadMapStart()
|
||||||
{{var "bh"}} := z.DecBasicHandle()
|
{{var "bh"}} := z.DecBasicHandle()
|
||||||
if {{var "v"}} == nil {
|
if {{var "v"}} == nil {
|
||||||
{{var "rl"}} := z.DecInferLen({{var "l"}}, {{var "bh"}}.MaxInitLen, {{ .Size }})
|
{{var "rl"}}, _ := z.DecInferLen({{var "l"}}, {{var "bh"}}.MaxInitLen, {{ .Size }})
|
||||||
{{var "v"}} = make(map[{{ .KTyp }}]{{ .Typ }}, {{var "rl"}})
|
{{var "v"}} = make(map[{{ .KTyp }}]{{ .Typ }}, {{var "rl"}})
|
||||||
*{{ .Varname }} = {{var "v"}}
|
*{{ .Varname }} = {{var "v"}}
|
||||||
}
|
}
|
||||||
var {{var "mk"}} {{ .KTyp }}
|
var {{var "mk"}} {{ .KTyp }}
|
||||||
var {{var "mv"}} {{ .Typ }}
|
var {{var "mv"}} {{ .Typ }}
|
||||||
var {{var "mg"}}, {{var "mdn"}} {{if decElemKindPtr}}, {{var "ms"}}, {{var "mok"}}{{end}} bool
|
var {{var "mg"}} {{if decElemKindPtr}}, {{var "ms"}}, {{var "mok"}}{{end}} bool
|
||||||
if {{var "bh"}}.MapValueReset {
|
if {{var "bh"}}.MapValueReset {
|
||||||
{{if decElemKindPtr}}{{var "mg"}} = true
|
{{if decElemKindPtr}}{{var "mg"}} = true
|
||||||
{{else if decElemKindIntf}}if !{{var "bh"}}.InterfaceReset { {{var "mg"}} = true }
|
{{else if decElemKindIntf}}if !{{var "bh"}}.InterfaceReset { {{var "mg"}} = true }
|
||||||
{{else if not decElemKindImmutable}}{{var "mg"}} = true
|
{{else if not decElemKindImmutable}}{{var "mg"}} = true
|
||||||
{{end}} }
|
{{end}} }
|
||||||
if {{var "l"}} != 0 {
|
if {{var "l"}} > 0 {
|
||||||
{{var "hl"}} := {{var "l"}} > 0
|
for {{var "j"}} := 0; {{var "j"}} < {{var "l"}}; {{var "j"}}++ {
|
||||||
for {{var "j"}} := 0; ({{var "hl"}} && {{var "j"}} < {{var "l"}}) || !({{var "hl"}} || r.CheckBreak()); {{var "j"}}++ {
|
z.DecSendContainerState(codecSelfer_containerMapKey{{ .Sfx }})
|
||||||
r.ReadMapElemKey() {{/* z.DecSendContainerState(codecSelfer_containerMapKey{{ .Sfx }}) */}}
|
|
||||||
{{ $x := printf "%vmk%v" .TempVar .Rand }}{{ decLineVarK $x }}
|
{{ $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"}} {
|
{{ 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"}})
|
{{var "mk"}} = string({{var "bv"}})
|
||||||
|
@ -29,14 +28,31 @@ if {{var "l"}} != 0 {
|
||||||
{{var "ms"}} = false
|
{{var "ms"}} = false
|
||||||
} {{else}}{{var "mv"}} = {{var "v"}}[{{var "mk"}}] {{end}}
|
} {{else}}{{var "mv"}} = {{var "v"}}[{{var "mk"}}] {{end}}
|
||||||
} {{if not decElemKindImmutable}}else { {{var "mv"}} = {{decElemZero}} }{{end}}
|
} {{if not decElemKindImmutable}}else { {{var "mv"}} = {{decElemZero}} }{{end}}
|
||||||
r.ReadMapElemValue() {{/* z.DecSendContainerState(codecSelfer_containerMapValue{{ .Sfx }}) */}}
|
z.DecSendContainerState(codecSelfer_containerMapValue{{ .Sfx }})
|
||||||
{{var "mdn"}} = false
|
{{ $x := printf "%vmv%v" .TempVar .Rand }}{{ decLineVar $x }}
|
||||||
{{ $x := printf "%vmv%v" .TempVar .Rand }}{{ $y := printf "%vmdn%v" .TempVar .Rand }}{{ decLineVar $x $y }}
|
if {{if decElemKindPtr}} {{var "ms"}} && {{end}} {{var "v"}} != nil {
|
||||||
if {{var "mdn"}} {
|
{{var "v"}}[{{var "mk"}}] = {{var "mv"}}
|
||||||
if {{ var "bh" }}.DeleteOnNilMapValue { delete({{var "v"}}, {{var "mk"}}) } else { {{var "v"}}[{{var "mk"}}] = {{decElemZero}} }
|
}
|
||||||
} else if {{if decElemKindPtr}} {{var "ms"}} && {{end}} {{var "v"}} != nil {
|
}
|
||||||
|
} 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"}}
|
{{var "v"}}[{{var "mk"}}] = {{var "mv"}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // else len==0: TODO: Should we clear map entries?
|
} // else len==0: TODO: Should we clear map entries?
|
||||||
r.ReadMapEnd() {{/* z.DecSendContainerState(codecSelfer_containerMapEnd{{ .Sfx }}) */}}
|
z.DecSendContainerState(codecSelfer_containerMapEnd{{ .Sfx }})
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
{{.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,24 +1,23 @@
|
||||||
/* // +build ignore */
|
// //+build ignore
|
||||||
|
|
||||||
// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
|
// 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.
|
// Use of this source code is governed by a MIT license found in the LICENSE file.
|
||||||
|
|
||||||
// Code generated from gen-helper.go.tmpl - DO NOT EDIT.
|
// ************************************************************
|
||||||
|
// DO NOT EDIT.
|
||||||
|
// THIS FILE IS AUTO-GENERATED from gen-helper.go.tmpl
|
||||||
|
// ************************************************************
|
||||||
|
|
||||||
package codec
|
package codec
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding"
|
"encoding"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GenVersion is the current version of codecgen.
|
|
||||||
const GenVersion = 8
|
|
||||||
|
|
||||||
// This file is used to generate helper code for codecgen.
|
// 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
|
// The values here i.e. genHelper(En|De)coder are not to be used directly by
|
||||||
// library users. They WILL change continuously and without notice.
|
// library users. They WILL change continously and without notice.
|
||||||
//
|
//
|
||||||
// To help enforce this, we create an unexported type with exported members.
|
// 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).
|
// The only way to get the type is via the one exported type that we control (somewhat).
|
||||||
|
@ -27,85 +26,25 @@ const GenVersion = 8
|
||||||
// to perform encoding or decoding of primitives or known slice or map types.
|
// 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.
|
// 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.
|
// Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE.
|
||||||
func GenHelperEncoder(e *Encoder) (ge genHelperEncoder, ee genHelperEncDriver) {
|
func GenHelperEncoder(e *Encoder) (genHelperEncoder, encDriver) {
|
||||||
ge = genHelperEncoder{e: e}
|
return genHelperEncoder{e: e}, e.e
|
||||||
ee = genHelperEncDriver{encDriver: e.e}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenHelperDecoder is exported so that it can be used externally by codecgen.
|
// 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.
|
// Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE.
|
||||||
func GenHelperDecoder(d *Decoder) (gd genHelperDecoder, dd genHelperDecDriver) {
|
func GenHelperDecoder(d *Decoder) (genHelperDecoder, decDriver) {
|
||||||
gd = genHelperDecoder{d: d}
|
return genHelperDecoder{d: d}, d.d
|
||||||
dd = genHelperDecDriver{decDriver: d.d}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
type genHelperEncDriver struct {
|
|
||||||
encDriver
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x genHelperEncDriver) EncodeBuiltin(rt uintptr, v interface{}) {}
|
|
||||||
func (x genHelperEncDriver) EncStructFieldKey(keyType valueType, s string) {
|
|
||||||
var m must
|
|
||||||
if keyType == valueTypeString {
|
|
||||||
x.encDriver.EncodeString(cUTF8, s)
|
|
||||||
} else if keyType == valueTypeInt {
|
|
||||||
x.encDriver.EncodeInt(m.Int(strconv.ParseInt(s, 10, 64)))
|
|
||||||
} else if keyType == valueTypeUint {
|
|
||||||
x.encDriver.EncodeUint(m.Uint(strconv.ParseUint(s, 10, 64)))
|
|
||||||
} else if keyType == valueTypeFloat {
|
|
||||||
x.encDriver.EncodeFloat64(m.Float(strconv.ParseFloat(s, 64)))
|
|
||||||
}
|
|
||||||
// encStructFieldKey(x.encDriver, keyType, s)
|
|
||||||
}
|
|
||||||
func (x genHelperEncDriver) EncodeSymbol(s string) {
|
|
||||||
x.encDriver.EncodeString(cUTF8, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
type genHelperDecDriver struct {
|
|
||||||
decDriver
|
|
||||||
C checkOverflow
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x genHelperDecDriver) DecodeBuiltin(rt uintptr, v interface{}) {}
|
|
||||||
func (x genHelperDecDriver) DecStructFieldKey(keyType valueType, buf *[decScratchByteArrayLen]byte) []byte {
|
|
||||||
return decStructFieldKey(x.decDriver, keyType, buf)
|
|
||||||
}
|
|
||||||
func (x genHelperDecDriver) DecodeInt(bitsize uint8) (i int64) {
|
|
||||||
return x.C.IntV(x.decDriver.DecodeInt64(), bitsize)
|
|
||||||
}
|
|
||||||
func (x genHelperDecDriver) DecodeUint(bitsize uint8) (ui uint64) {
|
|
||||||
return x.C.UintV(x.decDriver.DecodeUint64(), bitsize)
|
|
||||||
}
|
|
||||||
func (x genHelperDecDriver) DecodeFloat(chkOverflow32 bool) (f float64) {
|
|
||||||
f = x.DecodeFloat64()
|
|
||||||
if chkOverflow32 && chkOvf.Float32(f) {
|
|
||||||
panicv.errorf("float32 overflow: %v", f)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
func (x genHelperDecDriver) DecodeFloat32As64() (f float64) {
|
|
||||||
f = x.DecodeFloat64()
|
|
||||||
if chkOvf.Float32(f) {
|
|
||||||
panicv.errorf("float32 overflow: %v", f)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
type genHelperEncoder struct {
|
type genHelperEncoder struct {
|
||||||
M must
|
|
||||||
e *Encoder
|
e *Encoder
|
||||||
F fastpathT
|
F fastpathT
|
||||||
}
|
}
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
type genHelperDecoder struct {
|
type genHelperDecoder struct {
|
||||||
C checkOverflow
|
|
||||||
d *Decoder
|
d *Decoder
|
||||||
F fastpathT
|
F fastpathT
|
||||||
}
|
}
|
||||||
|
@ -120,91 +59,69 @@ func (f genHelperEncoder) EncBinary() bool {
|
||||||
return f.e.be // f.e.hh.isBinaryEncoding()
|
return f.e.be // f.e.hh.isBinaryEncoding()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
func (f genHelperEncoder) EncFallback(iv interface{}) {
|
func (f genHelperEncoder) EncFallback(iv interface{}) {
|
||||||
// println(">>>>>>>>> EncFallback")
|
// println(">>>>>>>>> EncFallback")
|
||||||
// f.e.encodeI(iv, false, false)
|
f.e.encodeI(iv, false, false)
|
||||||
f.e.encodeValue(reflect.ValueOf(iv), nil, false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
func (f genHelperEncoder) EncTextMarshal(iv encoding.TextMarshaler) {
|
func (f genHelperEncoder) EncTextMarshal(iv encoding.TextMarshaler) {
|
||||||
bs, fnerr := iv.MarshalText()
|
bs, fnerr := iv.MarshalText()
|
||||||
f.e.marshal(bs, fnerr, false, cUTF8)
|
f.e.marshal(bs, fnerr, false, c_UTF8)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
func (f genHelperEncoder) EncJSONMarshal(iv jsonMarshaler) {
|
func (f genHelperEncoder) EncJSONMarshal(iv jsonMarshaler) {
|
||||||
bs, fnerr := iv.MarshalJSON()
|
bs, fnerr := iv.MarshalJSON()
|
||||||
f.e.marshal(bs, fnerr, true, cUTF8)
|
f.e.marshal(bs, fnerr, true, c_UTF8)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
func (f genHelperEncoder) EncBinaryMarshal(iv encoding.BinaryMarshaler) {
|
func (f genHelperEncoder) EncBinaryMarshal(iv encoding.BinaryMarshaler) {
|
||||||
bs, fnerr := iv.MarshalBinary()
|
bs, fnerr := iv.MarshalBinary()
|
||||||
f.e.marshal(bs, fnerr, false, cRAW)
|
f.e.marshal(bs, fnerr, false, c_RAW)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
func (f genHelperEncoder) EncRaw(iv Raw) { f.e.rawBytes(iv) }
|
func (f genHelperEncoder) TimeRtidIfBinc() uintptr {
|
||||||
|
if _, ok := f.e.hh.(*BincHandle); ok {
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
return timeTypId
|
||||||
//
|
}
|
||||||
// Deprecated: builtin no longer supported - so we make this method a no-op,
|
return 0
|
||||||
// but leave in-place so that old generated files continue to work without regeneration.
|
|
||||||
func (f genHelperEncoder) TimeRtidIfBinc() (v uintptr) { return }
|
|
||||||
|
|
||||||
// func (f genHelperEncoder) TimeRtidIfBinc() uintptr {
|
|
||||||
// if _, ok := f.e.hh.(*BincHandle); ok {
|
|
||||||
// return timeTypId
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
|
||||||
func (f genHelperEncoder) I2Rtid(v interface{}) uintptr {
|
|
||||||
return i2rtid(v)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
func (f genHelperEncoder) Extension(rtid uintptr) (xfn *extTypeTagFn) {
|
func (f genHelperEncoder) IsJSONHandle() bool {
|
||||||
return f.e.h.getExt(rtid)
|
return f.e.js
|
||||||
}
|
}
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// 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, f.e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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*
|
|
||||||
//
|
|
||||||
// Deprecated: No longer used,
|
|
||||||
// but leave in-place so that old generated files continue to work without regeneration.
|
|
||||||
func (f genHelperEncoder) HasExtensions() bool {
|
func (f genHelperEncoder) HasExtensions() bool {
|
||||||
return len(f.e.h.extHandle) != 0
|
return len(f.e.h.extHandle) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
//
|
|
||||||
// Deprecated: No longer used,
|
|
||||||
// but leave in-place so that old generated files continue to work without regeneration.
|
|
||||||
func (f genHelperEncoder) EncExt(v interface{}) (r bool) {
|
func (f genHelperEncoder) EncExt(v interface{}) (r bool) {
|
||||||
if xfFn := f.e.h.getExt(i2rtid(v)); xfFn != nil {
|
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)
|
f.e.e.EncodeExt(v, xfFn.tag, xfFn.ext, f.e)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------- DECODER FOLLOWS -----------------
|
// ---------------- DECODER FOLLOWS -----------------
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
|
@ -218,27 +135,19 @@ func (f genHelperDecoder) DecBinary() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// 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*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
func (f genHelperDecoder) DecScratchBuffer() []byte {
|
func (f genHelperDecoder) DecScratchBuffer() []byte {
|
||||||
return f.d.b[:]
|
return f.d.b[:]
|
||||||
}
|
}
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
|
||||||
func (f genHelperDecoder) DecScratchArrayBuffer() *[decScratchByteArrayLen]byte {
|
|
||||||
return &f.d.b
|
|
||||||
}
|
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
func (f genHelperDecoder) DecFallback(iv interface{}, chkPtr bool) {
|
func (f genHelperDecoder) DecFallback(iv interface{}, chkPtr bool) {
|
||||||
// println(">>>>>>>>> DecFallback")
|
// println(">>>>>>>>> DecFallback")
|
||||||
rv := reflect.ValueOf(iv)
|
f.d.decodeI(iv, chkPtr, false, false, false)
|
||||||
if chkPtr {
|
|
||||||
rv = f.d.ensureDecodeable(rv)
|
|
||||||
}
|
|
||||||
f.d.decodeValue(rv, nil, false)
|
|
||||||
// f.d.decodeValueFallback(rv)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
|
@ -258,7 +167,7 @@ func (f genHelperDecoder) DecArrayCannotExpand(sliceLen, streamLen int) {
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
func (f genHelperDecoder) DecTextUnmarshal(tm encoding.TextUnmarshaler) {
|
func (f genHelperDecoder) DecTextUnmarshal(tm encoding.TextUnmarshaler) {
|
||||||
fnerr := tm.UnmarshalText(f.d.d.DecodeStringAsBytes())
|
fnerr := tm.UnmarshalText(f.d.d.DecodeBytes(f.d.b[:], true, true))
|
||||||
if fnerr != nil {
|
if fnerr != nil {
|
||||||
panic(fnerr)
|
panic(fnerr)
|
||||||
}
|
}
|
||||||
|
@ -266,7 +175,7 @@ func (f genHelperDecoder) DecTextUnmarshal(tm encoding.TextUnmarshaler) {
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
func (f genHelperDecoder) DecJSONUnmarshal(tm jsonUnmarshaler) {
|
func (f genHelperDecoder) DecJSONUnmarshal(tm jsonUnmarshaler) {
|
||||||
// bs := f.dd.DecodeStringAsBytes()
|
// 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.
|
// grab the bytes to be read, as UnmarshalJSON needs the full JSON so as to unmarshal it itself.
|
||||||
fnerr := tm.UnmarshalJSON(f.d.nextValueBytes())
|
fnerr := tm.UnmarshalJSON(f.d.nextValueBytes())
|
||||||
if fnerr != nil {
|
if fnerr != nil {
|
||||||
|
@ -276,28 +185,19 @@ func (f genHelperDecoder) DecJSONUnmarshal(tm jsonUnmarshaler) {
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
func (f genHelperDecoder) DecBinaryUnmarshal(bm encoding.BinaryUnmarshaler) {
|
func (f genHelperDecoder) DecBinaryUnmarshal(bm encoding.BinaryUnmarshaler) {
|
||||||
fnerr := bm.UnmarshalBinary(f.d.d.DecodeBytes(nil, true))
|
fnerr := bm.UnmarshalBinary(f.d.d.DecodeBytes(nil, false, true))
|
||||||
if fnerr != nil {
|
if fnerr != nil {
|
||||||
panic(fnerr)
|
panic(fnerr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
func (f genHelperDecoder) DecRaw() []byte { return f.d.rawBytes() }
|
func (f genHelperDecoder) TimeRtidIfBinc() uintptr {
|
||||||
|
if _, ok := f.d.hh.(*BincHandle); ok {
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
return timeTypId
|
||||||
//
|
}
|
||||||
// Deprecated: builtin no longer supported - so we make this method a no-op,
|
return 0
|
||||||
// but leave in-place so that old generated files continue to work without regeneration.
|
}
|
||||||
func (f genHelperDecoder) TimeRtidIfBinc() (v uintptr) { return }
|
|
||||||
|
|
||||||
// func (f genHelperDecoder) TimeRtidIfBinc() uintptr {
|
|
||||||
// // Note: builtin is no longer supported - so make this a no-op
|
|
||||||
// if _, ok := f.d.hh.(*BincHandle); ok {
|
|
||||||
// return timeTypId
|
|
||||||
// }
|
|
||||||
// return 0
|
|
||||||
// }
|
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
func (f genHelperDecoder) IsJSONHandle() bool {
|
func (f genHelperDecoder) IsJSONHandle() bool {
|
||||||
|
@ -305,34 +205,15 @@ func (f genHelperDecoder) IsJSONHandle() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
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(rtid uintptr) (xfn *extTypeTagFn) {
|
|
||||||
return f.d.h.getExt(rtid)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
|
||||||
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*
|
|
||||||
//
|
|
||||||
// Deprecated: No longer used,
|
|
||||||
// but leave in-place so that old generated files continue to work without regeneration.
|
|
||||||
func (f genHelperDecoder) HasExtensions() bool {
|
func (f genHelperDecoder) HasExtensions() bool {
|
||||||
return len(f.d.h.extHandle) != 0
|
return len(f.d.h.extHandle) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
//
|
|
||||||
// Deprecated: No longer used,
|
|
||||||
// but leave in-place so that old generated files continue to work without regeneration.
|
|
||||||
func (f genHelperDecoder) DecExt(v interface{}) (r bool) {
|
func (f genHelperDecoder) DecExt(v interface{}) (r bool) {
|
||||||
if xfFn := f.d.h.getExt(i2rtid(v)); xfFn != nil {
|
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)
|
f.d.d.DecodeExt(v, xfFn.tag, xfFn.ext)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -340,12 +221,13 @@ func (f genHelperDecoder) DecExt(v interface{}) (r bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
func (f genHelperDecoder) DecInferLen(clen, maxlen, unit int) (rvlen int) {
|
func (f genHelperDecoder) DecInferLen(clen, maxlen, unit int) (rvlen int, truncated bool) {
|
||||||
return decInferLen(clen, maxlen, unit)
|
return decInferLen(clen, maxlen, unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
//
|
func (f genHelperDecoder) DecSendContainerState(c containerState) {
|
||||||
// Deprecated: no longer used,
|
if f.d.cr != nil {
|
||||||
// but leave in-place so that old generated files continue to work without regeneration.
|
f.d.cr.sendContainerState(c)
|
||||||
func (f genHelperDecoder) StringView(v []byte) string { return stringView(v) }
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,111 +1,50 @@
|
||||||
/* // +build ignore */
|
// //+build ignore
|
||||||
|
|
||||||
// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
|
// 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.
|
// Use of this source code is governed by a MIT license found in the LICENSE file.
|
||||||
|
|
||||||
// Code generated from gen-helper.go.tmpl - DO NOT EDIT.
|
// ************************************************************
|
||||||
|
// DO NOT EDIT.
|
||||||
|
// THIS FILE IS AUTO-GENERATED from gen-helper.go.tmpl
|
||||||
|
// ************************************************************
|
||||||
|
|
||||||
package codec
|
package codec
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding"
|
"encoding"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GenVersion is the current version of codecgen.
|
|
||||||
const GenVersion = {{ .Version }}
|
|
||||||
|
|
||||||
// This file is used to generate helper code for codecgen.
|
// 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
|
// The values here i.e. genHelper(En|De)coder are not to be used directly by
|
||||||
// library users. They WILL change continuously and without notice.
|
// library users. They WILL change continously and without notice.
|
||||||
//
|
//
|
||||||
// To help enforce this, we create an unexported type with exported members.
|
// 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).
|
// 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
|
// 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.
|
// 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.
|
// 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.
|
// Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE.
|
||||||
func GenHelperEncoder(e *Encoder) (ge genHelperEncoder, ee genHelperEncDriver) {
|
func GenHelperEncoder(e *Encoder) (genHelperEncoder, encDriver) {
|
||||||
ge = genHelperEncoder{e: e}
|
return genHelperEncoder{e:e}, e.e
|
||||||
ee = genHelperEncDriver{encDriver: e.e}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenHelperDecoder is exported so that it can be used externally by codecgen.
|
// 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.
|
// Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE.
|
||||||
func GenHelperDecoder(d *Decoder) (gd genHelperDecoder, dd genHelperDecDriver) {
|
func GenHelperDecoder(d *Decoder) (genHelperDecoder, decDriver) {
|
||||||
gd = genHelperDecoder{d: d}
|
return genHelperDecoder{d:d}, d.d
|
||||||
dd = genHelperDecDriver{decDriver: d.d}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
type genHelperEncDriver struct {
|
|
||||||
encDriver
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x genHelperEncDriver) EncodeBuiltin(rt uintptr, v interface{}) {}
|
|
||||||
func (x genHelperEncDriver) EncStructFieldKey(keyType valueType, s string) {
|
|
||||||
var m must
|
|
||||||
if keyType == valueTypeString {
|
|
||||||
x.encDriver.EncodeString(cUTF8, s)
|
|
||||||
} else if keyType == valueTypeInt {
|
|
||||||
x.encDriver.EncodeInt(m.Int(strconv.ParseInt(s, 10, 64)))
|
|
||||||
} else if keyType == valueTypeUint {
|
|
||||||
x.encDriver.EncodeUint(m.Uint(strconv.ParseUint(s, 10, 64)))
|
|
||||||
} else if keyType == valueTypeFloat {
|
|
||||||
x.encDriver.EncodeFloat64(m.Float(strconv.ParseFloat(s, 64)))
|
|
||||||
}
|
|
||||||
// encStructFieldKey(x.encDriver, keyType, s)
|
|
||||||
}
|
|
||||||
func (x genHelperEncDriver) EncodeSymbol(s string) {
|
|
||||||
x.encDriver.EncodeString(cUTF8, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
type genHelperDecDriver struct {
|
|
||||||
decDriver
|
|
||||||
C checkOverflow
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x genHelperDecDriver) DecodeBuiltin(rt uintptr, v interface{}) {}
|
|
||||||
func (x genHelperDecDriver) DecStructFieldKey(keyType valueType, buf *[decScratchByteArrayLen]byte) []byte {
|
|
||||||
return decStructFieldKey(x.decDriver, keyType, buf)
|
|
||||||
}
|
|
||||||
func (x genHelperDecDriver) DecodeInt(bitsize uint8) (i int64) {
|
|
||||||
return x.C.IntV(x.decDriver.DecodeInt64(), bitsize)
|
|
||||||
}
|
|
||||||
func (x genHelperDecDriver) DecodeUint(bitsize uint8) (ui uint64) {
|
|
||||||
return x.C.UintV(x.decDriver.DecodeUint64(), bitsize)
|
|
||||||
}
|
|
||||||
func (x genHelperDecDriver) DecodeFloat(chkOverflow32 bool) (f float64) {
|
|
||||||
f = x.DecodeFloat64()
|
|
||||||
if chkOverflow32 && chkOvf.Float32(f) {
|
|
||||||
panicv.errorf("float32 overflow: %v", f)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
func (x genHelperDecDriver) DecodeFloat32As64() (f float64) {
|
|
||||||
f = x.DecodeFloat64()
|
|
||||||
if chkOvf.Float32(f) {
|
|
||||||
panicv.errorf("float32 overflow: %v", f)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
type genHelperEncoder struct {
|
type genHelperEncoder struct {
|
||||||
M must
|
|
||||||
e *Encoder
|
e *Encoder
|
||||||
F fastpathT
|
F fastpathT
|
||||||
}
|
}
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
type genHelperDecoder struct {
|
type genHelperDecoder struct {
|
||||||
C checkOverflow
|
|
||||||
d *Decoder
|
d *Decoder
|
||||||
F fastpathT
|
F fastpathT
|
||||||
}
|
}
|
||||||
|
@ -114,82 +53,65 @@ type genHelperDecoder struct {
|
||||||
func (f genHelperEncoder) EncBasicHandle() *BasicHandle {
|
func (f genHelperEncoder) EncBasicHandle() *BasicHandle {
|
||||||
return f.e.h
|
return f.e.h
|
||||||
}
|
}
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
func (f genHelperEncoder) EncBinary() bool {
|
func (f genHelperEncoder) EncBinary() bool {
|
||||||
return f.e.be // f.e.hh.isBinaryEncoding()
|
return f.e.be // f.e.hh.isBinaryEncoding()
|
||||||
}
|
}
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// 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 {
|
func (f genHelperEncoder) IsJSONHandle() bool {
|
||||||
return f.e.js
|
return f.e.js
|
||||||
}
|
}
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// 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)
|
|
||||||
f.e.encodeValue(reflect.ValueOf(iv), nil, 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, cUTF8)
|
|
||||||
}
|
|
||||||
// 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, cUTF8)
|
|
||||||
}
|
|
||||||
// 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, cRAW)
|
|
||||||
}
|
|
||||||
// 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*
|
|
||||||
//
|
|
||||||
// Deprecated: builtin no longer supported - so we make this method a no-op,
|
|
||||||
// but leave in-place so that old generated files continue to work without regeneration.
|
|
||||||
func (f genHelperEncoder) TimeRtidIfBinc() (v uintptr) { return }
|
|
||||||
// func (f genHelperEncoder) TimeRtidIfBinc() uintptr {
|
|
||||||
// if _, ok := f.e.hh.(*BincHandle); ok {
|
|
||||||
// return timeTypId
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
|
||||||
func (f genHelperEncoder) I2Rtid(v interface{}) uintptr {
|
|
||||||
return i2rtid(v)
|
|
||||||
}
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
|
||||||
func (f genHelperEncoder) Extension(rtid uintptr) (xfn *extTypeTagFn) {
|
|
||||||
return f.e.h.getExt(rtid)
|
|
||||||
}
|
|
||||||
// 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, f.e)
|
|
||||||
}
|
|
||||||
// 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*
|
|
||||||
//
|
|
||||||
// Deprecated: No longer used,
|
|
||||||
// but leave in-place so that old generated files continue to work without regeneration.
|
|
||||||
func (f genHelperEncoder) HasExtensions() bool {
|
func (f genHelperEncoder) HasExtensions() bool {
|
||||||
return len(f.e.h.extHandle) != 0
|
return len(f.e.h.extHandle) != 0
|
||||||
}
|
}
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
//
|
|
||||||
// Deprecated: No longer used,
|
|
||||||
// but leave in-place so that old generated files continue to work without regeneration.
|
|
||||||
func (f genHelperEncoder) EncExt(v interface{}) (r bool) {
|
func (f genHelperEncoder) EncExt(v interface{}) (r bool) {
|
||||||
if xfFn := f.e.h.getExt(i2rtid(v)); xfFn != nil {
|
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)
|
f.e.e.EncodeExt(v, xfFn.tag, xfFn.ext, f.e)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------- DECODER FOLLOWS -----------------
|
// ---------------- DECODER FOLLOWS -----------------
|
||||||
|
|
||||||
|
@ -202,24 +124,17 @@ func (f genHelperDecoder) DecBinary() bool {
|
||||||
return f.d.be // f.d.hh.isBinaryEncoding()
|
return f.d.be // f.d.hh.isBinaryEncoding()
|
||||||
}
|
}
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// 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*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
func (f genHelperDecoder) DecScratchBuffer() []byte {
|
func (f genHelperDecoder) DecScratchBuffer() []byte {
|
||||||
return f.d.b[:]
|
return f.d.b[:]
|
||||||
}
|
}
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
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) {
|
func (f genHelperDecoder) DecFallback(iv interface{}, chkPtr bool) {
|
||||||
// println(">>>>>>>>> DecFallback")
|
// println(">>>>>>>>> DecFallback")
|
||||||
rv := reflect.ValueOf(iv)
|
f.d.decodeI(iv, chkPtr, false, false, false)
|
||||||
if chkPtr {
|
|
||||||
rv = f.d.ensureDecodeable(rv)
|
|
||||||
}
|
|
||||||
f.d.decodeValue(rv, nil, false)
|
|
||||||
// f.d.decodeValueFallback(rv)
|
|
||||||
}
|
}
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
func (f genHelperDecoder) DecSliceHelperStart() (decSliceHelper, int) {
|
func (f genHelperDecoder) DecSliceHelperStart() (decSliceHelper, int) {
|
||||||
|
@ -235,14 +150,14 @@ func (f genHelperDecoder) DecArrayCannotExpand(sliceLen, streamLen int) {
|
||||||
}
|
}
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
func (f genHelperDecoder) DecTextUnmarshal(tm encoding.TextUnmarshaler) {
|
func (f genHelperDecoder) DecTextUnmarshal(tm encoding.TextUnmarshaler) {
|
||||||
fnerr := tm.UnmarshalText(f.d.d.DecodeStringAsBytes())
|
fnerr := tm.UnmarshalText(f.d.d.DecodeBytes(f.d.b[:], true, true))
|
||||||
if fnerr != nil {
|
if fnerr != nil {
|
||||||
panic(fnerr)
|
panic(fnerr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
func (f genHelperDecoder) DecJSONUnmarshal(tm jsonUnmarshaler) {
|
func (f genHelperDecoder) DecJSONUnmarshal(tm jsonUnmarshaler) {
|
||||||
// bs := f.dd.DecodeStringAsBytes()
|
// 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.
|
// grab the bytes to be read, as UnmarshalJSON needs the full JSON so as to unmarshal it itself.
|
||||||
fnerr := tm.UnmarshalJSON(f.d.nextValueBytes())
|
fnerr := tm.UnmarshalJSON(f.d.nextValueBytes())
|
||||||
if fnerr != nil {
|
if fnerr != nil {
|
||||||
|
@ -251,67 +166,199 @@ func (f genHelperDecoder) DecJSONUnmarshal(tm jsonUnmarshaler) {
|
||||||
}
|
}
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
func (f genHelperDecoder) DecBinaryUnmarshal(bm encoding.BinaryUnmarshaler) {
|
func (f genHelperDecoder) DecBinaryUnmarshal(bm encoding.BinaryUnmarshaler) {
|
||||||
fnerr := bm.UnmarshalBinary(f.d.d.DecodeBytes(nil, true))
|
fnerr := bm.UnmarshalBinary(f.d.d.DecodeBytes(nil, false, true))
|
||||||
if fnerr != nil {
|
if fnerr != nil {
|
||||||
panic(fnerr)
|
panic(fnerr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
func (f genHelperDecoder) DecRaw() []byte { return f.d.rawBytes() }
|
func (f genHelperDecoder) TimeRtidIfBinc() uintptr {
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
if _, ok := f.d.hh.(*BincHandle); ok {
|
||||||
//
|
return timeTypId
|
||||||
// Deprecated: builtin no longer supported - so we make this method a no-op,
|
}
|
||||||
// but leave in-place so that old generated files continue to work without regeneration.
|
return 0
|
||||||
func (f genHelperDecoder) TimeRtidIfBinc() (v uintptr) { return }
|
}
|
||||||
// func (f genHelperDecoder) TimeRtidIfBinc() uintptr {
|
|
||||||
// // Note: builtin is no longer supported - so make this a no-op
|
|
||||||
// if _, ok := f.d.hh.(*BincHandle); ok {
|
|
||||||
// return timeTypId
|
|
||||||
// }
|
|
||||||
// return 0
|
|
||||||
// }
|
|
||||||
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
func (f genHelperDecoder) IsJSONHandle() bool {
|
func (f genHelperDecoder) IsJSONHandle() bool {
|
||||||
return f.d.js
|
return f.d.js
|
||||||
}
|
}
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
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(rtid uintptr) (xfn *extTypeTagFn) {
|
|
||||||
return f.d.h.getExt(rtid)
|
|
||||||
}
|
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
|
||||||
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*
|
|
||||||
//
|
|
||||||
// Deprecated: No longer used,
|
|
||||||
// but leave in-place so that old generated files continue to work without regeneration.
|
|
||||||
func (f genHelperDecoder) HasExtensions() bool {
|
func (f genHelperDecoder) HasExtensions() bool {
|
||||||
return len(f.d.h.extHandle) != 0
|
return len(f.d.h.extHandle) != 0
|
||||||
}
|
}
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
//
|
|
||||||
// Deprecated: No longer used,
|
|
||||||
// but leave in-place so that old generated files continue to work without regeneration.
|
|
||||||
func (f genHelperDecoder) DecExt(v interface{}) (r bool) {
|
func (f genHelperDecoder) DecExt(v interface{}) (r bool) {
|
||||||
if xfFn := f.d.h.getExt(i2rtid(v)); xfFn != nil {
|
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)
|
f.d.d.DecodeExt(v, xfFn.tag, xfFn.ext)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
func (f genHelperDecoder) DecInferLen(clen, maxlen, unit int) (rvlen int) {
|
func (f genHelperDecoder) DecInferLen(clen, maxlen, unit int) (rvlen int, truncated bool) {
|
||||||
return decInferLen(clen, maxlen, unit)
|
return decInferLen(clen, maxlen, unit)
|
||||||
}
|
}
|
||||||
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
//
|
func (f genHelperDecoder) DecSendContainerState(c containerState) {
|
||||||
// Deprecated: no longer used,
|
if f.d.cr != nil {
|
||||||
// but leave in-place so that old generated files continue to work without regeneration.
|
f.d.cr.sendContainerState(c)
|
||||||
func (f genHelperDecoder) StringView(v []byte) string { return stringView(v) }
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
|
||||||
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
|
func (f genHelperEncoder) EncDriver() encDriver {
|
||||||
|
return f.e.e
|
||||||
|
}
|
||||||
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
|
func (f genHelperDecoder) DecDriver() decDriver {
|
||||||
|
return f.d.d
|
||||||
|
}
|
||||||
|
|
||||||
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
|
func (f genHelperEncoder) EncNil() {
|
||||||
|
f.e.e.EncodeNil()
|
||||||
|
}
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
|
||||||
|
func (f genHelperEncoder) EncArrayStart(length int) {
|
||||||
|
f.e.e.EncodeArrayStart(length)
|
||||||
|
}
|
||||||
|
// 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 }}
|
||||||
|
*/}}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
// +build codecgen.exec
|
|
||||||
|
|
||||||
// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
|
// 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.
|
// Use of this source code is governed by a MIT license found in the LICENSE file.
|
||||||
|
|
||||||
|
@ -12,22 +10,21 @@ const genDecMapTmpl = `
|
||||||
{{var "l"}} := r.ReadMapStart()
|
{{var "l"}} := r.ReadMapStart()
|
||||||
{{var "bh"}} := z.DecBasicHandle()
|
{{var "bh"}} := z.DecBasicHandle()
|
||||||
if {{var "v"}} == nil {
|
if {{var "v"}} == nil {
|
||||||
{{var "rl"}} := z.DecInferLen({{var "l"}}, {{var "bh"}}.MaxInitLen, {{ .Size }})
|
{{var "rl"}}, _ := z.DecInferLen({{var "l"}}, {{var "bh"}}.MaxInitLen, {{ .Size }})
|
||||||
{{var "v"}} = make(map[{{ .KTyp }}]{{ .Typ }}, {{var "rl"}})
|
{{var "v"}} = make(map[{{ .KTyp }}]{{ .Typ }}, {{var "rl"}})
|
||||||
*{{ .Varname }} = {{var "v"}}
|
*{{ .Varname }} = {{var "v"}}
|
||||||
}
|
}
|
||||||
var {{var "mk"}} {{ .KTyp }}
|
var {{var "mk"}} {{ .KTyp }}
|
||||||
var {{var "mv"}} {{ .Typ }}
|
var {{var "mv"}} {{ .Typ }}
|
||||||
var {{var "mg"}}, {{var "mdn"}} {{if decElemKindPtr}}, {{var "ms"}}, {{var "mok"}}{{end}} bool
|
var {{var "mg"}} {{if decElemKindPtr}}, {{var "ms"}}, {{var "mok"}}{{end}} bool
|
||||||
if {{var "bh"}}.MapValueReset {
|
if {{var "bh"}}.MapValueReset {
|
||||||
{{if decElemKindPtr}}{{var "mg"}} = true
|
{{if decElemKindPtr}}{{var "mg"}} = true
|
||||||
{{else if decElemKindIntf}}if !{{var "bh"}}.InterfaceReset { {{var "mg"}} = true }
|
{{else if decElemKindIntf}}if !{{var "bh"}}.InterfaceReset { {{var "mg"}} = true }
|
||||||
{{else if not decElemKindImmutable}}{{var "mg"}} = true
|
{{else if not decElemKindImmutable}}{{var "mg"}} = true
|
||||||
{{end}} }
|
{{end}} }
|
||||||
if {{var "l"}} != 0 {
|
if {{var "l"}} > 0 {
|
||||||
{{var "hl"}} := {{var "l"}} > 0
|
for {{var "j"}} := 0; {{var "j"}} < {{var "l"}}; {{var "j"}}++ {
|
||||||
for {{var "j"}} := 0; ({{var "hl"}} && {{var "j"}} < {{var "l"}}) || !({{var "hl"}} || r.CheckBreak()); {{var "j"}}++ {
|
z.DecSendContainerState(codecSelfer_containerMapKey{{ .Sfx }})
|
||||||
r.ReadMapElemKey() {{/* z.DecSendContainerState(codecSelfer_containerMapKey{{ .Sfx }}) */}}
|
|
||||||
{{ $x := printf "%vmk%v" .TempVar .Rand }}{{ decLineVarK $x }}
|
{{ $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"}} {
|
{{ 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"}})
|
{{var "mk"}} = string({{var "bv"}})
|
||||||
|
@ -39,17 +36,34 @@ if {{var "l"}} != 0 {
|
||||||
{{var "ms"}} = false
|
{{var "ms"}} = false
|
||||||
} {{else}}{{var "mv"}} = {{var "v"}}[{{var "mk"}}] {{end}}
|
} {{else}}{{var "mv"}} = {{var "v"}}[{{var "mk"}}] {{end}}
|
||||||
} {{if not decElemKindImmutable}}else { {{var "mv"}} = {{decElemZero}} }{{end}}
|
} {{if not decElemKindImmutable}}else { {{var "mv"}} = {{decElemZero}} }{{end}}
|
||||||
r.ReadMapElemValue() {{/* z.DecSendContainerState(codecSelfer_containerMapValue{{ .Sfx }}) */}}
|
z.DecSendContainerState(codecSelfer_containerMapValue{{ .Sfx }})
|
||||||
{{var "mdn"}} = false
|
{{ $x := printf "%vmv%v" .TempVar .Rand }}{{ decLineVar $x }}
|
||||||
{{ $x := printf "%vmv%v" .TempVar .Rand }}{{ $y := printf "%vmdn%v" .TempVar .Rand }}{{ decLineVar $x $y }}
|
if {{if decElemKindPtr}} {{var "ms"}} && {{end}} {{var "v"}} != nil {
|
||||||
if {{var "mdn"}} {
|
{{var "v"}}[{{var "mk"}}] = {{var "mv"}}
|
||||||
if {{ var "bh" }}.DeleteOnNilMapValue { delete({{var "v"}}, {{var "mk"}}) } else { {{var "v"}}[{{var "mk"}}] = {{decElemZero}} }
|
}
|
||||||
} else if {{if decElemKindPtr}} {{var "ms"}} && {{end}} {{var "v"}} != nil {
|
}
|
||||||
|
} 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"}}
|
{{var "v"}}[{{var "mk"}}] = {{var "mv"}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // else len==0: TODO: Should we clear map entries?
|
} // else len==0: TODO: Should we clear map entries?
|
||||||
r.ReadMapEnd() {{/* z.DecSendContainerState(codecSelfer_containerMapEnd{{ .Sfx }}) */}}
|
z.DecSendContainerState(codecSelfer_containerMapEnd{{ .Sfx }})
|
||||||
`
|
`
|
||||||
|
|
||||||
const genDecListTmpl = `
|
const genDecListTmpl = `
|
||||||
|
@ -64,68 +78,94 @@ if {{var "l"}} == 0 {
|
||||||
} else if len({{var "v"}}) != 0 {
|
} else if len({{var "v"}}) != 0 {
|
||||||
{{var "v"}} = {{var "v"}}[:0]
|
{{var "v"}} = {{var "v"}}[:0]
|
||||||
{{var "c"}} = true
|
{{var "c"}} = true
|
||||||
} {{else if isChan }}if {{var "v"}} == nil {
|
} {{end}} {{if isChan }}if {{var "v"}} == nil {
|
||||||
{{var "v"}} = make({{ .CTyp }}, 0)
|
{{var "v"}} = make({{ .CTyp }}, 0)
|
||||||
{{var "c"}} = true
|
{{var "c"}} = true
|
||||||
} {{end}}
|
} {{end}}
|
||||||
} else {
|
} else if {{var "l"}} > 0 {
|
||||||
{{var "hl"}} := {{var "l"}} > 0
|
{{if isChan }}if {{var "v"}} == nil {
|
||||||
var {{var "rl"}} int
|
{{var "rl"}}, _ = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})
|
||||||
_ = {{var "rl"}}
|
{{var "v"}} = make({{ .CTyp }}, {{var "rl"}})
|
||||||
{{if isSlice }} if {{var "hl"}} {
|
{{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"}})
|
||||||
if {{var "l"}} > cap({{var "v"}}) {
|
if {{var "l"}} > cap({{var "v"}}) {
|
||||||
{{var "rl"}} = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})
|
{{if isArray }}z.DecArrayCannotExpand(len({{var "v"}}), {{var "l"}})
|
||||||
if {{var "rl"}} <= cap({{var "v"}}) {
|
{{ else }}{{if not .Immutable }}
|
||||||
{{var "v"}} = {{var "v"}}[:{{var "rl"}}]
|
{{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"}})
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
{{var "v"}} = make([]{{ .Typ }}, {{var "rl"}})
|
{{var "v"}} = make([]{{ .Typ }}, {{var "rl"}})
|
||||||
}
|
}
|
||||||
{{var "c"}} = true
|
{{var "c"}} = true
|
||||||
} else if {{var "l"}} != len({{var "v"}}) {
|
{{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"}}) {
|
||||||
{{var "v"}} = {{var "v"}}[:{{var "l"}}]
|
{{var "v"}} = {{var "v"}}[:{{var "l"}}]
|
||||||
{{var "c"}} = true
|
{{var "c"}} = true
|
||||||
}
|
} {{end}} {{/* end isSlice:47 */}}
|
||||||
} {{end}}
|
{{var "j"}} := 0
|
||||||
var {{var "j"}} int
|
for ; {{var "j"}} < {{var "rr"}} ; {{var "j"}}++ {
|
||||||
// var {{var "dn"}} bool
|
|
||||||
for ; ({{var "hl"}} && {{var "j"}} < {{var "l"}}) || !({{var "hl"}} || r.CheckBreak()); {{var "j"}}++ {
|
|
||||||
{{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}}
|
|
||||||
{{var "h"}}.ElemContainerState({{var "j"}})
|
{{var "h"}}.ElemContainerState({{var "j"}})
|
||||||
{{/* {{var "dn"}} = r.TryDecodeAsNil() */}}{{/* commented out, as decLineVar handles this already each time */}}
|
{{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }}
|
||||||
{{if isChan}}{{ $x := printf "%[1]vvcx%[2]v" .TempVar .Rand }}var {{$x}} {{ .Typ }}
|
}
|
||||||
{{ decLineVar $x }}
|
{{if isArray }}for ; {{var "j"}} < {{var "l"}} ; {{var "j"}}++ {
|
||||||
{{var "v"}} <- {{ $x }}
|
{{var "h"}}.ElemContainerState({{var "j"}})
|
||||||
// println(">>>> sending ", {{ $x }}, " into ", {{var "v"}}) // TODO: remove this
|
z.DecSwallow()
|
||||||
{{else}}{{/* // if indefinite, etc, then expand the slice if necessary */}}
|
}
|
||||||
var {{var "db"}} bool
|
{{ else }}if {{var "rt"}} {
|
||||||
if {{var "j"}} >= len({{var "v"}}) {
|
for ; {{var "j"}} < {{var "l"}} ; {{var "j"}}++ {
|
||||||
{{if isSlice }} {{var "v"}} = append({{var "v"}}, {{ zero }})
|
{{var "v"}} = append({{var "v"}}, {{ zero}})
|
||||||
{{var "c"}} = true
|
{{var "h"}}.ElemContainerState({{var "j"}})
|
||||||
{{else}} z.DecArrayCannotExpand(len(v), {{var "j"}}+1); {{var "db"}} = true
|
|
||||||
{{end}}
|
|
||||||
}
|
|
||||||
if {{var "db"}} {
|
|
||||||
z.DecSwallow()
|
|
||||||
} else {
|
|
||||||
{{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }}
|
{{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }}
|
||||||
}
|
}
|
||||||
{{end}}
|
} {{end}} {{/* end isArray:56 */}}
|
||||||
|
{{end}} {{/* end isChan:16 */}}
|
||||||
|
} else { {{/* len < 0 */}}
|
||||||
|
{{var "j"}} := 0
|
||||||
|
for ; !r.CheckBreak(); {{var "j"}}++ {
|
||||||
|
{{if isChan }}
|
||||||
|
{{var "h"}}.ElemContainerState({{var "j"}})
|
||||||
|
var {{var "t"}} {{ .Typ }}
|
||||||
|
{{ $x := printf "%st%s" .TempVar .Rand }}{{ decLineVar $x }}
|
||||||
|
{{var "v"}} <- {{var "t"}}
|
||||||
|
{{ else }}
|
||||||
|
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}}
|
||||||
|
}
|
||||||
|
{{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 {
|
||||||
|
z.DecSwallow()
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
}
|
}
|
||||||
{{if isSlice}} if {{var "j"}} < len({{var "v"}}) {
|
{{if isSlice }}if {{var "j"}} < len({{var "v"}}) {
|
||||||
{{var "v"}} = {{var "v"}}[:{{var "j"}}]
|
{{var "v"}} = {{var "v"}}[:{{var "j"}}]
|
||||||
{{var "c"}} = true
|
{{var "c"}} = true
|
||||||
} else if {{var "j"}} == 0 && {{var "v"}} == nil {
|
} else if {{var "j"}} == 0 && {{var "v"}} == nil {
|
||||||
{{var "v"}} = make([]{{ .Typ }}, 0)
|
{{var "v"}} = []{{ .Typ }}{}
|
||||||
{{var "c"}} = true
|
{{var "c"}} = true
|
||||||
} {{end}}
|
}{{end}}
|
||||||
}
|
}
|
||||||
{{var "h"}}.End()
|
{{var "h"}}.End()
|
||||||
{{if not isArray }}if {{var "c"}} {
|
{{if not isArray }}if {{var "c"}} {
|
||||||
|
@ -133,32 +173,3 @@ if {{var "l"}} == 0 {
|
||||||
}{{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
|
@ -1,14 +0,0 @@
|
||||||
// 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.
|
|
||||||
|
|
||||||
// +build go1.5
|
|
||||||
|
|
||||||
package codec
|
|
||||||
|
|
||||||
import "reflect"
|
|
||||||
|
|
||||||
const reflectArrayOfSupported = true
|
|
||||||
|
|
||||||
func reflectArrayOf(count int, elem reflect.Type) reflect.Type {
|
|
||||||
return reflect.ArrayOf(count, elem)
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
// 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.
|
|
||||||
|
|
||||||
// +build !go1.5
|
|
||||||
|
|
||||||
package codec
|
|
||||||
|
|
||||||
import "reflect"
|
|
||||||
|
|
||||||
const reflectArrayOfSupported = false
|
|
||||||
|
|
||||||
func reflectArrayOf(count int, elem reflect.Type) reflect.Type {
|
|
||||||
panic("codec: reflect.ArrayOf unsupported in this go version")
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
// 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.
|
|
||||||
|
|
||||||
// +build go1.9
|
|
||||||
|
|
||||||
package codec
|
|
||||||
|
|
||||||
import "reflect"
|
|
||||||
|
|
||||||
func makeMapReflect(t reflect.Type, size int) reflect.Value {
|
|
||||||
if size < 0 {
|
|
||||||
return reflect.MakeMapWithSize(t, 4)
|
|
||||||
}
|
|
||||||
return reflect.MakeMapWithSize(t, size)
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
// 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.
|
|
||||||
|
|
||||||
// +build !go1.9
|
|
||||||
|
|
||||||
package codec
|
|
||||||
|
|
||||||
import "reflect"
|
|
||||||
|
|
||||||
func makeMapReflect(t reflect.Type, size int) reflect.Value {
|
|
||||||
return reflect.MakeMap(t)
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
// 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.
|
|
||||||
|
|
||||||
// +build go1.10
|
|
||||||
|
|
||||||
package codec
|
|
||||||
|
|
||||||
const allowSetUnexportedEmbeddedPtr = false
|
|
|
@ -1,8 +0,0 @@
|
||||||
// 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.
|
|
||||||
|
|
||||||
// +build !go1.10
|
|
||||||
|
|
||||||
package codec
|
|
||||||
|
|
||||||
const allowSetUnexportedEmbeddedPtr = true
|
|
|
@ -1,17 +0,0 @@
|
||||||
// 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.
|
|
||||||
|
|
||||||
// +build !go1.4
|
|
||||||
|
|
||||||
package codec
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
panic("codec: go 1.3 and below are not supported")
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
// 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.
|
|
||||||
|
|
||||||
// +build go1.5,!go1.6
|
|
||||||
|
|
||||||
package codec
|
|
||||||
|
|
||||||
import "os"
|
|
||||||
|
|
||||||
var genCheckVendor = os.Getenv("GO15VENDOREXPERIMENT") == "1"
|
|
|
@ -1,10 +0,0 @@
|
||||||
// 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.
|
|
||||||
|
|
||||||
// +build go1.6,!go1.7
|
|
||||||
|
|
||||||
package codec
|
|
||||||
|
|
||||||
import "os"
|
|
||||||
|
|
||||||
var genCheckVendor = os.Getenv("GO15VENDOREXPERIMENT") != "0"
|
|
|
@ -1,8 +0,0 @@
|
||||||
// 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.
|
|
||||||
|
|
||||||
// +build go1.7
|
|
||||||
|
|
||||||
package codec
|
|
||||||
|
|
||||||
const genCheckVendor = true
|
|
|
@ -1,8 +0,0 @@
|
||||||
// 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.
|
|
||||||
|
|
||||||
// +build !go1.5
|
|
||||||
|
|
||||||
package codec
|
|
||||||
|
|
||||||
var genCheckVendor = false
|
|
File diff suppressed because it is too large
Load Diff
|
@ -6,6 +6,74 @@ package codec
|
||||||
// All non-std package dependencies live in this file,
|
// All non-std package dependencies live in this file,
|
||||||
// so porting to different environment is easy (just update functions).
|
// 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) {
|
func pruneSignExt(v []byte, pos bool) (n int) {
|
||||||
if len(v) < 2 {
|
if len(v) < 2 {
|
||||||
} else if pos && v[0] == 0 {
|
} else if pos && v[0] == 0 {
|
||||||
|
@ -18,6 +86,37 @@ func pruneSignExt(v []byte, pos bool) (n int) {
|
||||||
return
|
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
|
||||||
|
}
|
||||||
|
|
||||||
// validate that this function is correct ...
|
// validate that this function is correct ...
|
||||||
// culled from OGRE (Object-Oriented Graphics Rendering Engine)
|
// culled from OGRE (Object-Oriented Graphics Rendering Engine)
|
||||||
// function: halfToFloatI (http://stderr.org/doc/ogre-doc/api/OgreBitwise_8h-source.html)
|
// function: halfToFloatI (http://stderr.org/doc/ogre-doc/api/OgreBitwise_8h-source.html)
|
||||||
|
@ -30,20 +129,21 @@ func halfFloatToFloatBits(yy uint16) (d uint32) {
|
||||||
if e == 0 {
|
if e == 0 {
|
||||||
if m == 0 { // plu or minus 0
|
if m == 0 { // plu or minus 0
|
||||||
return s << 31
|
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 & 0x00000400) == 0 {
|
|
||||||
m <<= 1
|
|
||||||
e -= 1
|
|
||||||
}
|
|
||||||
e += 1
|
|
||||||
const zz uint32 = 0x0400
|
|
||||||
m &= ^zz
|
|
||||||
} else if e == 31 {
|
} else if e == 31 {
|
||||||
if m == 0 { // Inf
|
if m == 0 { // Inf
|
||||||
return (s << 31) | 0x7f800000
|
return (s << 31) | 0x7f800000
|
||||||
|
} else { // NaN
|
||||||
|
return (s << 31) | 0x7f800000 | (m << 13)
|
||||||
}
|
}
|
||||||
return (s << 31) | 0x7f800000 | (m << 13) // NaN
|
|
||||||
}
|
}
|
||||||
e = e + (127 - 15)
|
e = e + (127 - 15)
|
||||||
m = m << 13
|
m = m << 13
|
||||||
|
@ -119,3 +219,24 @@ func growCap(oldCap, unit, num int) (newCap int) {
|
||||||
}
|
}
|
||||||
return
|
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,24 +1,13 @@
|
||||||
// +build !go1.7 safe appengine
|
//+build !unsafe
|
||||||
|
|
||||||
// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
|
// 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.
|
// Use of this source code is governed by a MIT license found in the LICENSE file.
|
||||||
|
|
||||||
package codec
|
package codec
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const safeMode = true
|
|
||||||
|
|
||||||
// stringView returns a view of the []byte as a string.
|
// stringView returns a view of the []byte as a string.
|
||||||
// In unsafe mode, it doesn't incur allocation and copying caused by conversion.
|
// In unsafe mode, it doesn't incur allocation and copying caused by conversion.
|
||||||
// In regular safe mode, it is an allocation and copy.
|
// In regular safe mode, it is an allocation and copy.
|
||||||
//
|
|
||||||
// Usage: Always maintain a reference to v while result of this call is in use,
|
|
||||||
// and call keepAlive4BytesView(v) at point where done with view.
|
|
||||||
func stringView(v []byte) string {
|
func stringView(v []byte) string {
|
||||||
return string(v)
|
return string(v)
|
||||||
}
|
}
|
||||||
|
@ -26,247 +15,6 @@ func stringView(v []byte) string {
|
||||||
// bytesView returns a view of the string as a []byte.
|
// bytesView returns a view of the string as a []byte.
|
||||||
// In unsafe mode, it doesn't incur allocation and copying caused by conversion.
|
// In unsafe mode, it doesn't incur allocation and copying caused by conversion.
|
||||||
// In regular safe mode, it is an allocation and copy.
|
// In regular safe mode, it is an allocation and copy.
|
||||||
//
|
|
||||||
// Usage: Always maintain a reference to v while result of this call is in use,
|
|
||||||
// and call keepAlive4BytesView(v) at point where done with view.
|
|
||||||
func bytesView(v string) []byte {
|
func bytesView(v string) []byte {
|
||||||
return []byte(v)
|
return []byte(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func definitelyNil(v interface{}) bool {
|
|
||||||
// this is a best-effort option.
|
|
||||||
// We just return false, so we don't unnecessarily incur the cost of reflection this early.
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func rv2i(rv reflect.Value) interface{} {
|
|
||||||
return rv.Interface()
|
|
||||||
}
|
|
||||||
|
|
||||||
func rt2id(rt reflect.Type) uintptr {
|
|
||||||
return reflect.ValueOf(rt).Pointer()
|
|
||||||
}
|
|
||||||
|
|
||||||
func rv2rtid(rv reflect.Value) uintptr {
|
|
||||||
return reflect.ValueOf(rv.Type()).Pointer()
|
|
||||||
}
|
|
||||||
|
|
||||||
func i2rtid(i interface{}) uintptr {
|
|
||||||
return reflect.ValueOf(reflect.TypeOf(i)).Pointer()
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------
|
|
||||||
|
|
||||||
func isEmptyValue(v reflect.Value, tinfos *TypeInfos, 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 isEmptyValue(v.Elem(), tinfos, deref, checkStruct)
|
|
||||||
}
|
|
||||||
return v.IsNil()
|
|
||||||
case reflect.Struct:
|
|
||||||
return isEmptyStruct(v, tinfos, deref, checkStruct)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------
|
|
||||||
// type ptrToRvMap struct{}
|
|
||||||
|
|
||||||
// func (*ptrToRvMap) init() {}
|
|
||||||
// func (*ptrToRvMap) get(i interface{}) reflect.Value {
|
|
||||||
// return reflect.ValueOf(i).Elem()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// --------------------------
|
|
||||||
type atomicTypeInfoSlice struct { // expected to be 2 words
|
|
||||||
v atomic.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *atomicTypeInfoSlice) load() []rtid2ti {
|
|
||||||
i := x.v.Load()
|
|
||||||
if i == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return i.([]rtid2ti)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *atomicTypeInfoSlice) store(p []rtid2ti) {
|
|
||||||
x.v.Store(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------
|
|
||||||
func (d *Decoder) raw(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
rv.SetBytes(d.rawBytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kString(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
rv.SetString(d.d.DecodeString())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kBool(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
rv.SetBool(d.d.DecodeBool())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kTime(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
rv.Set(reflect.ValueOf(d.d.DecodeTime()))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
fv := d.d.DecodeFloat64()
|
|
||||||
if chkOvf.Float32(fv) {
|
|
||||||
d.errorf("float32 overflow: %v", fv)
|
|
||||||
}
|
|
||||||
rv.SetFloat(fv)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kFloat64(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
rv.SetFloat(d.d.DecodeFloat64())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kInt(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
rv.SetInt(chkOvf.IntV(d.d.DecodeInt64(), intBitsize))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kInt8(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
rv.SetInt(chkOvf.IntV(d.d.DecodeInt64(), 8))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kInt16(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
rv.SetInt(chkOvf.IntV(d.d.DecodeInt64(), 16))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kInt32(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
rv.SetInt(chkOvf.IntV(d.d.DecodeInt64(), 32))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kInt64(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
rv.SetInt(d.d.DecodeInt64())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kUint(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
rv.SetUint(chkOvf.UintV(d.d.DecodeUint64(), uintBitsize))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kUintptr(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
rv.SetUint(chkOvf.UintV(d.d.DecodeUint64(), uintBitsize))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kUint8(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
rv.SetUint(chkOvf.UintV(d.d.DecodeUint64(), 8))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kUint16(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
rv.SetUint(chkOvf.UintV(d.d.DecodeUint64(), 16))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kUint32(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
rv.SetUint(chkOvf.UintV(d.d.DecodeUint64(), 32))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kUint64(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
rv.SetUint(d.d.DecodeUint64())
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------
|
|
||||||
|
|
||||||
func (e *Encoder) kBool(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
e.e.EncodeBool(rv.Bool())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kTime(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
e.e.EncodeTime(rv2i(rv).(time.Time))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kString(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
e.e.EncodeString(cUTF8, rv.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kFloat64(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
e.e.EncodeFloat64(rv.Float())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
e.e.EncodeFloat32(float32(rv.Float()))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kInt(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
e.e.EncodeInt(rv.Int())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kInt8(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
e.e.EncodeInt(rv.Int())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kInt16(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
e.e.EncodeInt(rv.Int())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kInt32(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
e.e.EncodeInt(rv.Int())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kInt64(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
e.e.EncodeInt(rv.Int())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kUint(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
e.e.EncodeUint(rv.Uint())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kUint8(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
e.e.EncodeUint(rv.Uint())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kUint16(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
e.e.EncodeUint(rv.Uint())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kUint32(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
e.e.EncodeUint(rv.Uint())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kUint64(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
e.e.EncodeUint(rv.Uint())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kUintptr(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
e.e.EncodeUint(rv.Uint())
|
|
||||||
}
|
|
||||||
|
|
||||||
// // keepAlive4BytesView maintains a reference to the input parameter for bytesView.
|
|
||||||
// //
|
|
||||||
// // Usage: call this at point where done with the bytes view.
|
|
||||||
// func keepAlive4BytesView(v string) {}
|
|
||||||
|
|
||||||
// // keepAlive4BytesView maintains a reference to the input parameter for stringView.
|
|
||||||
// //
|
|
||||||
// // Usage: call this at point where done with the string view.
|
|
||||||
// func keepAlive4StringView(v []byte) {}
|
|
||||||
|
|
||||||
// func definitelyNil(v interface{}) bool {
|
|
||||||
// rv := reflect.ValueOf(v)
|
|
||||||
// switch rv.Kind() {
|
|
||||||
// case reflect.Invalid:
|
|
||||||
// return true
|
|
||||||
// case reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Slice, reflect.Map, reflect.Func:
|
|
||||||
// return rv.IsNil()
|
|
||||||
// default:
|
|
||||||
// return false
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
|
@ -1,639 +1,45 @@
|
||||||
// +build !safe
|
//+build unsafe
|
||||||
// +build !appengine
|
|
||||||
// +build go1.7
|
|
||||||
|
|
||||||
// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
|
// 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.
|
// Use of this source code is governed by a MIT license found in the LICENSE file.
|
||||||
|
|
||||||
package codec
|
package codec
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This file has unsafe variants of some helper methods.
|
// This file has unsafe variants of some helper methods.
|
||||||
// NOTE: See helper_not_unsafe.go for the usage information.
|
|
||||||
|
|
||||||
// var zeroRTv [4]uintptr
|
|
||||||
|
|
||||||
const safeMode = false
|
|
||||||
const unsafeFlagIndir = 1 << 7 // keep in sync with GO_ROOT/src/reflect/value.go
|
|
||||||
|
|
||||||
type unsafeString struct {
|
type unsafeString struct {
|
||||||
Data unsafe.Pointer
|
Data uintptr
|
||||||
Len int
|
Len int
|
||||||
}
|
}
|
||||||
|
|
||||||
type unsafeSlice struct {
|
type unsafeBytes struct {
|
||||||
Data unsafe.Pointer
|
Data uintptr
|
||||||
Len int
|
Len int
|
||||||
Cap int
|
Cap int
|
||||||
}
|
}
|
||||||
|
|
||||||
type unsafeIntf struct {
|
// stringView returns a view of the []byte as a string.
|
||||||
typ unsafe.Pointer
|
// In unsafe mode, it doesn't incur allocation and copying caused by conversion.
|
||||||
word unsafe.Pointer
|
// In regular safe mode, it is an allocation and copy.
|
||||||
}
|
|
||||||
|
|
||||||
type unsafeReflectValue struct {
|
|
||||||
typ unsafe.Pointer
|
|
||||||
ptr unsafe.Pointer
|
|
||||||
flag uintptr
|
|
||||||
}
|
|
||||||
|
|
||||||
func stringView(v []byte) string {
|
func stringView(v []byte) string {
|
||||||
if len(v) == 0 {
|
if len(v) == 0 {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
bx := (*unsafeSlice)(unsafe.Pointer(&v))
|
x := unsafeString{uintptr(unsafe.Pointer(&v[0])), len(v)}
|
||||||
return *(*string)(unsafe.Pointer(&unsafeString{bx.Data, bx.Len}))
|
return *(*string)(unsafe.Pointer(&x))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 {
|
func bytesView(v string) []byte {
|
||||||
if len(v) == 0 {
|
if len(v) == 0 {
|
||||||
return zeroByteSlice
|
return zeroByteSlice
|
||||||
}
|
}
|
||||||
sx := (*unsafeString)(unsafe.Pointer(&v))
|
x := unsafeBytes{uintptr(unsafe.Pointer(&v)), len(v), len(v)}
|
||||||
return *(*[]byte)(unsafe.Pointer(&unsafeSlice{sx.Data, sx.Len, sx.Len}))
|
return *(*[]byte)(unsafe.Pointer(&x))
|
||||||
}
|
}
|
||||||
|
|
||||||
func definitelyNil(v interface{}) bool {
|
|
||||||
// There is no global way of checking if an interface is nil.
|
|
||||||
// For true references (map, ptr, func, chan), you can just look
|
|
||||||
// at the word of the interface. However, for slices, you have to dereference
|
|
||||||
// the word, and get a pointer to the 3-word interface value.
|
|
||||||
//
|
|
||||||
// However, the following are cheap calls
|
|
||||||
// - TypeOf(interface): cheap 2-line call.
|
|
||||||
// - ValueOf(interface{}): expensive
|
|
||||||
// - type.Kind: cheap call through an interface
|
|
||||||
// - Value.Type(): cheap call
|
|
||||||
// except it's a method value (e.g. r.Read, which implies that it is a Func)
|
|
||||||
|
|
||||||
return ((*unsafeIntf)(unsafe.Pointer(&v))).word == nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func rv2i(rv reflect.Value) interface{} {
|
|
||||||
// TODO: consider a more generally-known optimization for reflect.Value ==> Interface
|
|
||||||
//
|
|
||||||
// Currently, we use this fragile method that taps into implememtation details from
|
|
||||||
// the source go stdlib reflect/value.go, and trims the implementation.
|
|
||||||
|
|
||||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
// true references (map, func, chan, ptr - NOT slice) may be double-referenced as flagIndir
|
|
||||||
var ptr unsafe.Pointer
|
|
||||||
if refBitset.isset(byte(urv.flag&(1<<5-1))) && urv.flag&unsafeFlagIndir != 0 {
|
|
||||||
ptr = *(*unsafe.Pointer)(urv.ptr)
|
|
||||||
} else {
|
|
||||||
ptr = urv.ptr
|
|
||||||
}
|
|
||||||
return *(*interface{})(unsafe.Pointer(&unsafeIntf{typ: urv.typ, word: ptr}))
|
|
||||||
}
|
|
||||||
|
|
||||||
func rt2id(rt reflect.Type) uintptr {
|
|
||||||
return uintptr(((*unsafeIntf)(unsafe.Pointer(&rt))).word)
|
|
||||||
}
|
|
||||||
|
|
||||||
func rv2rtid(rv reflect.Value) uintptr {
|
|
||||||
return uintptr((*unsafeReflectValue)(unsafe.Pointer(&rv)).typ)
|
|
||||||
}
|
|
||||||
|
|
||||||
func i2rtid(i interface{}) uintptr {
|
|
||||||
return uintptr(((*unsafeIntf)(unsafe.Pointer(&i))).typ)
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------
|
|
||||||
|
|
||||||
func isEmptyValue(v reflect.Value, tinfos *TypeInfos, deref, checkStruct bool) bool {
|
|
||||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&v))
|
|
||||||
if urv.flag == 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
switch v.Kind() {
|
|
||||||
case reflect.Invalid:
|
|
||||||
return true
|
|
||||||
case reflect.String:
|
|
||||||
return (*unsafeString)(urv.ptr).Len == 0
|
|
||||||
case reflect.Slice:
|
|
||||||
return (*unsafeSlice)(urv.ptr).Len == 0
|
|
||||||
case reflect.Bool:
|
|
||||||
return !*(*bool)(urv.ptr)
|
|
||||||
case reflect.Int:
|
|
||||||
return *(*int)(urv.ptr) == 0
|
|
||||||
case reflect.Int8:
|
|
||||||
return *(*int8)(urv.ptr) == 0
|
|
||||||
case reflect.Int16:
|
|
||||||
return *(*int16)(urv.ptr) == 0
|
|
||||||
case reflect.Int32:
|
|
||||||
return *(*int32)(urv.ptr) == 0
|
|
||||||
case reflect.Int64:
|
|
||||||
return *(*int64)(urv.ptr) == 0
|
|
||||||
case reflect.Uint:
|
|
||||||
return *(*uint)(urv.ptr) == 0
|
|
||||||
case reflect.Uint8:
|
|
||||||
return *(*uint8)(urv.ptr) == 0
|
|
||||||
case reflect.Uint16:
|
|
||||||
return *(*uint16)(urv.ptr) == 0
|
|
||||||
case reflect.Uint32:
|
|
||||||
return *(*uint32)(urv.ptr) == 0
|
|
||||||
case reflect.Uint64:
|
|
||||||
return *(*uint64)(urv.ptr) == 0
|
|
||||||
case reflect.Uintptr:
|
|
||||||
return *(*uintptr)(urv.ptr) == 0
|
|
||||||
case reflect.Float32:
|
|
||||||
return *(*float32)(urv.ptr) == 0
|
|
||||||
case reflect.Float64:
|
|
||||||
return *(*float64)(urv.ptr) == 0
|
|
||||||
case reflect.Interface:
|
|
||||||
isnil := urv.ptr == nil || *(*unsafe.Pointer)(urv.ptr) == nil
|
|
||||||
if deref {
|
|
||||||
if isnil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return isEmptyValue(v.Elem(), tinfos, deref, checkStruct)
|
|
||||||
}
|
|
||||||
return isnil
|
|
||||||
case reflect.Ptr:
|
|
||||||
// isnil := urv.ptr == nil (not sufficient, as a pointer value encodes the type)
|
|
||||||
isnil := urv.ptr == nil || *(*unsafe.Pointer)(urv.ptr) == nil
|
|
||||||
if deref {
|
|
||||||
if isnil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return isEmptyValue(v.Elem(), tinfos, deref, checkStruct)
|
|
||||||
}
|
|
||||||
return isnil
|
|
||||||
case reflect.Struct:
|
|
||||||
return isEmptyStruct(v, tinfos, deref, checkStruct)
|
|
||||||
case reflect.Map, reflect.Array, reflect.Chan:
|
|
||||||
return v.Len() == 0
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------
|
|
||||||
|
|
||||||
// atomicTypeInfoSlice contains length and pointer to the array for a slice.
|
|
||||||
// It is expected to be 2 words.
|
|
||||||
//
|
|
||||||
// Previously, we atomically loaded and stored the length and array pointer separately,
|
|
||||||
// which could lead to some races.
|
|
||||||
// We now just atomically store and load the pointer to the value directly.
|
|
||||||
|
|
||||||
type atomicTypeInfoSlice struct { // expected to be 2 words
|
|
||||||
l int // length of the data array (must be first in struct, for 64-bit alignment necessary for 386)
|
|
||||||
v unsafe.Pointer // data array - Pointer (not uintptr) to maintain GC reference
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *atomicTypeInfoSlice) load() []rtid2ti {
|
|
||||||
xp := unsafe.Pointer(x)
|
|
||||||
x2 := *(*atomicTypeInfoSlice)(atomic.LoadPointer(&xp))
|
|
||||||
if x2.l == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return *(*[]rtid2ti)(unsafe.Pointer(&unsafeSlice{Data: x2.v, Len: x2.l, Cap: x2.l}))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *atomicTypeInfoSlice) store(p []rtid2ti) {
|
|
||||||
s := (*unsafeSlice)(unsafe.Pointer(&p))
|
|
||||||
xp := unsafe.Pointer(x)
|
|
||||||
atomic.StorePointer(&xp, unsafe.Pointer(&atomicTypeInfoSlice{l: s.Len, v: s.Data}))
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------
|
|
||||||
func (d *Decoder) raw(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
*(*[]byte)(urv.ptr) = d.rawBytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kString(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
*(*string)(urv.ptr) = d.d.DecodeString()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kBool(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
*(*bool)(urv.ptr) = d.d.DecodeBool()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kTime(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
*(*time.Time)(urv.ptr) = d.d.DecodeTime()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
fv := d.d.DecodeFloat64()
|
|
||||||
if chkOvf.Float32(fv) {
|
|
||||||
d.errorf("float32 overflow: %v", fv)
|
|
||||||
}
|
|
||||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
*(*float32)(urv.ptr) = float32(fv)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kFloat64(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
*(*float64)(urv.ptr) = d.d.DecodeFloat64()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kInt(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
*(*int)(urv.ptr) = int(chkOvf.IntV(d.d.DecodeInt64(), intBitsize))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kInt8(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
*(*int8)(urv.ptr) = int8(chkOvf.IntV(d.d.DecodeInt64(), 8))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kInt16(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
*(*int16)(urv.ptr) = int16(chkOvf.IntV(d.d.DecodeInt64(), 16))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kInt32(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
*(*int32)(urv.ptr) = int32(chkOvf.IntV(d.d.DecodeInt64(), 32))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kInt64(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
*(*int64)(urv.ptr) = d.d.DecodeInt64()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kUint(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
*(*uint)(urv.ptr) = uint(chkOvf.UintV(d.d.DecodeUint64(), uintBitsize))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kUintptr(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
*(*uintptr)(urv.ptr) = uintptr(chkOvf.UintV(d.d.DecodeUint64(), uintBitsize))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kUint8(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
*(*uint8)(urv.ptr) = uint8(chkOvf.UintV(d.d.DecodeUint64(), 8))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kUint16(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
*(*uint16)(urv.ptr) = uint16(chkOvf.UintV(d.d.DecodeUint64(), 16))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kUint32(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
*(*uint32)(urv.ptr) = uint32(chkOvf.UintV(d.d.DecodeUint64(), 32))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Decoder) kUint64(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
*(*uint64)(urv.ptr) = d.d.DecodeUint64()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------
|
|
||||||
|
|
||||||
func (e *Encoder) kBool(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
e.e.EncodeBool(*(*bool)(v.ptr))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kTime(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
e.e.EncodeTime(*(*time.Time)(v.ptr))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kString(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
e.e.EncodeString(cUTF8, *(*string)(v.ptr))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kFloat64(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
e.e.EncodeFloat64(*(*float64)(v.ptr))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
e.e.EncodeFloat32(*(*float32)(v.ptr))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kInt(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
e.e.EncodeInt(int64(*(*int)(v.ptr)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kInt8(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
e.e.EncodeInt(int64(*(*int8)(v.ptr)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kInt16(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
e.e.EncodeInt(int64(*(*int16)(v.ptr)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kInt32(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
e.e.EncodeInt(int64(*(*int32)(v.ptr)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kInt64(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
e.e.EncodeInt(int64(*(*int64)(v.ptr)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kUint(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
e.e.EncodeUint(uint64(*(*uint)(v.ptr)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kUint8(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
e.e.EncodeUint(uint64(*(*uint8)(v.ptr)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kUint16(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
e.e.EncodeUint(uint64(*(*uint16)(v.ptr)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kUint32(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
e.e.EncodeUint(uint64(*(*uint32)(v.ptr)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kUint64(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
e.e.EncodeUint(uint64(*(*uint64)(v.ptr)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Encoder) kUintptr(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
e.e.EncodeUint(uint64(*(*uintptr)(v.ptr)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------
|
|
||||||
|
|
||||||
// func (d *Decoder) raw(f *codecFnInfo, rv reflect.Value) {
|
|
||||||
// urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
// // if urv.flag&unsafeFlagIndir != 0 {
|
|
||||||
// // urv.ptr = *(*unsafe.Pointer)(urv.ptr)
|
|
||||||
// // }
|
|
||||||
// *(*[]byte)(urv.ptr) = d.rawBytes()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func rv0t(rt reflect.Type) reflect.Value {
|
|
||||||
// ut := (*unsafeIntf)(unsafe.Pointer(&rt))
|
|
||||||
// // we need to determine whether ifaceIndir, and then whether to just pass 0 as the ptr
|
|
||||||
// uv := unsafeReflectValue{ut.word, &zeroRTv, flag(rt.Kind())}
|
|
||||||
// return *(*reflect.Value)(unsafe.Pointer(&uv})
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func rv2i(rv reflect.Value) interface{} {
|
|
||||||
// urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
// // true references (map, func, chan, ptr - NOT slice) may be double-referenced as flagIndir
|
|
||||||
// var ptr unsafe.Pointer
|
|
||||||
// // kk := reflect.Kind(urv.flag & (1<<5 - 1))
|
|
||||||
// // if (kk == reflect.Map || kk == reflect.Ptr || kk == reflect.Chan || kk == reflect.Func) && urv.flag&unsafeFlagIndir != 0 {
|
|
||||||
// if refBitset.isset(byte(urv.flag&(1<<5-1))) && urv.flag&unsafeFlagIndir != 0 {
|
|
||||||
// ptr = *(*unsafe.Pointer)(urv.ptr)
|
|
||||||
// } else {
|
|
||||||
// ptr = urv.ptr
|
|
||||||
// }
|
|
||||||
// return *(*interface{})(unsafe.Pointer(&unsafeIntf{typ: urv.typ, word: ptr}))
|
|
||||||
// // return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
|
|
||||||
// // return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func definitelyNil(v interface{}) bool {
|
|
||||||
// var ui *unsafeIntf = (*unsafeIntf)(unsafe.Pointer(&v))
|
|
||||||
// if ui.word == nil {
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
// var tk = reflect.TypeOf(v).Kind()
|
|
||||||
// return (tk == reflect.Interface || tk == reflect.Slice) && *(*unsafe.Pointer)(ui.word) == nil
|
|
||||||
// fmt.Printf(">>>> definitely nil: isnil: %v, TYPE: \t%T, word: %v, *word: %v, type: %v, nil: %v\n",
|
|
||||||
// v == nil, v, word, *((*unsafe.Pointer)(word)), ui.typ, nil)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func keepAlive4BytesView(v string) {
|
|
||||||
// runtime.KeepAlive(v)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func keepAlive4StringView(v []byte) {
|
|
||||||
// runtime.KeepAlive(v)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func rt2id(rt reflect.Type) uintptr {
|
|
||||||
// return uintptr(((*unsafeIntf)(unsafe.Pointer(&rt))).word)
|
|
||||||
// // var i interface{} = rt
|
|
||||||
// // // ui := (*unsafeIntf)(unsafe.Pointer(&i))
|
|
||||||
// // return ((*unsafeIntf)(unsafe.Pointer(&i))).word
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func rv2i(rv reflect.Value) interface{} {
|
|
||||||
// urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
// // non-reference type: already indir
|
|
||||||
// // reference type: depend on flagIndir property ('cos maybe was double-referenced)
|
|
||||||
// // const (unsafeRvFlagKindMask = 1<<5 - 1 , unsafeRvFlagIndir = 1 << 7 )
|
|
||||||
// // rvk := reflect.Kind(urv.flag & (1<<5 - 1))
|
|
||||||
// // if (rvk == reflect.Chan ||
|
|
||||||
// // rvk == reflect.Func ||
|
|
||||||
// // rvk == reflect.Interface ||
|
|
||||||
// // rvk == reflect.Map ||
|
|
||||||
// // rvk == reflect.Ptr ||
|
|
||||||
// // rvk == reflect.UnsafePointer) && urv.flag&(1<<8) != 0 {
|
|
||||||
// // fmt.Printf(">>>>> ---- double indirect reference: %v, %v\n", rvk, rv.Type())
|
|
||||||
// // return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
|
|
||||||
// // }
|
|
||||||
// if urv.flag&(1<<5-1) == uintptr(reflect.Map) && urv.flag&(1<<7) != 0 {
|
|
||||||
// // fmt.Printf(">>>>> ---- double indirect reference: %v, %v\n", rvk, rv.Type())
|
|
||||||
// return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
|
|
||||||
// }
|
|
||||||
// // fmt.Printf(">>>>> ++++ direct reference: %v, %v\n", rvk, rv.Type())
|
|
||||||
// return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const (
|
|
||||||
// unsafeRvFlagKindMask = 1<<5 - 1
|
|
||||||
// unsafeRvKindDirectIface = 1 << 5
|
|
||||||
// unsafeRvFlagIndir = 1 << 7
|
|
||||||
// unsafeRvFlagAddr = 1 << 8
|
|
||||||
// unsafeRvFlagMethod = 1 << 9
|
|
||||||
|
|
||||||
// _USE_RV_INTERFACE bool = false
|
|
||||||
// _UNSAFE_RV_DEBUG = true
|
|
||||||
// )
|
|
||||||
|
|
||||||
// type unsafeRtype struct {
|
|
||||||
// _ [2]uintptr
|
|
||||||
// _ uint32
|
|
||||||
// _ uint8
|
|
||||||
// _ uint8
|
|
||||||
// _ uint8
|
|
||||||
// kind uint8
|
|
||||||
// _ [2]uintptr
|
|
||||||
// _ int32
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func _rv2i(rv reflect.Value) interface{} {
|
|
||||||
// // Note: From use,
|
|
||||||
// // - it's never an interface
|
|
||||||
// // - the only calls here are for ifaceIndir types.
|
|
||||||
// // (though that conditional is wrong)
|
|
||||||
// // To know for sure, we need the value of t.kind (which is not exposed).
|
|
||||||
// //
|
|
||||||
// // Need to validate the path: type is indirect ==> only value is indirect ==> default (value is direct)
|
|
||||||
// // - Type indirect, Value indirect: ==> numbers, boolean, slice, struct, array, string
|
|
||||||
// // - Type Direct, Value indirect: ==> map???
|
|
||||||
// // - Type Direct, Value direct: ==> pointers, unsafe.Pointer, func, chan, map
|
|
||||||
// //
|
|
||||||
// // TRANSLATES TO:
|
|
||||||
// // if typeIndirect { } else if valueIndirect { } else { }
|
|
||||||
// //
|
|
||||||
// // Since we don't deal with funcs, then "flagNethod" is unset, and can be ignored.
|
|
||||||
|
|
||||||
// if _USE_RV_INTERFACE {
|
|
||||||
// return rv.Interface()
|
|
||||||
// }
|
|
||||||
// urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
|
|
||||||
// // if urv.flag&unsafeRvFlagMethod != 0 || urv.flag&unsafeRvFlagKindMask == uintptr(reflect.Interface) {
|
|
||||||
// // println("***** IS flag method or interface: delegating to rv.Interface()")
|
|
||||||
// // return rv.Interface()
|
|
||||||
// // }
|
|
||||||
|
|
||||||
// // if urv.flag&unsafeRvFlagKindMask == uintptr(reflect.Interface) {
|
|
||||||
// // println("***** IS Interface: delegate to rv.Interface")
|
|
||||||
// // return rv.Interface()
|
|
||||||
// // }
|
|
||||||
// // if urv.flag&unsafeRvFlagKindMask&unsafeRvKindDirectIface == 0 {
|
|
||||||
// // if urv.flag&unsafeRvFlagAddr == 0 {
|
|
||||||
// // println("***** IS ifaceIndir typ")
|
|
||||||
// // // ui := unsafeIntf{word: urv.ptr, typ: urv.typ}
|
|
||||||
// // // return *(*interface{})(unsafe.Pointer(&ui))
|
|
||||||
// // // return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
|
|
||||||
// // }
|
|
||||||
// // } else if urv.flag&unsafeRvFlagIndir != 0 {
|
|
||||||
// // println("***** IS flagindir")
|
|
||||||
// // // return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
|
|
||||||
// // } else {
|
|
||||||
// // println("***** NOT flagindir")
|
|
||||||
// // return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
|
|
||||||
// // }
|
|
||||||
// // println("***** default: delegate to rv.Interface")
|
|
||||||
|
|
||||||
// urt := (*unsafeRtype)(unsafe.Pointer(urv.typ))
|
|
||||||
// if _UNSAFE_RV_DEBUG {
|
|
||||||
// fmt.Printf(">>>> start: %v: ", rv.Type())
|
|
||||||
// fmt.Printf("%v - %v\n", *urv, *urt)
|
|
||||||
// }
|
|
||||||
// if urt.kind&unsafeRvKindDirectIface == 0 {
|
|
||||||
// if _UNSAFE_RV_DEBUG {
|
|
||||||
// fmt.Printf("**** +ifaceIndir type: %v\n", rv.Type())
|
|
||||||
// }
|
|
||||||
// // println("***** IS ifaceIndir typ")
|
|
||||||
// // if true || urv.flag&unsafeRvFlagAddr == 0 {
|
|
||||||
// // // println(" ***** IS NOT addr")
|
|
||||||
// return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
|
|
||||||
// // }
|
|
||||||
// } else if urv.flag&unsafeRvFlagIndir != 0 {
|
|
||||||
// if _UNSAFE_RV_DEBUG {
|
|
||||||
// fmt.Printf("**** +flagIndir type: %v\n", rv.Type())
|
|
||||||
// }
|
|
||||||
// // println("***** IS flagindir")
|
|
||||||
// return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
|
|
||||||
// } else {
|
|
||||||
// if _UNSAFE_RV_DEBUG {
|
|
||||||
// fmt.Printf("**** -flagIndir type: %v\n", rv.Type())
|
|
||||||
// }
|
|
||||||
// // println("***** NOT flagindir")
|
|
||||||
// return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
|
|
||||||
// }
|
|
||||||
// // println("***** default: delegating to rv.Interface()")
|
|
||||||
// // return rv.Interface()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// var staticM0 = make(map[string]uint64)
|
|
||||||
// var staticI0 = (int32)(-5)
|
|
||||||
|
|
||||||
// func staticRv2iTest() {
|
|
||||||
// i0 := (int32)(-5)
|
|
||||||
// m0 := make(map[string]uint16)
|
|
||||||
// m0["1"] = 1
|
|
||||||
// for _, i := range []interface{}{
|
|
||||||
// (int)(7),
|
|
||||||
// (uint)(8),
|
|
||||||
// (int16)(-9),
|
|
||||||
// (uint16)(19),
|
|
||||||
// (uintptr)(77),
|
|
||||||
// (bool)(true),
|
|
||||||
// float32(-32.7),
|
|
||||||
// float64(64.9),
|
|
||||||
// complex(float32(19), 5),
|
|
||||||
// complex(float64(-32), 7),
|
|
||||||
// [4]uint64{1, 2, 3, 4},
|
|
||||||
// (chan<- int)(nil), // chan,
|
|
||||||
// rv2i, // func
|
|
||||||
// io.Writer(ioutil.Discard),
|
|
||||||
// make(map[string]uint),
|
|
||||||
// (map[string]uint)(nil),
|
|
||||||
// staticM0,
|
|
||||||
// m0,
|
|
||||||
// &m0,
|
|
||||||
// i0,
|
|
||||||
// &i0,
|
|
||||||
// &staticI0,
|
|
||||||
// &staticM0,
|
|
||||||
// []uint32{6, 7, 8},
|
|
||||||
// "abc",
|
|
||||||
// Raw{},
|
|
||||||
// RawExt{},
|
|
||||||
// &Raw{},
|
|
||||||
// &RawExt{},
|
|
||||||
// unsafe.Pointer(&i0),
|
|
||||||
// } {
|
|
||||||
// i2 := rv2i(reflect.ValueOf(i))
|
|
||||||
// eq := reflect.DeepEqual(i, i2)
|
|
||||||
// fmt.Printf(">>>> %v == %v? %v\n", i, i2, eq)
|
|
||||||
// }
|
|
||||||
// // os.Exit(0)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func init() {
|
|
||||||
// staticRv2iTest()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func rv2i(rv reflect.Value) interface{} {
|
|
||||||
// if _USE_RV_INTERFACE || rv.Kind() == reflect.Interface || rv.CanAddr() {
|
|
||||||
// return rv.Interface()
|
|
||||||
// }
|
|
||||||
// // var i interface{}
|
|
||||||
// // ui := (*unsafeIntf)(unsafe.Pointer(&i))
|
|
||||||
// var ui unsafeIntf
|
|
||||||
// urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
|
|
||||||
// // fmt.Printf("urv: flag: %b, typ: %b, ptr: %b\n", urv.flag, uintptr(urv.typ), uintptr(urv.ptr))
|
|
||||||
// if (urv.flag&unsafeRvFlagKindMask)&unsafeRvKindDirectIface == 0 {
|
|
||||||
// if urv.flag&unsafeRvFlagAddr != 0 {
|
|
||||||
// println("***** indirect and addressable! Needs typed move - delegate to rv.Interface()")
|
|
||||||
// return rv.Interface()
|
|
||||||
// }
|
|
||||||
// println("****** indirect type/kind")
|
|
||||||
// ui.word = urv.ptr
|
|
||||||
// } else if urv.flag&unsafeRvFlagIndir != 0 {
|
|
||||||
// println("****** unsafe rv flag indir")
|
|
||||||
// ui.word = *(*unsafe.Pointer)(urv.ptr)
|
|
||||||
// } else {
|
|
||||||
// println("****** default: assign prt to word directly")
|
|
||||||
// ui.word = urv.ptr
|
|
||||||
// }
|
|
||||||
// // ui.word = urv.ptr
|
|
||||||
// ui.typ = urv.typ
|
|
||||||
// // fmt.Printf("(pointers) ui.typ: %p, word: %p\n", ui.typ, ui.word)
|
|
||||||
// // fmt.Printf("(binary) ui.typ: %b, word: %b\n", uintptr(ui.typ), uintptr(ui.word))
|
|
||||||
// return *(*interface{})(unsafe.Pointer(&ui))
|
|
||||||
// // return i
|
|
||||||
// }
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,154 +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.
|
|
||||||
|
|
||||||
// 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 }}
|
|
||||||
{{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 }}
|
|
||||||
v{{$i}}v1 = v
|
|
||||||
bs{{$i}} := testMarshalErr(v{{$i}}v1, h, t, "enc-slice-v{{$i}}")
|
|
||||||
if v == nil { v{{$i}}v2 = nil } 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}}")
|
|
||||||
if v == nil { v{{$i}}v2 = nil } else { 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")
|
|
||||||
// ...
|
|
||||||
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
|
|
||||||
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")
|
|
||||||
}
|
|
||||||
// ...
|
|
||||||
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)
|
|
||||||
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")
|
|
||||||
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")
|
|
||||||
}
|
|
||||||
{{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 }}
|
|
||||||
v{{$i}}v1 = v
|
|
||||||
bs{{$i}} := testMarshalErr(v{{$i}}v1, h, t, "enc-map-v{{$i}}")
|
|
||||||
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")
|
|
||||||
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")
|
|
||||||
// ...
|
|
||||||
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)
|
|
||||||
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")
|
|
||||||
}
|
|
||||||
{{end}}{{end}}{{end}}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func doTestMammothMapsAndSlices(t *testing.T, h Handle) {
|
|
||||||
doTestMammothSlices(t, h)
|
|
||||||
doTestMammothMaps(t, h)
|
|
||||||
}
|
|
|
@ -1,94 +0,0 @@
|
||||||
// +build !notfastpath
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
bigen.PutUint64(data, uint64(x))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
func (x *testMammoth2Binary) UnmarshalBinary(data []byte) (err error) {
|
|
||||||
*x = testMammoth2Binary(bigen.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
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
|
// 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.
|
// Use of this source code is governed by a MIT license found in the LICENSE file.
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -15,8 +15,8 @@ For compatibility with behaviour of msgpack-c reference implementation:
|
||||||
- Go intX (<0)
|
- Go intX (<0)
|
||||||
IS ENCODED AS
|
IS ENCODED AS
|
||||||
msgpack -ve fixnum, signed
|
msgpack -ve fixnum, signed
|
||||||
*/
|
|
||||||
|
|
||||||
|
*/
|
||||||
package codec
|
package codec
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -25,7 +25,6 @@ import (
|
||||||
"math"
|
"math"
|
||||||
"net/rpc"
|
"net/rpc"
|
||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -79,89 +78,6 @@ const (
|
||||||
mpNegFixNumMax = 0xff
|
mpNegFixNumMax = 0xff
|
||||||
)
|
)
|
||||||
|
|
||||||
var mpTimeExtTag int8 = -1
|
|
||||||
var mpTimeExtTagU = uint8(mpTimeExtTag)
|
|
||||||
|
|
||||||
// var mpdesc = map[byte]string{
|
|
||||||
// mpPosFixNumMin: "PosFixNumMin",
|
|
||||||
// mpPosFixNumMax: "PosFixNumMax",
|
|
||||||
// mpFixMapMin: "FixMapMin",
|
|
||||||
// mpFixMapMax: "FixMapMax",
|
|
||||||
// mpFixArrayMin: "FixArrayMin",
|
|
||||||
// mpFixArrayMax: "FixArrayMax",
|
|
||||||
// mpFixStrMin: "FixStrMin",
|
|
||||||
// mpFixStrMax: "FixStrMax",
|
|
||||||
// mpNil: "Nil",
|
|
||||||
// mpFalse: "False",
|
|
||||||
// mpTrue: "True",
|
|
||||||
// mpFloat: "Float",
|
|
||||||
// mpDouble: "Double",
|
|
||||||
// mpUint8: "Uint8",
|
|
||||||
// mpUint16: "Uint16",
|
|
||||||
// mpUint32: "Uint32",
|
|
||||||
// mpUint64: "Uint64",
|
|
||||||
// mpInt8: "Int8",
|
|
||||||
// mpInt16: "Int16",
|
|
||||||
// mpInt32: "Int32",
|
|
||||||
// mpInt64: "Int64",
|
|
||||||
// mpBin8: "Bin8",
|
|
||||||
// mpBin16: "Bin16",
|
|
||||||
// mpBin32: "Bin32",
|
|
||||||
// mpExt8: "Ext8",
|
|
||||||
// mpExt16: "Ext16",
|
|
||||||
// mpExt32: "Ext32",
|
|
||||||
// mpFixExt1: "FixExt1",
|
|
||||||
// mpFixExt2: "FixExt2",
|
|
||||||
// mpFixExt4: "FixExt4",
|
|
||||||
// mpFixExt8: "FixExt8",
|
|
||||||
// mpFixExt16: "FixExt16",
|
|
||||||
// mpStr8: "Str8",
|
|
||||||
// mpStr16: "Str16",
|
|
||||||
// mpStr32: "Str32",
|
|
||||||
// mpArray16: "Array16",
|
|
||||||
// mpArray32: "Array32",
|
|
||||||
// mpMap16: "Map16",
|
|
||||||
// mpMap32: "Map32",
|
|
||||||
// mpNegFixNumMin: "NegFixNumMin",
|
|
||||||
// mpNegFixNumMax: "NegFixNumMax",
|
|
||||||
// }
|
|
||||||
|
|
||||||
func mpdesc(bd byte) string {
|
|
||||||
switch bd {
|
|
||||||
case mpNil:
|
|
||||||
return "nil"
|
|
||||||
case mpFalse:
|
|
||||||
return "false"
|
|
||||||
case mpTrue:
|
|
||||||
return "true"
|
|
||||||
case mpFloat, mpDouble:
|
|
||||||
return "float"
|
|
||||||
case mpUint8, mpUint16, mpUint32, mpUint64:
|
|
||||||
return "uint"
|
|
||||||
case mpInt8, mpInt16, mpInt32, mpInt64:
|
|
||||||
return "int"
|
|
||||||
default:
|
|
||||||
switch {
|
|
||||||
case bd >= mpPosFixNumMin && bd <= mpPosFixNumMax:
|
|
||||||
return "int"
|
|
||||||
case bd >= mpNegFixNumMin && bd <= mpNegFixNumMax:
|
|
||||||
return "int"
|
|
||||||
case bd == mpStr8, bd == mpStr16, bd == mpStr32, bd >= mpFixStrMin && bd <= mpFixStrMax:
|
|
||||||
return "string|bytes"
|
|
||||||
case bd == mpBin8, bd == mpBin16, bd == mpBin32:
|
|
||||||
return "bytes"
|
|
||||||
case bd == mpArray16, bd == mpArray32, bd >= mpFixArrayMin && bd <= mpFixArrayMax:
|
|
||||||
return "array"
|
|
||||||
case bd == mpMap16, bd == mpMap32, bd >= mpFixMapMin && bd <= mpFixMapMax:
|
|
||||||
return "map"
|
|
||||||
case bd >= mpFixExt1 && bd <= mpFixExt16, bd >= mpExt8 && bd <= mpExt32:
|
|
||||||
return "ext"
|
|
||||||
default:
|
|
||||||
return "unknown"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MsgpackSpecRpcMultiArgs is a special type which signifies to the MsgpackSpecRpcCodec
|
// MsgpackSpecRpcMultiArgs is a special type which signifies to the MsgpackSpecRpcCodec
|
||||||
// that the backend RPC service takes multiple arguments, which have been arranged
|
// that the backend RPC service takes multiple arguments, which have been arranged
|
||||||
// in sequence in the slice.
|
// in sequence in the slice.
|
||||||
|
@ -178,31 +94,21 @@ type msgpackContainerType struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
msgpackContainerStr = msgpackContainerType{
|
msgpackContainerStr = msgpackContainerType{32, mpFixStrMin, mpStr8, mpStr16, mpStr32, true, true, false}
|
||||||
32, mpFixStrMin, mpStr8, mpStr16, mpStr32, true, true, false,
|
msgpackContainerBin = msgpackContainerType{0, 0, mpBin8, mpBin16, mpBin32, false, true, true}
|
||||||
}
|
msgpackContainerList = msgpackContainerType{16, mpFixArrayMin, 0, mpArray16, mpArray32, true, false, false}
|
||||||
msgpackContainerBin = msgpackContainerType{
|
msgpackContainerMap = msgpackContainerType{16, mpFixMapMin, 0, mpMap16, mpMap32, true, false, false}
|
||||||
0, 0, mpBin8, mpBin16, mpBin32, false, true, true,
|
|
||||||
}
|
|
||||||
msgpackContainerList = msgpackContainerType{
|
|
||||||
16, mpFixArrayMin, 0, mpArray16, mpArray32, true, false, false,
|
|
||||||
}
|
|
||||||
msgpackContainerMap = msgpackContainerType{
|
|
||||||
16, mpFixMapMin, 0, mpMap16, mpMap32, true, false, false,
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//---------------------------------------------
|
//---------------------------------------------
|
||||||
|
|
||||||
type msgpackEncDriver struct {
|
type msgpackEncDriver struct {
|
||||||
noBuiltInTypes
|
noBuiltInTypes
|
||||||
encDriverNoopContainerWriter
|
encNoSeparator
|
||||||
// encNoSeparator
|
|
||||||
e *Encoder
|
e *Encoder
|
||||||
w encWriter
|
w encWriter
|
||||||
h *MsgpackHandle
|
h *MsgpackHandle
|
||||||
x [8]byte
|
x [8]byte
|
||||||
// _ [3]uint64 // padding
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *msgpackEncDriver) EncodeNil() {
|
func (e *msgpackEncDriver) EncodeNil() {
|
||||||
|
@ -210,25 +116,10 @@ func (e *msgpackEncDriver) EncodeNil() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *msgpackEncDriver) EncodeInt(i int64) {
|
func (e *msgpackEncDriver) EncodeInt(i int64) {
|
||||||
if e.h.PositiveIntUnsigned && i >= 0 {
|
if i >= 0 {
|
||||||
e.EncodeUint(uint64(i))
|
e.EncodeUint(uint64(i))
|
||||||
} else if i > math.MaxInt8 {
|
|
||||||
if i <= math.MaxInt16 {
|
|
||||||
e.w.writen1(mpInt16)
|
|
||||||
bigenHelper{e.x[:2], e.w}.writeUint16(uint16(i))
|
|
||||||
} else if i <= math.MaxInt32 {
|
|
||||||
e.w.writen1(mpInt32)
|
|
||||||
bigenHelper{e.x[:4], e.w}.writeUint32(uint32(i))
|
|
||||||
} else {
|
|
||||||
e.w.writen1(mpInt64)
|
|
||||||
bigenHelper{e.x[:8], e.w}.writeUint64(uint64(i))
|
|
||||||
}
|
|
||||||
} else if i >= -32 {
|
} else if i >= -32 {
|
||||||
if e.h.NoFixedNum {
|
e.w.writen1(byte(i))
|
||||||
e.w.writen2(mpInt8, byte(i))
|
|
||||||
} else {
|
|
||||||
e.w.writen1(byte(i))
|
|
||||||
}
|
|
||||||
} else if i >= math.MinInt8 {
|
} else if i >= math.MinInt8 {
|
||||||
e.w.writen2(mpInt8, byte(i))
|
e.w.writen2(mpInt8, byte(i))
|
||||||
} else if i >= math.MinInt16 {
|
} else if i >= math.MinInt16 {
|
||||||
|
@ -245,11 +136,7 @@ func (e *msgpackEncDriver) EncodeInt(i int64) {
|
||||||
|
|
||||||
func (e *msgpackEncDriver) EncodeUint(i uint64) {
|
func (e *msgpackEncDriver) EncodeUint(i uint64) {
|
||||||
if i <= math.MaxInt8 {
|
if i <= math.MaxInt8 {
|
||||||
if e.h.NoFixedNum {
|
e.w.writen1(byte(i))
|
||||||
e.w.writen2(mpUint8, byte(i))
|
|
||||||
} else {
|
|
||||||
e.w.writen1(byte(i))
|
|
||||||
}
|
|
||||||
} else if i <= math.MaxUint8 {
|
} else if i <= math.MaxUint8 {
|
||||||
e.w.writen2(mpUint8, byte(i))
|
e.w.writen2(mpUint8, byte(i))
|
||||||
} else if i <= math.MaxUint16 {
|
} else if i <= math.MaxUint16 {
|
||||||
|
@ -282,39 +169,6 @@ func (e *msgpackEncDriver) EncodeFloat64(f float64) {
|
||||||
bigenHelper{e.x[:8], e.w}.writeUint64(math.Float64bits(f))
|
bigenHelper{e.x[:8], e.w}.writeUint64(math.Float64bits(f))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *msgpackEncDriver) EncodeTime(t time.Time) {
|
|
||||||
if t.IsZero() {
|
|
||||||
e.EncodeNil()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t = t.UTC()
|
|
||||||
sec, nsec := t.Unix(), uint64(t.Nanosecond())
|
|
||||||
var data64 uint64
|
|
||||||
var l = 4
|
|
||||||
if sec >= 0 && sec>>34 == 0 {
|
|
||||||
data64 = (nsec << 34) | uint64(sec)
|
|
||||||
if data64&0xffffffff00000000 != 0 {
|
|
||||||
l = 8
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
l = 12
|
|
||||||
}
|
|
||||||
if e.h.WriteExt {
|
|
||||||
e.encodeExtPreamble(mpTimeExtTagU, l)
|
|
||||||
} else {
|
|
||||||
e.writeContainerLen(msgpackContainerStr, l)
|
|
||||||
}
|
|
||||||
switch l {
|
|
||||||
case 4:
|
|
||||||
bigenHelper{e.x[:4], e.w}.writeUint32(uint32(data64))
|
|
||||||
case 8:
|
|
||||||
bigenHelper{e.x[:8], e.w}.writeUint64(data64)
|
|
||||||
case 12:
|
|
||||||
bigenHelper{e.x[:4], e.w}.writeUint32(uint32(nsec))
|
|
||||||
bigenHelper{e.x[:8], e.w}.writeUint64(uint64(sec))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *msgpackEncDriver) EncodeExt(v interface{}, xtag uint64, ext Ext, _ *Encoder) {
|
func (e *msgpackEncDriver) EncodeExt(v interface{}, xtag uint64, ext Ext, _ *Encoder) {
|
||||||
bs := ext.WriteExt(v)
|
bs := ext.WriteExt(v)
|
||||||
if bs == nil {
|
if bs == nil {
|
||||||
|
@ -325,7 +179,7 @@ func (e *msgpackEncDriver) EncodeExt(v interface{}, xtag uint64, ext Ext, _ *Enc
|
||||||
e.encodeExtPreamble(uint8(xtag), len(bs))
|
e.encodeExtPreamble(uint8(xtag), len(bs))
|
||||||
e.w.writeb(bs)
|
e.w.writeb(bs)
|
||||||
} else {
|
} else {
|
||||||
e.EncodeStringBytes(cRAW, bs)
|
e.EncodeStringBytes(c_RAW, bs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,38 +213,36 @@ func (e *msgpackEncDriver) encodeExtPreamble(xtag byte, l int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *msgpackEncDriver) WriteArrayStart(length int) {
|
func (e *msgpackEncDriver) EncodeArrayStart(length int) {
|
||||||
e.writeContainerLen(msgpackContainerList, length)
|
e.writeContainerLen(msgpackContainerList, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *msgpackEncDriver) WriteMapStart(length int) {
|
func (e *msgpackEncDriver) EncodeMapStart(length int) {
|
||||||
e.writeContainerLen(msgpackContainerMap, length)
|
e.writeContainerLen(msgpackContainerMap, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *msgpackEncDriver) EncodeString(c charEncoding, s string) {
|
func (e *msgpackEncDriver) EncodeString(c charEncoding, s string) {
|
||||||
slen := len(s)
|
if c == c_RAW && e.h.WriteExt {
|
||||||
if c == cRAW && e.h.WriteExt {
|
e.writeContainerLen(msgpackContainerBin, len(s))
|
||||||
e.writeContainerLen(msgpackContainerBin, slen)
|
|
||||||
} else {
|
} else {
|
||||||
e.writeContainerLen(msgpackContainerStr, slen)
|
e.writeContainerLen(msgpackContainerStr, len(s))
|
||||||
}
|
}
|
||||||
if slen > 0 {
|
if len(s) > 0 {
|
||||||
e.w.writestr(s)
|
e.w.writestr(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *msgpackEncDriver) EncodeSymbol(v string) {
|
||||||
|
e.EncodeString(c_UTF8, v)
|
||||||
|
}
|
||||||
|
|
||||||
func (e *msgpackEncDriver) EncodeStringBytes(c charEncoding, bs []byte) {
|
func (e *msgpackEncDriver) EncodeStringBytes(c charEncoding, bs []byte) {
|
||||||
if bs == nil {
|
if c == c_RAW && e.h.WriteExt {
|
||||||
e.EncodeNil()
|
e.writeContainerLen(msgpackContainerBin, len(bs))
|
||||||
return
|
|
||||||
}
|
|
||||||
slen := len(bs)
|
|
||||||
if c == cRAW && e.h.WriteExt {
|
|
||||||
e.writeContainerLen(msgpackContainerBin, slen)
|
|
||||||
} else {
|
} else {
|
||||||
e.writeContainerLen(msgpackContainerStr, slen)
|
e.writeContainerLen(msgpackContainerStr, len(bs))
|
||||||
}
|
}
|
||||||
if slen > 0 {
|
if len(bs) > 0 {
|
||||||
e.w.writeb(bs)
|
e.w.writeb(bs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -412,18 +264,16 @@ func (e *msgpackEncDriver) writeContainerLen(ct msgpackContainerType, l int) {
|
||||||
//---------------------------------------------
|
//---------------------------------------------
|
||||||
|
|
||||||
type msgpackDecDriver struct {
|
type msgpackDecDriver struct {
|
||||||
d *Decoder
|
d *Decoder
|
||||||
r decReader
|
r decReader // *Decoder decReader decReaderT
|
||||||
h *MsgpackHandle
|
h *MsgpackHandle
|
||||||
// b [scratchByteArrayLen]byte
|
b [scratchByteArrayLen]byte
|
||||||
bd byte
|
bd byte
|
||||||
bdRead bool
|
bdRead bool
|
||||||
br bool // bytes reader
|
br bool // bytes reader
|
||||||
noBuiltInTypes
|
noBuiltInTypes
|
||||||
// noStreamingCodec
|
noStreamingCodec
|
||||||
// decNoSeparator
|
decNoSeparator
|
||||||
decDriverNoopContainerReader
|
|
||||||
// _ [3]uint64 // padding
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: This returns either a primitive (int, bool, etc) for non-containers,
|
// Note: This returns either a primitive (int, bool, etc) for non-containers,
|
||||||
|
@ -436,7 +286,7 @@ func (d *msgpackDecDriver) DecodeNaked() {
|
||||||
d.readNextBd()
|
d.readNextBd()
|
||||||
}
|
}
|
||||||
bd := d.bd
|
bd := d.bd
|
||||||
n := d.d.n
|
n := &d.d.n
|
||||||
var decodeFurther bool
|
var decodeFurther bool
|
||||||
|
|
||||||
switch bd {
|
switch bd {
|
||||||
|
@ -499,11 +349,11 @@ func (d *msgpackDecDriver) DecodeNaked() {
|
||||||
n.s = d.DecodeString()
|
n.s = d.DecodeString()
|
||||||
} else {
|
} else {
|
||||||
n.v = valueTypeBytes
|
n.v = valueTypeBytes
|
||||||
n.l = d.DecodeBytes(nil, false)
|
n.l = d.DecodeBytes(nil, false, false)
|
||||||
}
|
}
|
||||||
case bd == mpBin8, bd == mpBin16, bd == mpBin32:
|
case bd == mpBin8, bd == mpBin16, bd == mpBin32:
|
||||||
n.v = valueTypeBytes
|
n.v = valueTypeBytes
|
||||||
n.l = d.DecodeBytes(nil, false)
|
n.l = d.DecodeBytes(nil, false, false)
|
||||||
case bd == mpArray16, bd == mpArray32, bd >= mpFixArrayMin && bd <= mpFixArrayMax:
|
case bd == mpArray16, bd == mpArray32, bd >= mpFixArrayMin && bd <= mpFixArrayMax:
|
||||||
n.v = valueTypeArray
|
n.v = valueTypeArray
|
||||||
decodeFurther = true
|
decodeFurther = true
|
||||||
|
@ -514,14 +364,9 @@ func (d *msgpackDecDriver) DecodeNaked() {
|
||||||
n.v = valueTypeExt
|
n.v = valueTypeExt
|
||||||
clen := d.readExtLen()
|
clen := d.readExtLen()
|
||||||
n.u = uint64(d.r.readn1())
|
n.u = uint64(d.r.readn1())
|
||||||
if n.u == uint64(mpTimeExtTagU) {
|
n.l = d.r.readx(clen)
|
||||||
n.v = valueTypeTime
|
|
||||||
n.t = d.decodeTime(clen)
|
|
||||||
} else {
|
|
||||||
n.l = d.r.readx(clen)
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
d.d.errorf("cannot infer value: %s: Ox%x/%d/%s", msgBadDesc, bd, bd, mpdesc(bd))
|
d.d.errorf("Nil-Deciphered DecodeValue: %s: hex: %x, dec: %d", msgBadDesc, bd, bd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !decodeFurther {
|
if !decodeFurther {
|
||||||
|
@ -535,7 +380,7 @@ func (d *msgpackDecDriver) DecodeNaked() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// int can be decoded from msgpack type: intXXX or uintXXX
|
// int can be decoded from msgpack type: intXXX or uintXXX
|
||||||
func (d *msgpackDecDriver) DecodeInt64() (i int64) {
|
func (d *msgpackDecDriver) DecodeInt(bitsize uint8) (i int64) {
|
||||||
if !d.bdRead {
|
if !d.bdRead {
|
||||||
d.readNextBd()
|
d.readNextBd()
|
||||||
}
|
}
|
||||||
|
@ -563,7 +408,14 @@ func (d *msgpackDecDriver) DecodeInt64() (i int64) {
|
||||||
case d.bd >= mpNegFixNumMin && d.bd <= mpNegFixNumMax:
|
case d.bd >= mpNegFixNumMin && d.bd <= mpNegFixNumMax:
|
||||||
i = int64(int8(d.bd))
|
i = int64(int8(d.bd))
|
||||||
default:
|
default:
|
||||||
d.d.errorf("cannot decode signed integer: %s: %x/%s", msgBadDesc, d.bd, mpdesc(d.bd))
|
d.d.errorf("Unhandled single-byte unsigned integer value: %s: %x", msgBadDesc, d.bd)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// check overflow (logic adapted from std pkg reflect/value.go OverflowUint()
|
||||||
|
if bitsize > 0 {
|
||||||
|
if trunc := (i << (64 - bitsize)) >> (64 - bitsize); i != trunc {
|
||||||
|
d.d.errorf("Overflow int value: %v", i)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -572,7 +424,7 @@ func (d *msgpackDecDriver) DecodeInt64() (i int64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// uint can be decoded from msgpack type: intXXX or uintXXX
|
// uint can be decoded from msgpack type: intXXX or uintXXX
|
||||||
func (d *msgpackDecDriver) DecodeUint64() (ui uint64) {
|
func (d *msgpackDecDriver) DecodeUint(bitsize uint8) (ui uint64) {
|
||||||
if !d.bdRead {
|
if !d.bdRead {
|
||||||
d.readNextBd()
|
d.readNextBd()
|
||||||
}
|
}
|
||||||
|
@ -589,28 +441,28 @@ func (d *msgpackDecDriver) DecodeUint64() (ui uint64) {
|
||||||
if i := int64(int8(d.r.readn1())); i >= 0 {
|
if i := int64(int8(d.r.readn1())); i >= 0 {
|
||||||
ui = uint64(i)
|
ui = uint64(i)
|
||||||
} else {
|
} else {
|
||||||
d.d.errorf("assigning negative signed value: %v, to unsigned type", i)
|
d.d.errorf("Assigning negative signed value: %v, to unsigned type", i)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case mpInt16:
|
case mpInt16:
|
||||||
if i := int64(int16(bigen.Uint16(d.r.readx(2)))); i >= 0 {
|
if i := int64(int16(bigen.Uint16(d.r.readx(2)))); i >= 0 {
|
||||||
ui = uint64(i)
|
ui = uint64(i)
|
||||||
} else {
|
} else {
|
||||||
d.d.errorf("assigning negative signed value: %v, to unsigned type", i)
|
d.d.errorf("Assigning negative signed value: %v, to unsigned type", i)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case mpInt32:
|
case mpInt32:
|
||||||
if i := int64(int32(bigen.Uint32(d.r.readx(4)))); i >= 0 {
|
if i := int64(int32(bigen.Uint32(d.r.readx(4)))); i >= 0 {
|
||||||
ui = uint64(i)
|
ui = uint64(i)
|
||||||
} else {
|
} else {
|
||||||
d.d.errorf("assigning negative signed value: %v, to unsigned type", i)
|
d.d.errorf("Assigning negative signed value: %v, to unsigned type", i)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case mpInt64:
|
case mpInt64:
|
||||||
if i := int64(bigen.Uint64(d.r.readx(8))); i >= 0 {
|
if i := int64(bigen.Uint64(d.r.readx(8))); i >= 0 {
|
||||||
ui = uint64(i)
|
ui = uint64(i)
|
||||||
} else {
|
} else {
|
||||||
d.d.errorf("assigning negative signed value: %v, to unsigned type", i)
|
d.d.errorf("Assigning negative signed value: %v, to unsigned type", i)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -618,10 +470,17 @@ func (d *msgpackDecDriver) DecodeUint64() (ui uint64) {
|
||||||
case d.bd >= mpPosFixNumMin && d.bd <= mpPosFixNumMax:
|
case d.bd >= mpPosFixNumMin && d.bd <= mpPosFixNumMax:
|
||||||
ui = uint64(d.bd)
|
ui = uint64(d.bd)
|
||||||
case d.bd >= mpNegFixNumMin && d.bd <= mpNegFixNumMax:
|
case d.bd >= mpNegFixNumMin && d.bd <= mpNegFixNumMax:
|
||||||
d.d.errorf("assigning negative signed value: %v, to unsigned type", int(d.bd))
|
d.d.errorf("Assigning negative signed value: %v, to unsigned type", int(d.bd))
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
d.d.errorf("cannot decode unsigned integer: %s: %x/%s", msgBadDesc, d.bd, mpdesc(d.bd))
|
d.d.errorf("Unhandled single-byte unsigned integer value: %s: %x", msgBadDesc, d.bd)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// check overflow (logic adapted from std pkg reflect/value.go OverflowUint()
|
||||||
|
if bitsize > 0 {
|
||||||
|
if trunc := (ui << (64 - bitsize)) >> (64 - bitsize); ui != trunc {
|
||||||
|
d.d.errorf("Overflow uint value: %v", ui)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -630,7 +489,7 @@ func (d *msgpackDecDriver) DecodeUint64() (ui uint64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// float can either be decoded from msgpack type: float, double or intX
|
// float can either be decoded from msgpack type: float, double or intX
|
||||||
func (d *msgpackDecDriver) DecodeFloat64() (f float64) {
|
func (d *msgpackDecDriver) DecodeFloat(chkOverflow32 bool) (f float64) {
|
||||||
if !d.bdRead {
|
if !d.bdRead {
|
||||||
d.readNextBd()
|
d.readNextBd()
|
||||||
}
|
}
|
||||||
|
@ -639,7 +498,11 @@ func (d *msgpackDecDriver) DecodeFloat64() (f float64) {
|
||||||
} else if d.bd == mpDouble {
|
} else if d.bd == mpDouble {
|
||||||
f = math.Float64frombits(bigen.Uint64(d.r.readx(8)))
|
f = math.Float64frombits(bigen.Uint64(d.r.readx(8)))
|
||||||
} else {
|
} else {
|
||||||
f = float64(d.DecodeInt64())
|
f = float64(d.DecodeInt(0))
|
||||||
|
}
|
||||||
|
if chkOverflow32 && chkOvf.Float32(f) {
|
||||||
|
d.d.errorf("msgpack: float32 overflow: %v", f)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
return
|
return
|
||||||
|
@ -655,45 +518,25 @@ func (d *msgpackDecDriver) DecodeBool() (b bool) {
|
||||||
} else if d.bd == mpTrue || d.bd == 1 {
|
} else if d.bd == mpTrue || d.bd == 1 {
|
||||||
b = true
|
b = true
|
||||||
} else {
|
} else {
|
||||||
d.d.errorf("cannot decode bool: %s: %x/%s", msgBadDesc, d.bd, mpdesc(d.bd))
|
d.d.errorf("Invalid single-byte value for bool: %s: %x", msgBadDesc, d.bd)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *msgpackDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
|
func (d *msgpackDecDriver) DecodeBytes(bs []byte, isstring, zerocopy bool) (bsOut []byte) {
|
||||||
if !d.bdRead {
|
if !d.bdRead {
|
||||||
d.readNextBd()
|
d.readNextBd()
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if an "array" of uint8's (see ContainerType for how to infer if an array)
|
|
||||||
bd := d.bd
|
|
||||||
// DecodeBytes could be from: bin str fixstr fixarray array ...
|
|
||||||
var clen int
|
var clen int
|
||||||
vt := d.ContainerType()
|
// ignore isstring. Expect that the bytes may be found from msgpackContainerStr or msgpackContainerBin
|
||||||
switch vt {
|
if bd := d.bd; bd == mpBin8 || bd == mpBin16 || bd == mpBin32 {
|
||||||
case valueTypeBytes:
|
clen = d.readContainerLen(msgpackContainerBin)
|
||||||
// valueTypeBytes may be a mpBin or an mpStr container
|
} else {
|
||||||
if bd == mpBin8 || bd == mpBin16 || bd == mpBin32 {
|
|
||||||
clen = d.readContainerLen(msgpackContainerBin)
|
|
||||||
} else {
|
|
||||||
clen = d.readContainerLen(msgpackContainerStr)
|
|
||||||
}
|
|
||||||
case valueTypeString:
|
|
||||||
clen = d.readContainerLen(msgpackContainerStr)
|
clen = d.readContainerLen(msgpackContainerStr)
|
||||||
case valueTypeArray:
|
|
||||||
if zerocopy && len(bs) == 0 {
|
|
||||||
bs = d.d.b[:]
|
|
||||||
}
|
|
||||||
bsOut, _ = fastpathTV.DecSliceUint8V(bs, true, d.d)
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
d.d.errorf("invalid container type: expecting bin|str|array, got: 0x%x", uint8(vt))
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
// println("DecodeBytes: clen: ", clen)
|
||||||
// these are (bin|str)(8|16|32)
|
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
// bytes may be nil, so handle it. if nil, clen=-1.
|
// bytes may be nil, so handle it. if nil, clen=-1.
|
||||||
if clen < 0 {
|
if clen < 0 {
|
||||||
|
@ -703,18 +546,14 @@ func (d *msgpackDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte)
|
||||||
if d.br {
|
if d.br {
|
||||||
return d.r.readx(clen)
|
return d.r.readx(clen)
|
||||||
} else if len(bs) == 0 {
|
} else if len(bs) == 0 {
|
||||||
bs = d.d.b[:]
|
bs = d.b[:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return decByteSlice(d.r, clen, d.h.MaxInitLen, bs)
|
return decByteSlice(d.r, clen, bs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *msgpackDecDriver) DecodeString() (s string) {
|
func (d *msgpackDecDriver) DecodeString() (s string) {
|
||||||
return string(d.DecodeBytes(d.d.b[:], true))
|
return string(d.DecodeBytes(d.b[:], true, true))
|
||||||
}
|
|
||||||
|
|
||||||
func (d *msgpackDecDriver) DecodeStringAsBytes() (s []byte) {
|
|
||||||
return d.DecodeBytes(d.d.b[:], true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *msgpackDecDriver) readNextBd() {
|
func (d *msgpackDecDriver) readNextBd() {
|
||||||
|
@ -722,17 +561,7 @@ func (d *msgpackDecDriver) readNextBd() {
|
||||||
d.bdRead = true
|
d.bdRead = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *msgpackDecDriver) uncacheRead() {
|
|
||||||
if d.bdRead {
|
|
||||||
d.r.unreadn1()
|
|
||||||
d.bdRead = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *msgpackDecDriver) ContainerType() (vt valueType) {
|
func (d *msgpackDecDriver) ContainerType() (vt valueType) {
|
||||||
if !d.bdRead {
|
|
||||||
d.readNextBd()
|
|
||||||
}
|
|
||||||
bd := d.bd
|
bd := d.bd
|
||||||
if bd == mpNil {
|
if bd == mpNil {
|
||||||
return valueTypeNil
|
return valueTypeNil
|
||||||
|
@ -747,10 +576,9 @@ func (d *msgpackDecDriver) ContainerType() (vt valueType) {
|
||||||
return valueTypeArray
|
return valueTypeArray
|
||||||
} else if bd == mpMap16 || bd == mpMap32 || (bd >= mpFixMapMin && bd <= mpFixMapMax) {
|
} else if bd == mpMap16 || bd == mpMap32 || (bd >= mpFixMapMin && bd <= mpFixMapMax) {
|
||||||
return valueTypeMap
|
return valueTypeMap
|
||||||
|
} else {
|
||||||
|
// d.d.errorf("isContainerType: unsupported parameter: %v", vt)
|
||||||
}
|
}
|
||||||
// else {
|
|
||||||
// d.d.errorf("isContainerType: unsupported parameter: %v", vt)
|
|
||||||
// }
|
|
||||||
return valueTypeUnset
|
return valueTypeUnset
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -760,7 +588,7 @@ func (d *msgpackDecDriver) TryDecodeAsNil() (v bool) {
|
||||||
}
|
}
|
||||||
if d.bd == mpNil {
|
if d.bd == mpNil {
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
return true
|
v = true
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -778,7 +606,7 @@ func (d *msgpackDecDriver) readContainerLen(ct msgpackContainerType) (clen int)
|
||||||
} else if (ct.bFixMin & bd) == ct.bFixMin {
|
} else if (ct.bFixMin & bd) == ct.bFixMin {
|
||||||
clen = int(ct.bFixMin ^ bd)
|
clen = int(ct.bFixMin ^ bd)
|
||||||
} else {
|
} else {
|
||||||
d.d.errorf("cannot read container length: %s: hex: %x, decimal: %d", msgBadDesc, bd, bd)
|
d.d.errorf("readContainerLen: %s: hex: %x, decimal: %d", msgBadDesc, bd, bd)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
|
@ -786,16 +614,10 @@ func (d *msgpackDecDriver) readContainerLen(ct msgpackContainerType) (clen int)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *msgpackDecDriver) ReadMapStart() int {
|
func (d *msgpackDecDriver) ReadMapStart() int {
|
||||||
if !d.bdRead {
|
|
||||||
d.readNextBd()
|
|
||||||
}
|
|
||||||
return d.readContainerLen(msgpackContainerMap)
|
return d.readContainerLen(msgpackContainerMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *msgpackDecDriver) ReadArrayStart() int {
|
func (d *msgpackDecDriver) ReadArrayStart() int {
|
||||||
if !d.bdRead {
|
|
||||||
d.readNextBd()
|
|
||||||
}
|
|
||||||
return d.readContainerLen(msgpackContainerList)
|
return d.readContainerLen(msgpackContainerList)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -826,60 +648,9 @@ func (d *msgpackDecDriver) readExtLen() (clen int) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *msgpackDecDriver) DecodeTime() (t time.Time) {
|
|
||||||
// decode time from string bytes or ext
|
|
||||||
if !d.bdRead {
|
|
||||||
d.readNextBd()
|
|
||||||
}
|
|
||||||
if d.bd == mpNil {
|
|
||||||
d.bdRead = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var clen int
|
|
||||||
switch d.ContainerType() {
|
|
||||||
case valueTypeBytes, valueTypeString:
|
|
||||||
clen = d.readContainerLen(msgpackContainerStr)
|
|
||||||
default:
|
|
||||||
// expect to see mpFixExt4,-1 OR mpFixExt8,-1 OR mpExt8,12,-1
|
|
||||||
d.bdRead = false
|
|
||||||
b2 := d.r.readn1()
|
|
||||||
if d.bd == mpFixExt4 && b2 == mpTimeExtTagU {
|
|
||||||
clen = 4
|
|
||||||
} else if d.bd == mpFixExt8 && b2 == mpTimeExtTagU {
|
|
||||||
clen = 8
|
|
||||||
} else if d.bd == mpExt8 && b2 == 12 && d.r.readn1() == mpTimeExtTagU {
|
|
||||||
clen = 12
|
|
||||||
} else {
|
|
||||||
d.d.errorf("invalid bytes for decoding time as extension: got 0x%x, 0x%x", d.bd, b2)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return d.decodeTime(clen)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *msgpackDecDriver) decodeTime(clen int) (t time.Time) {
|
|
||||||
// bs = d.r.readx(clen)
|
|
||||||
d.bdRead = false
|
|
||||||
switch clen {
|
|
||||||
case 4:
|
|
||||||
t = time.Unix(int64(bigen.Uint32(d.r.readx(4))), 0).UTC()
|
|
||||||
case 8:
|
|
||||||
tv := bigen.Uint64(d.r.readx(8))
|
|
||||||
t = time.Unix(int64(tv&0x00000003ffffffff), int64(tv>>34)).UTC()
|
|
||||||
case 12:
|
|
||||||
nsec := bigen.Uint32(d.r.readx(4))
|
|
||||||
sec := bigen.Uint64(d.r.readx(8))
|
|
||||||
t = time.Unix(int64(sec), int64(nsec)).UTC()
|
|
||||||
default:
|
|
||||||
d.d.errorf("invalid length of bytes for decoding time - expecting 4 or 8 or 12, got %d", clen)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *msgpackDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) {
|
func (d *msgpackDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) {
|
||||||
if xtag > 0xff {
|
if xtag > 0xff {
|
||||||
d.d.errorf("ext: tag must be <= 0xff; got: %v", xtag)
|
d.d.errorf("decodeExt: tag must be <= 0xff; got: %v", xtag)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
realxtag1, xbs := d.decodeExtV(ext != nil, uint8(xtag))
|
realxtag1, xbs := d.decodeExtV(ext != nil, uint8(xtag))
|
||||||
|
@ -900,15 +671,15 @@ func (d *msgpackDecDriver) decodeExtV(verifyTag bool, tag byte) (xtag byte, xbs
|
||||||
}
|
}
|
||||||
xbd := d.bd
|
xbd := d.bd
|
||||||
if xbd == mpBin8 || xbd == mpBin16 || xbd == mpBin32 {
|
if xbd == mpBin8 || xbd == mpBin16 || xbd == mpBin32 {
|
||||||
xbs = d.DecodeBytes(nil, true)
|
xbs = d.DecodeBytes(nil, false, true)
|
||||||
} else if xbd == mpStr8 || xbd == mpStr16 || xbd == mpStr32 ||
|
} else if xbd == mpStr8 || xbd == mpStr16 || xbd == mpStr32 ||
|
||||||
(xbd >= mpFixStrMin && xbd <= mpFixStrMax) {
|
(xbd >= mpFixStrMin && xbd <= mpFixStrMax) {
|
||||||
xbs = d.DecodeStringAsBytes()
|
xbs = d.DecodeBytes(nil, true, true)
|
||||||
} else {
|
} else {
|
||||||
clen := d.readExtLen()
|
clen := d.readExtLen()
|
||||||
xtag = d.r.readn1()
|
xtag = d.r.readn1()
|
||||||
if verifyTag && xtag != tag {
|
if verifyTag && xtag != tag {
|
||||||
d.d.errorf("wrong extension tag - got %b, expecting %v", xtag, tag)
|
d.d.errorf("Wrong extension tag. Got %b. Expecting: %v", xtag, tag)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
xbs = d.r.readx(clen)
|
xbs = d.r.readx(clen)
|
||||||
|
@ -926,9 +697,6 @@ type MsgpackHandle struct {
|
||||||
// RawToString controls how raw bytes are decoded into a nil interface{}.
|
// RawToString controls how raw bytes are decoded into a nil interface{}.
|
||||||
RawToString bool
|
RawToString bool
|
||||||
|
|
||||||
// NoFixedNum says to output all signed integers as 2-bytes, never as 1-byte fixednum.
|
|
||||||
NoFixedNum bool
|
|
||||||
|
|
||||||
// WriteExt flag supports encoding configured extensions with extension tags.
|
// WriteExt flag supports encoding configured extensions with extension tags.
|
||||||
// It also controls whether other elements of the new spec are encoded (ie Str8).
|
// It also controls whether other elements of the new spec are encoded (ie Str8).
|
||||||
//
|
//
|
||||||
|
@ -940,22 +708,11 @@ type MsgpackHandle struct {
|
||||||
// type is provided (e.g. decoding into a nil interface{}), you get back
|
// type is provided (e.g. decoding into a nil interface{}), you get back
|
||||||
// a []byte or string based on the setting of RawToString.
|
// a []byte or string based on the setting of RawToString.
|
||||||
WriteExt bool
|
WriteExt bool
|
||||||
|
|
||||||
// PositiveIntUnsigned says to encode positive integers as unsigned.
|
|
||||||
PositiveIntUnsigned bool
|
|
||||||
|
|
||||||
binaryEncodingType
|
binaryEncodingType
|
||||||
noElemSeparators
|
|
||||||
|
|
||||||
// _ [1]uint64 // padding
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name returns the name of the handle: msgpack
|
|
||||||
func (h *MsgpackHandle) Name() string { return "msgpack" }
|
|
||||||
|
|
||||||
// SetBytesExt sets an extension
|
|
||||||
func (h *MsgpackHandle) SetBytesExt(rt reflect.Type, tag uint64, ext BytesExt) (err error) {
|
func (h *MsgpackHandle) SetBytesExt(rt reflect.Type, tag uint64, ext BytesExt) (err error) {
|
||||||
return h.SetExt(rt, tag, &extWrapper{ext, interfaceExtFailer{}})
|
return h.SetExt(rt, tag, &setExtWrapper{b: ext})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *MsgpackHandle) newEncDriver(e *Encoder) encDriver {
|
func (h *MsgpackHandle) newEncDriver(e *Encoder) encDriver {
|
||||||
|
@ -963,7 +720,7 @@ func (h *MsgpackHandle) newEncDriver(e *Encoder) encDriver {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *MsgpackHandle) newDecDriver(d *Decoder) decDriver {
|
func (h *MsgpackHandle) newDecDriver(d *Decoder) decDriver {
|
||||||
return &msgpackDecDriver{d: d, h: h, r: d.r, br: d.bytes}
|
return &msgpackDecDriver{d: d, r: d.r, h: h, br: d.bytes}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *msgpackEncDriver) reset() {
|
func (e *msgpackEncDriver) reset() {
|
||||||
|
@ -971,7 +728,7 @@ func (e *msgpackEncDriver) reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *msgpackDecDriver) reset() {
|
func (d *msgpackDecDriver) reset() {
|
||||||
d.r, d.br = d.d.r, d.d.bytes
|
d.r = d.d.r
|
||||||
d.bd, d.bdRead = 0, false
|
d.bd, d.bdRead = 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -993,7 +750,7 @@ func (c *msgpackSpecRpcCodec) WriteRequest(r *rpc.Request, body interface{}) err
|
||||||
bodyArr = []interface{}{body}
|
bodyArr = []interface{}{body}
|
||||||
}
|
}
|
||||||
r2 := []interface{}{0, uint32(r.Seq), r.ServiceMethod, bodyArr}
|
r2 := []interface{}{0, uint32(r.Seq), r.ServiceMethod, bodyArr}
|
||||||
return c.write(r2, nil, false)
|
return c.write(r2, nil, false, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *msgpackSpecRpcCodec) WriteResponse(r *rpc.Response, body interface{}) error {
|
func (c *msgpackSpecRpcCodec) WriteResponse(r *rpc.Response, body interface{}) error {
|
||||||
|
@ -1005,7 +762,7 @@ func (c *msgpackSpecRpcCodec) WriteResponse(r *rpc.Response, body interface{}) e
|
||||||
body = nil
|
body = nil
|
||||||
}
|
}
|
||||||
r2 := []interface{}{1, uint32(r.Seq), moe, body}
|
r2 := []interface{}{1, uint32(r.Seq), moe, body}
|
||||||
return c.write(r2, nil, false)
|
return c.write(r2, nil, false, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *msgpackSpecRpcCodec) ReadResponseHeader(r *rpc.Response) error {
|
func (c *msgpackSpecRpcCodec) ReadResponseHeader(r *rpc.Response) error {
|
||||||
|
@ -1025,6 +782,7 @@ func (c *msgpackSpecRpcCodec) ReadRequestBody(body interface{}) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *msgpackSpecRpcCodec) parseCustomHeader(expectTypeByte byte, msgid *uint64, methodOrError *string) (err error) {
|
func (c *msgpackSpecRpcCodec) parseCustomHeader(expectTypeByte byte, msgid *uint64, methodOrError *string) (err error) {
|
||||||
|
|
||||||
if c.isClosed() {
|
if c.isClosed() {
|
||||||
return io.EOF
|
return io.EOF
|
||||||
}
|
}
|
||||||
|
@ -1038,34 +796,28 @@ func (c *msgpackSpecRpcCodec) parseCustomHeader(expectTypeByte byte, msgid *uint
|
||||||
// err = fmt.Errorf("Unexpected value for array descriptor: Expecting %v. Received %v", fia, bs1)
|
// err = fmt.Errorf("Unexpected value for array descriptor: Expecting %v. Received %v", fia, bs1)
|
||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
var ba [1]byte
|
var b byte
|
||||||
var n int
|
b, err = c.br.ReadByte()
|
||||||
for {
|
if err != nil {
|
||||||
n, err = c.r.Read(ba[:])
|
return
|
||||||
if err != nil {
|
}
|
||||||
return
|
if b != fia {
|
||||||
}
|
err = fmt.Errorf("Unexpected value for array descriptor: Expecting %v. Received %v", fia, b)
|
||||||
if n == 1 {
|
return
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var b = ba[0]
|
if err = c.read(&b); err != nil {
|
||||||
if b != fia {
|
return
|
||||||
err = fmt.Errorf("not array - %s %x/%s", msgBadDesc, b, mpdesc(b))
|
}
|
||||||
} else {
|
if b != expectTypeByte {
|
||||||
err = c.read(&b)
|
err = fmt.Errorf("Unexpected byte descriptor in header. Expecting %v. Received %v", expectTypeByte, b)
|
||||||
if err == nil {
|
return
|
||||||
if b != expectTypeByte {
|
}
|
||||||
err = fmt.Errorf("%s - expecting %v but got %x/%s",
|
if err = c.read(msgid); err != nil {
|
||||||
msgBadDesc, expectTypeByte, b, mpdesc(b))
|
return
|
||||||
} else {
|
}
|
||||||
err = c.read(msgid)
|
if err = c.read(methodOrError); err != nil {
|
||||||
if err == nil {
|
return
|
||||||
err = c.read(methodOrError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1078,8 +830,7 @@ type msgpackSpecRpc struct{}
|
||||||
|
|
||||||
// MsgpackSpecRpc implements Rpc using the communication protocol defined in
|
// MsgpackSpecRpc implements Rpc using the communication protocol defined in
|
||||||
// the msgpack spec at https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md .
|
// the msgpack spec at https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md .
|
||||||
//
|
// Its methods (ServerCodec and ClientCodec) return values that implement RpcCodecBuffered.
|
||||||
// See GoRpc documentation, for information on buffering for better performance.
|
|
||||||
var MsgpackSpecRpc msgpackSpecRpc
|
var MsgpackSpecRpc msgpackSpecRpc
|
||||||
|
|
||||||
func (x msgpackSpecRpc) ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec {
|
func (x msgpackSpecRpc) ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec {
|
||||||
|
|
|
@ -1,152 +1,127 @@
|
||||||
// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
|
// 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.
|
// Use of this source code is governed by a MIT license found in the LICENSE file.
|
||||||
|
|
||||||
package codec
|
package codec
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"errors"
|
|
||||||
"io"
|
"io"
|
||||||
"net/rpc"
|
"net/rpc"
|
||||||
"sync"
|
"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
|
||||||
|
}
|
||||||
|
|
||||||
// Rpc provides a rpc Server or Client Codec for rpc communication.
|
// Rpc provides a rpc Server or Client Codec for rpc communication.
|
||||||
type Rpc interface {
|
type Rpc interface {
|
||||||
ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec
|
ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec
|
||||||
ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec
|
ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec
|
||||||
}
|
}
|
||||||
|
|
||||||
// RPCOptions holds options specific to rpc functionality
|
// RpcCodecBuffered allows access to the underlying bufio.Reader/Writer
|
||||||
type RPCOptions struct {
|
// used by the rpc connection. It accomodates use-cases where the connection
|
||||||
// RPCNoBuffer configures whether we attempt to buffer reads and writes during RPC calls.
|
// should be used by rpc and non-rpc functions, e.g. streaming a file after
|
||||||
//
|
// sending an rpc response.
|
||||||
// Set RPCNoBuffer=true to turn buffering off.
|
type RpcCodecBuffered interface {
|
||||||
// Buffering can still be done if buffered connections are passed in, or
|
BufferedReader() *bufio.Reader
|
||||||
// buffering is configured on the handle.
|
BufferedWriter() *bufio.Writer
|
||||||
RPCNoBuffer bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
// rpcCodec defines the struct members and common methods.
|
// rpcCodec defines the struct members and common methods.
|
||||||
type rpcCodec struct {
|
type rpcCodec struct {
|
||||||
c io.Closer
|
rwc io.ReadWriteCloser
|
||||||
r io.Reader
|
|
||||||
w io.Writer
|
|
||||||
f ioFlusher
|
|
||||||
|
|
||||||
dec *Decoder
|
dec *Decoder
|
||||||
enc *Encoder
|
enc *Encoder
|
||||||
// bw *bufio.Writer
|
bw *bufio.Writer
|
||||||
// br *bufio.Reader
|
br *bufio.Reader
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
h Handle
|
h Handle
|
||||||
|
|
||||||
cls bool
|
cls bool
|
||||||
clsmu sync.RWMutex
|
clsmu sync.RWMutex
|
||||||
clsErr error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRPCCodec(conn io.ReadWriteCloser, h Handle) rpcCodec {
|
func newRPCCodec(conn io.ReadWriteCloser, h Handle) rpcCodec {
|
||||||
// return newRPCCodec2(bufio.NewReader(conn), bufio.NewWriter(conn), conn, h)
|
bw := bufio.NewWriter(conn)
|
||||||
return newRPCCodec2(conn, conn, conn, h)
|
br := bufio.NewReader(conn)
|
||||||
}
|
|
||||||
|
|
||||||
func newRPCCodec2(r io.Reader, w io.Writer, c io.Closer, h Handle) rpcCodec {
|
|
||||||
// defensive: ensure that jsonH has TermWhitespace turned on.
|
|
||||||
if jsonH, ok := h.(*JsonHandle); ok && !jsonH.TermWhitespace {
|
|
||||||
panic(errors.New("rpc requires a JsonHandle with TermWhitespace set to true"))
|
|
||||||
}
|
|
||||||
// always ensure that we use a flusher, and always flush what was written to the connection.
|
|
||||||
// we lose nothing by using a buffered writer internally.
|
|
||||||
f, ok := w.(ioFlusher)
|
|
||||||
bh := h.getBasicHandle()
|
|
||||||
if !bh.RPCNoBuffer {
|
|
||||||
if bh.WriterBufferSize <= 0 {
|
|
||||||
if !ok {
|
|
||||||
bw := bufio.NewWriter(w)
|
|
||||||
f, w = bw, bw
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if bh.ReaderBufferSize <= 0 {
|
|
||||||
if _, ok = w.(ioPeeker); !ok {
|
|
||||||
if _, ok = w.(ioBuffered); !ok {
|
|
||||||
br := bufio.NewReader(r)
|
|
||||||
r = br
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rpcCodec{
|
return rpcCodec{
|
||||||
c: c,
|
rwc: conn,
|
||||||
w: w,
|
bw: bw,
|
||||||
r: r,
|
br: br,
|
||||||
f: f,
|
enc: NewEncoder(bw, h),
|
||||||
|
dec: NewDecoder(br, h),
|
||||||
h: h,
|
h: h,
|
||||||
enc: NewEncoder(w, h),
|
|
||||||
dec: NewDecoder(r, h),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *rpcCodec) write(obj1, obj2 interface{}, writeObj2 bool) (err error) {
|
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() {
|
if c.isClosed() {
|
||||||
return c.clsErr
|
return io.EOF
|
||||||
}
|
}
|
||||||
err = c.enc.Encode(obj1)
|
if err = c.enc.Encode(obj1); err != nil {
|
||||||
if err == nil {
|
return
|
||||||
if writeObj2 {
|
|
||||||
err = c.enc.Encode(obj2)
|
|
||||||
}
|
|
||||||
// if err == nil && c.f != nil {
|
|
||||||
// err = c.f.Flush()
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
if c.f != nil {
|
t, tOk := c.h.(rpcEncodeTerminator)
|
||||||
if err == nil {
|
if tOk {
|
||||||
err = c.f.Flush()
|
c.bw.Write(t.rpcEncodeTerminate())
|
||||||
} else {
|
}
|
||||||
_ = c.f.Flush() // swallow flush error, so we maintain prior error on write
|
if writeObj2 {
|
||||||
|
if err = c.enc.Encode(obj2); err != nil {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
if tOk {
|
||||||
|
c.bw.Write(t.rpcEncodeTerminate())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if doFlush {
|
||||||
|
return c.bw.Flush()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *rpcCodec) swallow(err *error) {
|
|
||||||
defer panicToErr(c.dec, err)
|
|
||||||
c.dec.swallow()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *rpcCodec) read(obj interface{}) (err error) {
|
func (c *rpcCodec) read(obj interface{}) (err error) {
|
||||||
if c.isClosed() {
|
if c.isClosed() {
|
||||||
return c.clsErr
|
return io.EOF
|
||||||
}
|
}
|
||||||
//If nil is passed in, we should read and discard
|
//If nil is passed in, we should still attempt to read content to nowhere.
|
||||||
if obj == nil {
|
if obj == nil {
|
||||||
// var obj2 interface{}
|
var obj2 interface{}
|
||||||
// return c.dec.Decode(&obj2)
|
return c.dec.Decode(&obj2)
|
||||||
c.swallow(&err)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
return c.dec.Decode(obj)
|
return c.dec.Decode(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *rpcCodec) isClosed() (b bool) {
|
func (c *rpcCodec) isClosed() bool {
|
||||||
if c.c != nil {
|
c.clsmu.RLock()
|
||||||
c.clsmu.RLock()
|
x := c.cls
|
||||||
b = c.cls
|
c.clsmu.RUnlock()
|
||||||
c.clsmu.RUnlock()
|
return x
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *rpcCodec) Close() error {
|
func (c *rpcCodec) Close() error {
|
||||||
if c.c == nil || c.isClosed() {
|
if c.isClosed() {
|
||||||
return c.clsErr
|
return io.EOF
|
||||||
}
|
}
|
||||||
c.clsmu.Lock()
|
c.clsmu.Lock()
|
||||||
c.cls = true
|
c.cls = true
|
||||||
c.clsErr = c.c.Close()
|
|
||||||
c.clsmu.Unlock()
|
c.clsmu.Unlock()
|
||||||
return c.clsErr
|
return c.rwc.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *rpcCodec) ReadResponseBody(body interface{}) error {
|
func (c *rpcCodec) ReadResponseBody(body interface{}) error {
|
||||||
|
@ -163,13 +138,13 @@ func (c *goRpcCodec) WriteRequest(r *rpc.Request, body interface{}) error {
|
||||||
// Must protect for concurrent access as per API
|
// Must protect for concurrent access as per API
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
defer c.mu.Unlock()
|
defer c.mu.Unlock()
|
||||||
return c.write(r, body, true)
|
return c.write(r, body, true, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *goRpcCodec) WriteResponse(r *rpc.Response, body interface{}) error {
|
func (c *goRpcCodec) WriteResponse(r *rpc.Response, body interface{}) error {
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
defer c.mu.Unlock()
|
defer c.mu.Unlock()
|
||||||
return c.write(r, body, true)
|
return c.write(r, body, true, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *goRpcCodec) ReadResponseHeader(r *rpc.Response) error {
|
func (c *goRpcCodec) ReadResponseHeader(r *rpc.Response) error {
|
||||||
|
@ -191,36 +166,7 @@ func (c *goRpcCodec) ReadRequestBody(body interface{}) error {
|
||||||
type goRpc struct{}
|
type goRpc struct{}
|
||||||
|
|
||||||
// GoRpc implements Rpc using the communication protocol defined in net/rpc package.
|
// 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
|
var GoRpc goRpc
|
||||||
|
|
||||||
func (x goRpc) ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec {
|
func (x goRpc) ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec {
|
||||||
|
@ -230,3 +176,5 @@ func (x goRpc) ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec {
|
||||||
func (x goRpc) ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec {
|
func (x goRpc) ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec {
|
||||||
return &goRpcCodec{newRPCCodec(conn, h)}
|
return &goRpcCodec{newRPCCodec(conn, h)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ RpcCodecBuffered = (*rpcCodec)(nil) // ensure *rpcCodec implements RpcCodecBuffered
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
|
// 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.
|
// Use of this source code is governed by a MIT license found in the LICENSE file.
|
||||||
|
|
||||||
package codec
|
package codec
|
||||||
|
@ -6,7 +6,6 @@ package codec
|
||||||
import (
|
import (
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -21,8 +20,6 @@ const (
|
||||||
simpleVdPosInt = 8
|
simpleVdPosInt = 8
|
||||||
simpleVdNegInt = 12
|
simpleVdNegInt = 12
|
||||||
|
|
||||||
simpleVdTime = 24
|
|
||||||
|
|
||||||
// containers: each lasts for 4 (ie n, n+1, n+2, ... n+7)
|
// containers: each lasts for 4 (ie n, n+1, n+2, ... n+7)
|
||||||
simpleVdString = 216
|
simpleVdString = 216
|
||||||
simpleVdByteArray = 224
|
simpleVdByteArray = 224
|
||||||
|
@ -33,15 +30,11 @@ const (
|
||||||
|
|
||||||
type simpleEncDriver struct {
|
type simpleEncDriver struct {
|
||||||
noBuiltInTypes
|
noBuiltInTypes
|
||||||
// encNoSeparator
|
encNoSeparator
|
||||||
e *Encoder
|
e *Encoder
|
||||||
h *SimpleHandle
|
h *SimpleHandle
|
||||||
w encWriter
|
w encWriter
|
||||||
b [8]byte
|
b [8]byte
|
||||||
// c containerState
|
|
||||||
encDriverTrackContainerWriter
|
|
||||||
// encDriverNoopContainerWriter
|
|
||||||
_ [3]uint64 // padding
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *simpleEncDriver) EncodeNil() {
|
func (e *simpleEncDriver) EncodeNil() {
|
||||||
|
@ -49,10 +42,6 @@ func (e *simpleEncDriver) EncodeNil() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *simpleEncDriver) EncodeBool(b bool) {
|
func (e *simpleEncDriver) EncodeBool(b bool) {
|
||||||
if e.h.EncZeroValuesAsNil && e.c != containerMapKey && !b {
|
|
||||||
e.EncodeNil()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if b {
|
if b {
|
||||||
e.w.writen1(simpleVdTrue)
|
e.w.writen1(simpleVdTrue)
|
||||||
} else {
|
} else {
|
||||||
|
@ -61,19 +50,11 @@ func (e *simpleEncDriver) EncodeBool(b bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *simpleEncDriver) EncodeFloat32(f float32) {
|
func (e *simpleEncDriver) EncodeFloat32(f float32) {
|
||||||
if e.h.EncZeroValuesAsNil && e.c != containerMapKey && f == 0.0 {
|
|
||||||
e.EncodeNil()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.w.writen1(simpleVdFloat32)
|
e.w.writen1(simpleVdFloat32)
|
||||||
bigenHelper{e.b[:4], e.w}.writeUint32(math.Float32bits(f))
|
bigenHelper{e.b[:4], e.w}.writeUint32(math.Float32bits(f))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *simpleEncDriver) EncodeFloat64(f float64) {
|
func (e *simpleEncDriver) EncodeFloat64(f float64) {
|
||||||
if e.h.EncZeroValuesAsNil && e.c != containerMapKey && f == 0.0 {
|
|
||||||
e.EncodeNil()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.w.writen1(simpleVdFloat64)
|
e.w.writen1(simpleVdFloat64)
|
||||||
bigenHelper{e.b[:8], e.w}.writeUint64(math.Float64bits(f))
|
bigenHelper{e.b[:8], e.w}.writeUint64(math.Float64bits(f))
|
||||||
}
|
}
|
||||||
|
@ -91,10 +72,6 @@ func (e *simpleEncDriver) EncodeUint(v uint64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *simpleEncDriver) encUint(v uint64, bd uint8) {
|
func (e *simpleEncDriver) encUint(v uint64, bd uint8) {
|
||||||
if e.h.EncZeroValuesAsNil && e.c != containerMapKey && v == 0 {
|
|
||||||
e.EncodeNil()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if v <= math.MaxUint8 {
|
if v <= math.MaxUint8 {
|
||||||
e.w.writen2(bd, uint8(v))
|
e.w.writen2(bd, uint8(v))
|
||||||
} else if v <= math.MaxUint16 {
|
} else if v <= math.MaxUint16 {
|
||||||
|
@ -147,52 +124,25 @@ func (e *simpleEncDriver) encodeExtPreamble(xtag byte, length int) {
|
||||||
e.w.writen1(xtag)
|
e.w.writen1(xtag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *simpleEncDriver) WriteArrayStart(length int) {
|
func (e *simpleEncDriver) EncodeArrayStart(length int) {
|
||||||
e.c = containerArrayStart
|
|
||||||
e.encLen(simpleVdArray, length)
|
e.encLen(simpleVdArray, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *simpleEncDriver) WriteMapStart(length int) {
|
func (e *simpleEncDriver) EncodeMapStart(length int) {
|
||||||
e.c = containerMapStart
|
|
||||||
e.encLen(simpleVdMap, length)
|
e.encLen(simpleVdMap, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *simpleEncDriver) EncodeString(c charEncoding, v string) {
|
func (e *simpleEncDriver) EncodeString(c charEncoding, v string) {
|
||||||
if false && e.h.EncZeroValuesAsNil && e.c != containerMapKey && v == "" {
|
|
||||||
e.EncodeNil()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.encLen(simpleVdString, len(v))
|
e.encLen(simpleVdString, len(v))
|
||||||
e.w.writestr(v)
|
e.w.writestr(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// func (e *simpleEncDriver) EncodeSymbol(v string) {
|
func (e *simpleEncDriver) EncodeSymbol(v string) {
|
||||||
// e.EncodeString(cUTF8, v)
|
e.EncodeString(c_UTF8, v)
|
||||||
// }
|
|
||||||
|
|
||||||
func (e *simpleEncDriver) EncodeStringBytes(c charEncoding, 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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *simpleEncDriver) EncodeTime(t time.Time) {
|
func (e *simpleEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
|
||||||
// if e.h.EncZeroValuesAsNil && e.c != containerMapKey && t.IsZero() {
|
e.encLen(simpleVdByteArray, len(v))
|
||||||
if t.IsZero() {
|
|
||||||
e.EncodeNil()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
v, err := t.MarshalBinary()
|
|
||||||
if err != nil {
|
|
||||||
e.e.errorv(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// time.Time marshalbinary takes about 14 bytes.
|
|
||||||
e.w.writen2(simpleVdTime, uint8(len(v)))
|
|
||||||
e.w.writeb(v)
|
e.w.writeb(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,13 +154,11 @@ type simpleDecDriver struct {
|
||||||
r decReader
|
r decReader
|
||||||
bdRead bool
|
bdRead bool
|
||||||
bd byte
|
bd byte
|
||||||
br bool // a bytes reader?
|
br bool // bytes reader
|
||||||
c containerState
|
|
||||||
// b [scratchByteArrayLen]byte
|
|
||||||
noBuiltInTypes
|
noBuiltInTypes
|
||||||
// noStreamingCodec
|
noStreamingCodec
|
||||||
decDriverNoopContainerReader
|
decNoSeparator
|
||||||
// _ [3]uint64 // padding
|
b [scratchByteArrayLen]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *simpleDecDriver) readNextBd() {
|
func (d *simpleDecDriver) readNextBd() {
|
||||||
|
@ -218,38 +166,24 @@ func (d *simpleDecDriver) readNextBd() {
|
||||||
d.bdRead = true
|
d.bdRead = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *simpleDecDriver) uncacheRead() {
|
|
||||||
if d.bdRead {
|
|
||||||
d.r.unreadn1()
|
|
||||||
d.bdRead = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *simpleDecDriver) ContainerType() (vt valueType) {
|
func (d *simpleDecDriver) ContainerType() (vt valueType) {
|
||||||
if !d.bdRead {
|
if d.bd == simpleVdNil {
|
||||||
d.readNextBd()
|
|
||||||
}
|
|
||||||
switch d.bd {
|
|
||||||
case simpleVdNil:
|
|
||||||
return valueTypeNil
|
return valueTypeNil
|
||||||
case simpleVdByteArray, simpleVdByteArray + 1,
|
} else if d.bd == simpleVdByteArray || d.bd == simpleVdByteArray+1 ||
|
||||||
simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
|
d.bd == simpleVdByteArray+2 || d.bd == simpleVdByteArray+3 || d.bd == simpleVdByteArray+4 {
|
||||||
return valueTypeBytes
|
return valueTypeBytes
|
||||||
case simpleVdString, simpleVdString + 1,
|
} else if d.bd == simpleVdString || d.bd == simpleVdString+1 ||
|
||||||
simpleVdString + 2, simpleVdString + 3, simpleVdString + 4:
|
d.bd == simpleVdString+2 || d.bd == simpleVdString+3 || d.bd == simpleVdString+4 {
|
||||||
return valueTypeString
|
return valueTypeString
|
||||||
case simpleVdArray, simpleVdArray + 1,
|
} else if d.bd == simpleVdArray || d.bd == simpleVdArray+1 ||
|
||||||
simpleVdArray + 2, simpleVdArray + 3, simpleVdArray + 4:
|
d.bd == simpleVdArray+2 || d.bd == simpleVdArray+3 || d.bd == simpleVdArray+4 {
|
||||||
return valueTypeArray
|
return valueTypeArray
|
||||||
case simpleVdMap, simpleVdMap + 1,
|
} else if d.bd == simpleVdMap || d.bd == simpleVdMap+1 ||
|
||||||
simpleVdMap + 2, simpleVdMap + 3, simpleVdMap + 4:
|
d.bd == simpleVdMap+2 || d.bd == simpleVdMap+3 || d.bd == simpleVdMap+4 {
|
||||||
return valueTypeMap
|
return valueTypeMap
|
||||||
// case simpleVdTime:
|
} else {
|
||||||
// return valueTypeTime
|
// d.d.errorf("isContainerType: unsupported parameter: %v", vt)
|
||||||
}
|
}
|
||||||
// else {
|
|
||||||
// d.d.errorf("isContainerType: unsupported parameter: %v", vt)
|
|
||||||
// }
|
|
||||||
return valueTypeUnset
|
return valueTypeUnset
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,7 +224,7 @@ func (d *simpleDecDriver) decCheckInteger() (ui uint64, neg bool) {
|
||||||
ui = uint64(bigen.Uint64(d.r.readx(8)))
|
ui = uint64(bigen.Uint64(d.r.readx(8)))
|
||||||
neg = true
|
neg = true
|
||||||
default:
|
default:
|
||||||
d.d.errorf("integer only valid from pos/neg integer1..8. Invalid descriptor: %v", d.bd)
|
d.d.errorf("decIntAny: Integer only valid from pos/neg integer1..8. Invalid descriptor: %v", d.bd)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// don't do this check, because callers may only want the unsigned value.
|
// don't do this check, because callers may only want the unsigned value.
|
||||||
|
@ -301,27 +235,39 @@ func (d *simpleDecDriver) decCheckInteger() (ui uint64, neg bool) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *simpleDecDriver) DecodeInt64() (i int64) {
|
func (d *simpleDecDriver) DecodeInt(bitsize uint8) (i int64) {
|
||||||
ui, neg := d.decCheckInteger()
|
ui, neg := d.decCheckInteger()
|
||||||
i = chkOvf.SignedIntV(ui)
|
i, overflow := chkOvf.SignedInt(ui)
|
||||||
|
if overflow {
|
||||||
|
d.d.errorf("simple: overflow converting %v to signed integer", ui)
|
||||||
|
return
|
||||||
|
}
|
||||||
if neg {
|
if neg {
|
||||||
i = -i
|
i = -i
|
||||||
}
|
}
|
||||||
d.bdRead = false
|
if chkOvf.Int(i, bitsize) {
|
||||||
return
|
d.d.errorf("simple: overflow integer: %v", i)
|
||||||
}
|
|
||||||
|
|
||||||
func (d *simpleDecDriver) DecodeUint64() (ui uint64) {
|
|
||||||
ui, neg := d.decCheckInteger()
|
|
||||||
if neg {
|
|
||||||
d.d.errorf("assigning negative signed value to unsigned type")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *simpleDecDriver) DecodeFloat64() (f float64) {
|
func (d *simpleDecDriver) DecodeUint(bitsize uint8) (ui uint64) {
|
||||||
|
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.bdRead = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *simpleDecDriver) DecodeFloat(chkOverflow32 bool) (f float64) {
|
||||||
if !d.bdRead {
|
if !d.bdRead {
|
||||||
d.readNextBd()
|
d.readNextBd()
|
||||||
}
|
}
|
||||||
|
@ -331,12 +277,16 @@ func (d *simpleDecDriver) DecodeFloat64() (f float64) {
|
||||||
f = math.Float64frombits(bigen.Uint64(d.r.readx(8)))
|
f = math.Float64frombits(bigen.Uint64(d.r.readx(8)))
|
||||||
} else {
|
} else {
|
||||||
if d.bd >= simpleVdPosInt && d.bd <= simpleVdNegInt+3 {
|
if d.bd >= simpleVdPosInt && d.bd <= simpleVdNegInt+3 {
|
||||||
f = float64(d.DecodeInt64())
|
f = float64(d.DecodeInt(64))
|
||||||
} else {
|
} else {
|
||||||
d.d.errorf("float only valid from float32/64: Invalid descriptor: %v", d.bd)
|
d.d.errorf("Float only valid from float32/64: Invalid descriptor: %v", d.bd)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if chkOverflow32 && chkOvf.Float32(f) {
|
||||||
|
d.d.errorf("msgpack: float32 overflow: %v", f)
|
||||||
|
return
|
||||||
|
}
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -350,7 +300,7 @@ func (d *simpleDecDriver) DecodeBool() (b bool) {
|
||||||
b = true
|
b = true
|
||||||
} else if d.bd == simpleVdFalse {
|
} else if d.bd == simpleVdFalse {
|
||||||
} else {
|
} else {
|
||||||
d.d.errorf("cannot decode bool - %s: %x", msgBadDesc, d.bd)
|
d.d.errorf("Invalid single-byte value for bool: %s: %x", msgBadDesc, d.bd)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
|
@ -358,43 +308,15 @@ func (d *simpleDecDriver) DecodeBool() (b bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *simpleDecDriver) ReadMapStart() (length int) {
|
func (d *simpleDecDriver) ReadMapStart() (length int) {
|
||||||
if !d.bdRead {
|
|
||||||
d.readNextBd()
|
|
||||||
}
|
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
d.c = containerMapStart
|
|
||||||
return d.decLen()
|
return d.decLen()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *simpleDecDriver) ReadArrayStart() (length int) {
|
func (d *simpleDecDriver) ReadArrayStart() (length int) {
|
||||||
if !d.bdRead {
|
|
||||||
d.readNextBd()
|
|
||||||
}
|
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
d.c = containerArrayStart
|
|
||||||
return d.decLen()
|
return d.decLen()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *simpleDecDriver) ReadArrayElem() {
|
|
||||||
d.c = containerArrayElem
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *simpleDecDriver) ReadArrayEnd() {
|
|
||||||
d.c = containerArrayEnd
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *simpleDecDriver) ReadMapElemKey() {
|
|
||||||
d.c = containerMapKey
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *simpleDecDriver) ReadMapElemValue() {
|
|
||||||
d.c = containerMapValue
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *simpleDecDriver) ReadMapEnd() {
|
|
||||||
d.c = containerMapEnd
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *simpleDecDriver) decLen() int {
|
func (d *simpleDecDriver) decLen() int {
|
||||||
switch d.bd % 8 {
|
switch d.bd % 8 {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -406,31 +328,27 @@ func (d *simpleDecDriver) decLen() int {
|
||||||
case 3:
|
case 3:
|
||||||
ui := uint64(bigen.Uint32(d.r.readx(4)))
|
ui := uint64(bigen.Uint32(d.r.readx(4)))
|
||||||
if chkOvf.Uint(ui, intBitsize) {
|
if chkOvf.Uint(ui, intBitsize) {
|
||||||
d.d.errorf("overflow integer: %v", ui)
|
d.d.errorf("simple: overflow integer: %v", ui)
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return int(ui)
|
return int(ui)
|
||||||
case 4:
|
case 4:
|
||||||
ui := bigen.Uint64(d.r.readx(8))
|
ui := bigen.Uint64(d.r.readx(8))
|
||||||
if chkOvf.Uint(ui, intBitsize) {
|
if chkOvf.Uint(ui, intBitsize) {
|
||||||
d.d.errorf("overflow integer: %v", ui)
|
d.d.errorf("simple: overflow integer: %v", ui)
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return int(ui)
|
return int(ui)
|
||||||
}
|
}
|
||||||
d.d.errorf("cannot read length: bd%%8 must be in range 0..4. Got: %d", d.bd%8)
|
d.d.errorf("decLen: Cannot read length: bd%8 must be in range 0..4. Got: %d", d.bd%8)
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *simpleDecDriver) DecodeString() (s string) {
|
func (d *simpleDecDriver) DecodeString() (s string) {
|
||||||
return string(d.DecodeBytes(d.d.b[:], true))
|
return string(d.DecodeBytes(d.b[:], true, true))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *simpleDecDriver) DecodeStringAsBytes() (s []byte) {
|
func (d *simpleDecDriver) DecodeBytes(bs []byte, isstring, zerocopy bool) (bsOut []byte) {
|
||||||
return d.DecodeBytes(d.d.b[:], true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *simpleDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
|
|
||||||
if !d.bdRead {
|
if !d.bdRead {
|
||||||
d.readNextBd()
|
d.readNextBd()
|
||||||
}
|
}
|
||||||
|
@ -438,51 +356,21 @@ func (d *simpleDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
return
|
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 len(bs) == 0 && zerocopy {
|
|
||||||
bs = d.d.b[:]
|
|
||||||
}
|
|
||||||
bsOut, _ = fastpathTV.DecSliceUint8V(bs, true, d.d)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
clen := d.decLen()
|
clen := d.decLen()
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
if zerocopy {
|
if zerocopy {
|
||||||
if d.br {
|
if d.br {
|
||||||
return d.r.readx(clen)
|
return d.r.readx(clen)
|
||||||
} else if len(bs) == 0 {
|
} else if len(bs) == 0 {
|
||||||
bs = d.d.b[:]
|
bs = d.b[:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return decByteSlice(d.r, clen, d.d.h.MaxInitLen, bs)
|
return decByteSlice(d.r, clen, bs)
|
||||||
}
|
|
||||||
|
|
||||||
func (d *simpleDecDriver) DecodeTime() (t time.Time) {
|
|
||||||
if !d.bdRead {
|
|
||||||
d.readNextBd()
|
|
||||||
}
|
|
||||||
if d.bd == simpleVdNil {
|
|
||||||
d.bdRead = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if d.bd != simpleVdTime {
|
|
||||||
d.d.errorf("invalid descriptor for time.Time - expect 0x%x, received 0x%x", simpleVdTime, d.bd)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
d.bdRead = false
|
|
||||||
clen := int(d.r.readn1())
|
|
||||||
b := d.r.readx(clen)
|
|
||||||
if err := (&t).UnmarshalBinary(b); err != nil {
|
|
||||||
d.d.errorv(err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *simpleDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) {
|
func (d *simpleDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) {
|
||||||
if xtag > 0xff {
|
if xtag > 0xff {
|
||||||
d.d.errorf("ext: tag must be <= 0xff; got: %v", xtag)
|
d.d.errorf("decodeExt: tag must be <= 0xff; got: %v", xtag)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
realxtag1, xbs := d.decodeExtV(ext != nil, uint8(xtag))
|
realxtag1, xbs := d.decodeExtV(ext != nil, uint8(xtag))
|
||||||
|
@ -506,15 +394,14 @@ func (d *simpleDecDriver) decodeExtV(verifyTag bool, tag byte) (xtag byte, xbs [
|
||||||
l := d.decLen()
|
l := d.decLen()
|
||||||
xtag = d.r.readn1()
|
xtag = d.r.readn1()
|
||||||
if verifyTag && xtag != tag {
|
if verifyTag && xtag != tag {
|
||||||
d.d.errorf("wrong extension tag. Got %b. Expecting: %v", xtag, tag)
|
d.d.errorf("Wrong extension tag. Got %b. Expecting: %v", xtag, tag)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
xbs = d.r.readx(l)
|
xbs = d.r.readx(l)
|
||||||
case simpleVdByteArray, simpleVdByteArray + 1,
|
case simpleVdByteArray, simpleVdByteArray + 1, simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
|
||||||
simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
|
xbs = d.DecodeBytes(nil, false, true)
|
||||||
xbs = d.DecodeBytes(nil, true)
|
|
||||||
default:
|
default:
|
||||||
d.d.errorf("ext - %s - expecting extensions/bytearray, got: 0x%x", msgBadDesc, d.bd)
|
d.d.errorf("Invalid d.bd for extensions (Expecting extensions or byte array). Got: 0x%x", d.bd)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
d.bdRead = false
|
d.bdRead = false
|
||||||
|
@ -526,7 +413,7 @@ func (d *simpleDecDriver) DecodeNaked() {
|
||||||
d.readNextBd()
|
d.readNextBd()
|
||||||
}
|
}
|
||||||
|
|
||||||
n := d.d.n
|
n := &d.d.n
|
||||||
var decodeFurther bool
|
var decodeFurther bool
|
||||||
|
|
||||||
switch d.bd {
|
switch d.bd {
|
||||||
|
@ -541,45 +428,39 @@ func (d *simpleDecDriver) DecodeNaked() {
|
||||||
case simpleVdPosInt, simpleVdPosInt + 1, simpleVdPosInt + 2, simpleVdPosInt + 3:
|
case simpleVdPosInt, simpleVdPosInt + 1, simpleVdPosInt + 2, simpleVdPosInt + 3:
|
||||||
if d.h.SignedInteger {
|
if d.h.SignedInteger {
|
||||||
n.v = valueTypeInt
|
n.v = valueTypeInt
|
||||||
n.i = d.DecodeInt64()
|
n.i = d.DecodeInt(64)
|
||||||
} else {
|
} else {
|
||||||
n.v = valueTypeUint
|
n.v = valueTypeUint
|
||||||
n.u = d.DecodeUint64()
|
n.u = d.DecodeUint(64)
|
||||||
}
|
}
|
||||||
case simpleVdNegInt, simpleVdNegInt + 1, simpleVdNegInt + 2, simpleVdNegInt + 3:
|
case simpleVdNegInt, simpleVdNegInt + 1, simpleVdNegInt + 2, simpleVdNegInt + 3:
|
||||||
n.v = valueTypeInt
|
n.v = valueTypeInt
|
||||||
n.i = d.DecodeInt64()
|
n.i = d.DecodeInt(64)
|
||||||
case simpleVdFloat32:
|
case simpleVdFloat32:
|
||||||
n.v = valueTypeFloat
|
n.v = valueTypeFloat
|
||||||
n.f = d.DecodeFloat64()
|
n.f = d.DecodeFloat(true)
|
||||||
case simpleVdFloat64:
|
case simpleVdFloat64:
|
||||||
n.v = valueTypeFloat
|
n.v = valueTypeFloat
|
||||||
n.f = d.DecodeFloat64()
|
n.f = d.DecodeFloat(false)
|
||||||
case simpleVdTime:
|
case simpleVdString, simpleVdString + 1, simpleVdString + 2, simpleVdString + 3, simpleVdString + 4:
|
||||||
n.v = valueTypeTime
|
|
||||||
n.t = d.DecodeTime()
|
|
||||||
case simpleVdString, simpleVdString + 1,
|
|
||||||
simpleVdString + 2, simpleVdString + 3, simpleVdString + 4:
|
|
||||||
n.v = valueTypeString
|
n.v = valueTypeString
|
||||||
n.s = d.DecodeString()
|
n.s = d.DecodeString()
|
||||||
case simpleVdByteArray, simpleVdByteArray + 1,
|
case simpleVdByteArray, simpleVdByteArray + 1, simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
|
||||||
simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
|
|
||||||
n.v = valueTypeBytes
|
n.v = valueTypeBytes
|
||||||
n.l = d.DecodeBytes(nil, false)
|
n.l = d.DecodeBytes(nil, false, false)
|
||||||
case simpleVdExt, simpleVdExt + 1, simpleVdExt + 2, simpleVdExt + 3, simpleVdExt + 4:
|
case simpleVdExt, simpleVdExt + 1, simpleVdExt + 2, simpleVdExt + 3, simpleVdExt + 4:
|
||||||
n.v = valueTypeExt
|
n.v = valueTypeExt
|
||||||
l := d.decLen()
|
l := d.decLen()
|
||||||
n.u = uint64(d.r.readn1())
|
n.u = uint64(d.r.readn1())
|
||||||
n.l = d.r.readx(l)
|
n.l = d.r.readx(l)
|
||||||
case simpleVdArray, simpleVdArray + 1, simpleVdArray + 2,
|
case simpleVdArray, simpleVdArray + 1, simpleVdArray + 2, simpleVdArray + 3, simpleVdArray + 4:
|
||||||
simpleVdArray + 3, simpleVdArray + 4:
|
|
||||||
n.v = valueTypeArray
|
n.v = valueTypeArray
|
||||||
decodeFurther = true
|
decodeFurther = true
|
||||||
case simpleVdMap, simpleVdMap + 1, simpleVdMap + 2, simpleVdMap + 3, simpleVdMap + 4:
|
case simpleVdMap, simpleVdMap + 1, simpleVdMap + 2, simpleVdMap + 3, simpleVdMap + 4:
|
||||||
n.v = valueTypeMap
|
n.v = valueTypeMap
|
||||||
decodeFurther = true
|
decodeFurther = true
|
||||||
default:
|
default:
|
||||||
d.d.errorf("cannot infer value - %s 0x%x", msgBadDesc, d.bd)
|
d.d.errorf("decodeNaked: Unrecognized d.bd: 0x%x", d.bd)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !decodeFurther {
|
if !decodeFurther {
|
||||||
|
@ -593,12 +474,12 @@ func (d *simpleDecDriver) DecodeNaked() {
|
||||||
// SimpleHandle is a Handle for a very simple encoding format.
|
// SimpleHandle is a Handle for a very simple encoding format.
|
||||||
//
|
//
|
||||||
// simple is a simplistic codec similar to binc, but not as compact.
|
// simple is a simplistic codec similar to binc, but not as compact.
|
||||||
// - Encoding of a value is always preceded by the descriptor byte (bd)
|
// - Encoding of a value is always preceeded by the descriptor byte (bd)
|
||||||
// - True, false, nil are encoded fully in 1 byte (the descriptor)
|
// - 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).
|
// - 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.
|
// There are positive (uintXXX and intXXX >= 0) and negative (intXXX < 0) integers.
|
||||||
// - Floats are encoded in 4 or 8 bytes (plus a descriptor byte)
|
// - Floats are encoded in 4 or 8 bytes (plus a descriptor byte)
|
||||||
// - Length of containers (strings, bytes, array, map, extensions)
|
// - Lenght of containers (strings, bytes, array, map, extensions)
|
||||||
// are encoded in 0, 1, 2, 4 or 8 bytes.
|
// are encoded in 0, 1, 2, 4 or 8 bytes.
|
||||||
// Zero-length containers have no length encoded.
|
// Zero-length containers have no length encoded.
|
||||||
// For others, the number of bytes is given by pow(2, bd%3)
|
// For others, the number of bytes is given by pow(2, bd%3)
|
||||||
|
@ -606,45 +487,31 @@ func (d *simpleDecDriver) DecodeNaked() {
|
||||||
// - arrays are encoded as [bd] [length] [value]...
|
// - arrays are encoded as [bd] [length] [value]...
|
||||||
// - extensions are encoded as [bd] [length] [tag] [byte]...
|
// - extensions are encoded as [bd] [length] [tag] [byte]...
|
||||||
// - strings/bytearrays are encoded as [bd] [length] [byte]...
|
// - strings/bytearrays are encoded as [bd] [length] [byte]...
|
||||||
// - time.Time are encoded as [bd] [length] [byte]...
|
|
||||||
//
|
//
|
||||||
// The full spec will be published soon.
|
// The full spec will be published soon.
|
||||||
type SimpleHandle struct {
|
type SimpleHandle struct {
|
||||||
BasicHandle
|
BasicHandle
|
||||||
binaryEncodingType
|
binaryEncodingType
|
||||||
noElemSeparators
|
|
||||||
// EncZeroValuesAsNil says to encode zero values for numbers, bool, string, etc as nil
|
|
||||||
EncZeroValuesAsNil bool
|
|
||||||
|
|
||||||
// _ [1]uint64 // padding
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name returns the name of the handle: simple
|
|
||||||
func (h *SimpleHandle) Name() string { return "simple" }
|
|
||||||
|
|
||||||
// SetBytesExt sets an extension
|
|
||||||
func (h *SimpleHandle) SetBytesExt(rt reflect.Type, tag uint64, ext BytesExt) (err error) {
|
func (h *SimpleHandle) SetBytesExt(rt reflect.Type, tag uint64, ext BytesExt) (err error) {
|
||||||
return h.SetExt(rt, tag, &extWrapper{ext, interfaceExtFailer{}})
|
return h.SetExt(rt, tag, &setExtWrapper{b: ext})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *SimpleHandle) hasElemSeparators() bool { return true } // as it implements Write(Map|Array)XXX
|
|
||||||
|
|
||||||
func (h *SimpleHandle) newEncDriver(e *Encoder) encDriver {
|
func (h *SimpleHandle) newEncDriver(e *Encoder) encDriver {
|
||||||
return &simpleEncDriver{e: e, w: e.w, h: h}
|
return &simpleEncDriver{e: e, w: e.w, h: h}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *SimpleHandle) newDecDriver(d *Decoder) decDriver {
|
func (h *SimpleHandle) newDecDriver(d *Decoder) decDriver {
|
||||||
return &simpleDecDriver{d: d, h: h, r: d.r, br: d.bytes}
|
return &simpleDecDriver{d: d, r: d.r, h: h, br: d.bytes}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *simpleEncDriver) reset() {
|
func (e *simpleEncDriver) reset() {
|
||||||
e.c = 0
|
|
||||||
e.w = e.e.w
|
e.w = e.e.w
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *simpleDecDriver) reset() {
|
func (d *simpleDecDriver) reset() {
|
||||||
d.c = 0
|
d.r = d.d.r
|
||||||
d.r, d.br = d.d.r, d.d.bytes
|
|
||||||
d.bd, d.bdRead = 0, false
|
d.bd, d.bdRead = 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ def get_test_data_list():
|
||||||
True,
|
True,
|
||||||
u"null",
|
u"null",
|
||||||
None,
|
None,
|
||||||
u"some&day>some<day",
|
u"someday",
|
||||||
1328176922000002000,
|
1328176922000002000,
|
||||||
u"",
|
u"",
|
||||||
-2206187877999998000,
|
-2206187877999998000,
|
||||||
|
@ -84,7 +84,7 @@ def doRpcServer(port, stopTimeSec):
|
||||||
def EchoStruct(self, msg):
|
def EchoStruct(self, msg):
|
||||||
return ("%s" % msg)
|
return ("%s" % msg)
|
||||||
|
|
||||||
addr = msgpackrpc.Address('127.0.0.1', port)
|
addr = msgpackrpc.Address('localhost', port)
|
||||||
server = msgpackrpc.Server(EchoHandler())
|
server = msgpackrpc.Server(EchoHandler())
|
||||||
server.listen(addr)
|
server.listen(addr)
|
||||||
# run thread to stop it after stopTimeSec seconds if > 0
|
# run thread to stop it after stopTimeSec seconds if > 0
|
||||||
|
@ -96,14 +96,14 @@ def doRpcServer(port, stopTimeSec):
|
||||||
server.start()
|
server.start()
|
||||||
|
|
||||||
def doRpcClientToPythonSvc(port):
|
def doRpcClientToPythonSvc(port):
|
||||||
address = msgpackrpc.Address('127.0.0.1', port)
|
address = msgpackrpc.Address('localhost', port)
|
||||||
client = msgpackrpc.Client(address, unpack_encoding='utf-8')
|
client = msgpackrpc.Client(address, unpack_encoding='utf-8')
|
||||||
print client.call("Echo123", "A1", "B2", "C3")
|
print client.call("Echo123", "A1", "B2", "C3")
|
||||||
print client.call("EchoStruct", {"A" :"Aa", "B":"Bb", "C":"Cc"})
|
print client.call("EchoStruct", {"A" :"Aa", "B":"Bb", "C":"Cc"})
|
||||||
|
|
||||||
def doRpcClientToGoSvc(port):
|
def doRpcClientToGoSvc(port):
|
||||||
# print ">>>> port: ", port, " <<<<<"
|
# print ">>>> port: ", port, " <<<<<"
|
||||||
address = msgpackrpc.Address('127.0.0.1', port)
|
address = msgpackrpc.Address('localhost', port)
|
||||||
client = msgpackrpc.Client(address, unpack_encoding='utf-8')
|
client = msgpackrpc.Client(address, unpack_encoding='utf-8')
|
||||||
print client.call("TestRpcInt.Echo123", ["A1", "B2", "C3"])
|
print client.call("TestRpcInt.Echo123", ["A1", "B2", "C3"])
|
||||||
print client.call("TestRpcInt.EchoStruct", {"A" :"Aa", "B":"Bb", "C":"Cc"})
|
print client.call("TestRpcInt.EchoStruct", {"A" :"Aa", "B":"Bb", "C":"Cc"})
|
||||||
|
|
|
@ -508,7 +508,7 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/http
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc/v20170312
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc/v20170312
|
||||||
# github.com/ucloud/ucloud-sdk-go v0.11.1
|
# github.com/ucloud/ucloud-sdk-go v0.12.0
|
||||||
github.com/ucloud/ucloud-sdk-go/private/protocol/http
|
github.com/ucloud/ucloud-sdk-go/private/protocol/http
|
||||||
github.com/ucloud/ucloud-sdk-go/private/utils
|
github.com/ucloud/ucloud-sdk-go/private/utils
|
||||||
github.com/ucloud/ucloud-sdk-go/services/uaccount
|
github.com/ucloud/ucloud-sdk-go/services/uaccount
|
||||||
|
@ -523,9 +523,9 @@ github.com/ucloud/ucloud-sdk-go/ucloud/log
|
||||||
github.com/ucloud/ucloud-sdk-go/ucloud/request
|
github.com/ucloud/ucloud-sdk-go/ucloud/request
|
||||||
github.com/ucloud/ucloud-sdk-go/ucloud/response
|
github.com/ucloud/ucloud-sdk-go/ucloud/response
|
||||||
github.com/ucloud/ucloud-sdk-go/ucloud/version
|
github.com/ucloud/ucloud-sdk-go/ucloud/version
|
||||||
# github.com/ufilesdk-dev/ufile-gosdk v0.0.0-20190730023212-866b183392c4
|
# github.com/ufilesdk-dev/ufile-gosdk v0.0.0-20190830075812-b4dbc4ef43a6
|
||||||
github.com/ufilesdk-dev/ufile-gosdk
|
github.com/ufilesdk-dev/ufile-gosdk
|
||||||
# github.com/ugorji/go v0.0.0-20180813092308-00b869d2f4a5
|
# github.com/ugorji/go v0.0.0-20151218193438-646ae4a518c1
|
||||||
github.com/ugorji/go/codec
|
github.com/ugorji/go/codec
|
||||||
# github.com/ulikunitz/xz v0.5.5
|
# github.com/ulikunitz/xz v0.5.5
|
||||||
github.com/ulikunitz/xz
|
github.com/ulikunitz/xz
|
||||||
|
|
Loading…
Reference in New Issue