go mod vendor

This commit is contained in:
Megan Marsh 2019-10-30 10:48:41 -07:00
parent 991af72758
commit 1ac41e91c1
47 changed files with 33633 additions and 33156 deletions

View File

@ -9,12 +9,23 @@ import (
"io"
"net/url"
"sort"
"time"
)
// Credential is the information of credential keys
type Credential struct {
PublicKey string
// UCloud Public Key
PublicKey string
// UCloud Private Key
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
@ -38,11 +49,18 @@ func (c *Credential) BuildCredentialedQuery(params map[string]string) string {
for k, v := range params {
urlValues.Set(k, v)
}
if len(c.SecurityToken) != 0 {
urlValues.Set("SecurityToken", c.SecurityToken)
}
urlValues.Set("PublicKey", c.PublicKey)
urlValues.Set("Signature", c.verifyAc(urlValues))
return urlValues.Encode()
}
func (c *Credential) IsExpired() bool {
return c.CanExpire && time.Now().After(c.Expires)
}
func (c *Credential) verifyAc(urlValues url.Values) string {
// sort keys
var keys []string

View File

@ -4,6 +4,7 @@ Package ucloud is a package of utilities to setup ucloud sdk and improve using e
package ucloud
import (
"fmt"
"time"
"github.com/ucloud/ucloud-sdk-go/private/utils"
@ -71,7 +72,7 @@ func (c *Client) SetHttpClient(httpClient http.Client) error {
return nil
}
// GetCredential will return the creadential config of client.
// GetCredential will return the credential config of client.
func (c *Client) GetCredential() *auth.Credential {
return c.credential
}
@ -108,6 +109,13 @@ func (c *Client) InvokeActionWithPatcher(action string, req request.Common, resp
req.SetRequestTime(time.Now())
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 {
req, err = handler(c, req)
if err != nil {
@ -142,7 +150,7 @@ func (c *Client) InvokeActionWithPatcher(action string, req request.Common, resp
if err == nil {
// 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()
for _, patch := range patches {

View File

@ -20,6 +20,8 @@ var (
// ErrUnexpected is the error for any unexpected error
ErrUnexpected = "client.UnexpectedError"
ErrCredentialExpired = "client.CredentialExpiredError"
)
// ClientError is the ucloud common errorfor server response

View File

@ -4,4 +4,4 @@ Package version is the version of sdk
package version
// Version see also semantic version: https://semver.org/
const Version = "0.11.1"
const Version = "0.12.0"

View File

@ -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.DownloadFile)
[比对本地与远程文件的 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)
[同步分片上传-带回调](https://godoc.org/pkg/github.com/ufilesdk-dev/ufile-gosdk/#UFileRequest.MPutWithPolicy)
[异步分片上传-带回调](https://godoc.org/pkg/github.com/ufilesdk-dev/ufile-gosdk/#UFileRequest.AsyncMPutWithPolicy)

View File

@ -30,7 +30,7 @@ func NewAuth(publicKey, privateKey string) Auth {
//Authorization 构造一个主要用于上传文件的签名,返回 HMAC-Sh1 的签名字符串,可以直接填充到 HTTP authorization header 里面。
//key 是传到 ufile 所使用的文件名bucekt 是文件上传后存放的 bucket。
//method 就是你当前这个 HTTP 请求的 Method。
//header 就是你当前这个 HTTP 的 header,我们主要拿里面的 content-type 来做签名 hash 计算
//header 就是你当前这个 HTTP 的 header
func (A Auth) Authorization(method, bucket, key string, header http.Header) string {
var sigData string
method = strings.ToUpper(method)
@ -40,6 +40,7 @@ func (A Auth) Authorization(method, bucket, key string, header http.Header) stri
date := header.Get("Date")
sigData = method + "\n" + md5 + "\n" + contentType + "\n" + date + "\n"
sigData += A.CanonicalizedUcloudHeaders(header)
resource := "/" + bucket + "/" + key
sigData += resource
@ -114,3 +115,25 @@ func (A Auth) AuthorizationBucketMgr(query url.Values) string {
query.Add("Signature", fmt.Sprintf("%x", h.Sum(nil)))
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
}

View File

@ -378,3 +378,42 @@ func (u *UFileRequest) ClassSwitch(keyName string, storageClass string) (err err
req.Header.Add("authorization", authorization)
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)
}

View File

@ -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.
/*
Package codec provides a
High Performance, Feature-Rich Idiomatic Go 1.4+ codec/encoding library
for binc, msgpack, cbor, json.
High Performance, Feature-Rich Idiomatic Go codec/encoding library for
binc, msgpack, cbor, json.
Supported Serialization formats are:
@ -18,11 +17,15 @@ To install:
go get github.com/ugorji/go/codec
This package will carefully use 'unsafe' for performance reasons in specific places.
You can build without unsafe use by passing the safe or appengine tag
i.e. 'go install -tags=safe ...'. Note that unsafe is only supported for the last 3
go sdk versions e.g. current go release is go 1.9, so we support unsafe use only from
go 1.7+ . This is because supporting unsafe requires knowledge of implementation details.
This package understands the 'unsafe' tag, to allow using unsafe semantics:
- When decoding into a struct, you need to read the field name as a string
so you can find the struct field it is mapped to.
Using `unsafe` will bypass the allocation and copying overhead of []byte->string conversion.
To install using unsafe, pass the 'unsafe' tag:
go get -tags=unsafe github.com/ugorji/go/codec
For detailed usage information, read the primer at http://ugorji.net/blog/go-codec-primer .
@ -32,15 +35,11 @@ the standard library (ie json, xml, gob, etc).
Rich Feature Set includes:
- 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.
Our extensive benchmarks show us outperforming Gob, Json, Bson, etc by 2-4X.
- Careful selected use of 'unsafe' for targeted performance gains.
100% mode exists where 'unsafe' is not used at all.
- Lock-free (sans mutex) concurrency for scaling to 100's of cores
- Coerce types where appropriate
e.g. decode an int in the stream into a float, decode numbers from formatted strings, etc
- Multiple conversions:
Package coerces types where appropriate
e.g. decode an int in the stream into a float, etc.
- Corner Cases:
Overflows, nil maps/slices, nil values in streams are handled correctly
- Standard field renaming via tags
@ -49,16 +48,10 @@ Rich Feature Set includes:
(struct, slice, map, primitives, pointers, interface{}, etc)
- Extensions to support efficient encoding/decoding of any named types
- Support encoding.(Binary|Text)(M|Unm)arshaler interfaces
- Support IsZero() bool to determine if a value is a zero value.
Analogous to time.Time.IsZero() bool.
- Decoding without a schema (into a interface{}).
Includes Options to configure what specific map or slice type to use
when decoding an encoded list or map into a nil interface{}
- Mapping a non-interface type to an interface, so we can decode appropriately
into any interface type with a correctly configured non-interface value.
- Encode a struct as an array, and decode struct from an array in the data stream
- Option to encode struct keys as numbers (instead of strings)
(to support structured streams with fields encoded as numeric codes)
- Comprehensive support for anonymous fields
- Fast (no-reflection) encoding/decoding of common maps and slices
- Code-generation for faster performance.
@ -75,7 +68,7 @@ Rich Feature Set includes:
- Encode/Decode from/to chan types (for iterative streaming support)
- Drop-in replacement for encoding/json. `json:` key in struct tag supported.
- Provides a RPC Server and Client Codec for net/rpc communication protocol.
- Handle unique 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, provide rpc server/client codec to support
msgpack-rpc protocol defined at:
@ -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
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 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)
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
// 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:
// - 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:
// - To make Handle comparable, make extHandle in BasicHandle a non-embedded pointer,
// and use overlay methods on *BasicHandle to call through to extHandle after initializing
// the "xh *extHandle" to point to a real slice.
//
// BEFORE EACH RELEASE:
// - Look through and fix padding for each type, to eliminate false sharing
// - critical shared objects that are read many times
// TypeInfos
// - pooled objects:
// decNaked, decNakedContainers, codecFner, typeInfoLoadArray,
// - small objects allocated independently, that we read/use much across threads:
// codecFn, typeInfo
// - Objects allocated independently and used a lot
// Decoder, Encoder,
// xxxHandle, xxxEncDriver, xxxDecDriver (xxx = json, msgpack, cbor, binc, simple)
// - In all above, arrange values modified together to be close to each other.
//
// For all of these, either ensure that they occupy full cache lines,
// or ensure that the things just past the cache line boundary are hardly read/written
// e.g. JsonHandle.RawBytesExt - which is copied into json(En|De)cDriver at init
//
// Occupying full cache lines means they occupy 8*N words (where N is an integer).
// Check this out by running: ./run.sh -z
// - look at those tagged ****, meaning they are not occupying full cache lines
// - look at those tagged <<<<, meaning they are larger than 32 words (something to watch)
// - Run "golint -min_confidence 0.81"
// - optimization for codecgen:
// if len of entity is <= 3 words, then support a value receiver for encode.
// - (En|De)coder should store an error when it occurs.
// Until reset, subsequent calls return that error that was stored.
// This means that free panics must go away.
// All errors must be raised through errorf method.
// - Decoding using a chan is good, but incurs concurrency costs.
// This is because there's no fast way to use a channel without it
// having to switch goroutines constantly.
// Callback pattern is still the best. Maybe cnsider supporting something like:
// type X struct {
// Name string
// Ys []Y
// Ys chan <- Y
// Ys func(Y) -> call this function for each entry
// }
// - Consider adding a isZeroer interface { isZero() bool }
// It is used within isEmpty, for omitEmpty support.
// - Consider making Handle used AS-IS within the encoding/decoding session.
// This means that we don't cache Handle information within the (En|De)coder,
// except we really need it at Reset(...)
// - Consider adding math/big support
// - Consider reducing the size of the generated functions:
// Maybe use one loop, and put the conditionals in the loop.
// for ... { if cLen > 0 { if j == cLen { break } } else if dd.CheckBreak() { break } }

View File

@ -15,11 +15,17 @@ To install:
go get github.com/ugorji/go/codec
This package will carefully use 'unsafe' for performance reasons in specific places.
You can build without unsafe use by passing the safe or appengine tag
i.e. 'go install -tags=safe ...'. Note that unsafe is only supported for the last 3
go sdk versions e.g. current go release is go 1.9, so we support unsafe use only from
go 1.7+ . This is because supporting unsafe requires knowledge of implementation details.
This package understands the `unsafe` tag, to allow using unsafe semantics:
- When decoding into a struct, you need to read the field name as a string
so you can find the struct field it is mapped to.
Using `unsafe` will bypass the allocation and copying overhead of `[]byte->string` conversion.
To use it, you must pass the `unsafe` tag during install:
```
go install -tags=unsafe github.com/ugorji/go/codec
```
Online documentation: http://godoc.org/github.com/ugorji/go/codec
Detailed Usage/How-to Primer: http://ugorji.net/blog/go-codec-primer
@ -30,15 +36,11 @@ the standard library (ie json, xml, gob, etc).
Rich Feature Set includes:
- 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.
Our extensive benchmarks show us outperforming Gob, Json, Bson, etc by 2-4X.
- Careful selected use of 'unsafe' for targeted performance gains.
100% mode exists where 'unsafe' is not used at all.
- Lock-free (sans mutex) concurrency for scaling to 100's of cores
- Coerce types where appropriate
e.g. decode an int in the stream into a float, decode numbers from formatted strings, etc
- Multiple conversions:
Package coerces types where appropriate
e.g. decode an int in the stream into a float, etc.
- Corner Cases:
Overflows, nil maps/slices, nil values in streams are handled correctly
- Standard field renaming via tags
@ -47,16 +49,10 @@ Rich Feature Set includes:
(struct, slice, map, primitives, pointers, interface{}, etc)
- Extensions to support efficient encoding/decoding of any named types
- Support encoding.(Binary|Text)(M|Unm)arshaler interfaces
- Support IsZero() bool to determine if a value is a zero value.
Analogous to time.Time.IsZero() bool.
- Decoding without a schema (into a interface{}).
Includes Options to configure what specific map or slice type to use
when decoding an encoded list or map into a nil interface{}
- Mapping a non-interface type to an interface, so we can decode appropriately
into any interface type with a correctly configured non-interface value.
- Encode a struct as an array, and decode struct from an array in the data stream
- Option to encode struct keys as numbers (instead of strings)
(to support structured streams with fields encoded as numeric codes)
- Comprehensive support for anonymous fields
- Fast (no-reflection) encoding/decoding of common maps and slices
- Code-generation for faster performance.
@ -72,7 +68,7 @@ Rich Feature Set includes:
- Encode/Decode from/to chan types (for iterative streaming support)
- Drop-in replacement for encoding/json. `json:` key in struct tag supported.
- Provides a RPC Server and Client Codec for net/rpc communication protocol.
- Handle unique 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, provide rpc server/client codec to support
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
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 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)
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.

View File

@ -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.
package codec
@ -55,77 +55,39 @@ const (
// 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 {
e *Encoder
h *BincHandle
w encWriter
m map[string]uint16 // symbols
b [16]byte // scratch, used for encoding numbers - bigendian style
s uint16 // symbols sequencer
// c containerState
encDriverTrackContainerWriter
noBuiltInTypes
// encNoSeparator
b [scratchByteArrayLen]byte
s uint16 // symbols sequencer
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() {
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) {
if b {
e.w.writen1(bincVdSpecial<<4 | bincSpTrue)
@ -233,21 +195,15 @@ func (e *bincEncDriver) encodeExtPreamble(xtag byte, length int) {
e.w.writen1(xtag)
}
func (e *bincEncDriver) WriteArrayStart(length int) {
func (e *bincEncDriver) EncodeArrayStart(length int) {
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.c = containerMapStart
}
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))
e.encBytesLen(c, l)
if l > 0 {
@ -257,7 +213,7 @@ func (e *bincEncDriver) EncodeString(c charEncoding, v string) {
func (e *bincEncDriver) EncodeSymbol(v string) {
// if WriteSymbolsNoRefs {
// e.encodeString(cUTF8, v)
// e.encodeString(c_UTF8, v)
// return
// }
@ -267,10 +223,10 @@ func (e *bincEncDriver) EncodeSymbol(v string) {
l := len(v)
if l == 0 {
e.encBytesLen(cUTF8, 0)
e.encBytesLen(c_UTF8, 0)
return
} else if l == 1 {
e.encBytesLen(cUTF8, 1)
e.encBytesLen(c_UTF8, 1)
e.w.writen1(v[0])
return
}
@ -320,10 +276,6 @@ func (e *bincEncDriver) EncodeSymbol(v string) {
}
func (e *bincEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
if v == nil {
e.EncodeNil()
return
}
l := uint64(len(v))
e.encBytesLen(c, l)
if l > 0 {
@ -333,7 +285,7 @@ func (e *bincEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
func (e *bincEncDriver) encBytesLen(c charEncoding, length uint64) {
//TODO: support bincUnicodeOther (for now, just use string or bytearray)
if c == cRAW {
if c == c_RAW {
e.encLen(bincVdByteArray<<4, length)
} else {
e.encLen(bincVdString<<4, length)
@ -372,9 +324,6 @@ type bincDecSymbol struct {
}
type bincDecDriver struct {
decDriverNoopContainerReader
noBuiltInTypes
d *Decoder
h *BincHandle
r decReader
@ -383,15 +332,13 @@ type bincDecDriver struct {
bd byte
vd byte
vs byte
_ [3]byte // padding
noStreamingCodec
decNoSeparator
b [scratchByteArrayLen]byte
// linear searching on this slice is ok,
// because we typically expect < 32 symbols in each stream.
s []bincDecSymbol
// noStreamingCodec
// decNoSeparator
b [8 * 8]byte // scratch
}
func (d *bincDecDriver) readNextBd() {
@ -401,17 +348,7 @@ func (d *bincDecDriver) readNextBd() {
d.bdRead = true
}
func (d *bincDecDriver) uncacheRead() {
if d.bdRead {
d.r.unreadn1()
d.bdRead = false
}
}
func (d *bincDecDriver) ContainerType() (vt valueType) {
if !d.bdRead {
d.readNextBd()
}
if d.vd == bincVdSpecial && d.vs == bincSpNil {
return valueTypeNil
} else if d.vd == bincVdByteArray {
@ -422,10 +359,9 @@ func (d *bincDecDriver) ContainerType() (vt valueType) {
return valueTypeArray
} else if d.vd == bincVdMap {
return valueTypeMap
} else {
// d.d.errorf("isContainerType: unsupported parameter: %v", vt)
}
// else {
// d.d.errorf("isContainerType: unsupported parameter: %v", vt)
// }
return valueTypeUnset
}
@ -440,24 +376,27 @@ func (d *bincDecDriver) TryDecodeAsNil() bool {
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 {
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
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) {
@ -466,7 +405,7 @@ func (d *bincDecDriver) decFloatPre(vs, defaultLen byte) {
} else {
l := d.r.readn1()
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
}
for i := l; i < 8; i++ {
@ -485,7 +424,7 @@ func (d *bincDecDriver) decFloat() (f float64) {
d.decFloatPre(d.vs, 8)
f = math.Float64frombits(bigen.Uint64(d.b[0:8]))
} 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
@ -542,38 +481,49 @@ func (d *bincDecDriver) decCheckInteger() (ui uint64, neg bool) {
neg = true
ui = 1
} else {
d.d.errorf("integer decode fails - invalid special value from descriptor %x-%x/%s",
d.vd, d.vs, bincdesc(d.vd, d.vs))
d.d.errorf("numeric decode fails for special value: d.vs: 0x%x", d.vs)
return
}
} 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
}
func (d *bincDecDriver) DecodeInt64() (i int64) {
func (d *bincDecDriver) DecodeInt(bitsize uint8) (i int64) {
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 {
i = -i
}
d.bdRead = false
return
}
func (d *bincDecDriver) DecodeUint64() (ui uint64) {
ui, neg := d.decCheckInteger()
if neg {
d.d.errorf("assigning negative signed value to unsigned integer type")
if chkOvf.Int(i, bitsize) {
d.d.errorf("binc: overflow integer: %v", i)
return
}
d.bdRead = false
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 {
d.readNextBd()
}
@ -589,14 +539,17 @@ func (d *bincDecDriver) DecodeFloat64() (f float64) {
} else if vs == bincSpNegInf {
return math.Inf(-1)
} else {
d.d.errorf("float - invalid special value from descriptor %x-%x/%s",
d.vd, d.vs, bincdesc(d.vd, d.vs))
d.d.errorf("Invalid d.vs decoding float where d.vd=bincVdSpecial: %v", d.vs)
return
}
} else if vd == bincVdFloat {
f = d.decFloat()
} 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
return
@ -612,7 +565,7 @@ func (d *bincDecDriver) DecodeBool() (b bool) {
} else if bd == (bincVdSpecial | bincSpTrue) {
b = true
} 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
}
d.bdRead = false
@ -620,11 +573,8 @@ func (d *bincDecDriver) DecodeBool() (b bool) {
}
func (d *bincDecDriver) ReadMapStart() (length int) {
if !d.bdRead {
d.readNextBd()
}
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
}
length = d.decLen()
@ -633,11 +583,8 @@ func (d *bincDecDriver) ReadMapStart() (length int) {
}
func (d *bincDecDriver) ReadArrayStart() (length int) {
if !d.bdRead {
d.readNextBd()
}
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
}
length = d.decLen()
@ -668,8 +615,7 @@ func (d *bincDecDriver) decLenNumber() (v uint64) {
return
}
func (d *bincDecDriver) decStringAndBytes(bs []byte, withString, zerocopy bool) (
bs2 []byte, s string) {
func (d *bincDecDriver) decStringAndBytes(bs []byte, withString, zerocopy bool) (bs2 []byte, s string) {
if !d.bdRead {
d.readNextBd()
}
@ -677,7 +623,7 @@ func (d *bincDecDriver) decStringAndBytes(bs []byte, withString, zerocopy bool)
d.bdRead = false
return
}
var slen = -1
var slen int = -1
// var ok bool
switch d.vd {
case bincVdString, bincVdByteArray:
@ -686,12 +632,12 @@ func (d *bincDecDriver) decStringAndBytes(bs []byte, withString, zerocopy bool)
if d.br {
bs2 = d.r.readx(slen)
} else if len(bs) == 0 {
bs2 = decByteSlice(d.r, slen, d.d.h.MaxInitLen, d.b[:])
bs2 = decByteSlice(d.r, slen, d.b[:])
} else {
bs2 = decByteSlice(d.r, slen, d.d.h.MaxInitLen, bs)
bs2 = decByteSlice(d.r, slen, bs)
}
} else {
bs2 = decByteSlice(d.r, slen, d.d.h.MaxInitLen, bs)
bs2 = decByteSlice(d.r, slen, bs)
}
if withString {
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
// the parameter bs in the map, as it might be a shared buffer.
// bs2 = decByteSlice(d.r, slen, bs)
bs2 = decByteSlice(d.r, slen, d.d.h.MaxInitLen, nil)
bs2 = decByteSlice(d.r, slen, nil)
if withString {
s = string(bs2)
}
d.s = append(d.s, bincDecSymbol{i: symbol, s: s, b: bs2})
}
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
}
d.bdRead = false
@ -758,19 +705,18 @@ func (d *bincDecDriver) decStringAndBytes(bs []byte, withString, zerocopy bool)
}
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.
// return string(d.DecodeBytes(d.b[:], true, true))
_, s = d.decStringAndBytes(d.b[:], true, true)
return
}
func (d *bincDecDriver) DecodeStringAsBytes() (s []byte) {
s, _ = d.decStringAndBytes(d.b[:], false, true)
return
}
func (d *bincDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
func (d *bincDecDriver) DecodeBytes(bs []byte, isstring, zerocopy bool) (bsOut []byte) {
if isstring {
bsOut, _ = d.decStringAndBytes(bs, false, zerocopy)
return
}
if !d.bdRead {
d.readNextBd()
}
@ -778,16 +724,12 @@ func (d *bincDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
d.bdRead = false
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
if d.vd == bincVdString || d.vd == bincVdByteArray {
clen = d.decLen()
} 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
}
d.bdRead = false
@ -798,12 +740,12 @@ func (d *bincDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
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) {
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
}
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()
xtag = d.r.readn1()
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
}
xbs = d.r.readx(l)
} else if d.vd == bincVdByteArray {
xbs = d.DecodeBytes(nil, true)
xbs = d.DecodeBytes(nil, false, true)
} 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
}
d.bdRead = false
@ -845,7 +787,7 @@ func (d *bincDecDriver) DecodeNaked() {
d.readNextBd()
}
n := d.d.n
n := &d.d.n
var decodeFurther bool
switch d.vd {
@ -878,7 +820,7 @@ func (d *bincDecDriver) DecodeNaked() {
n.v = valueTypeInt
n.i = int64(-1) // int8(-1)
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:
n.v = valueTypeUint
@ -900,10 +842,10 @@ func (d *bincDecDriver) DecodeNaked() {
n.s = d.DecodeString()
case bincVdByteArray:
n.v = valueTypeBytes
n.l = d.DecodeBytes(nil, false)
n.l = d.DecodeBytes(nil, false, false)
case bincVdTimestamp:
n.v = valueTypeTime
tt, err := bincDecodeTime(d.r.readx(int(d.vs)))
n.v = valueTypeTimestamp
tt, err := decodeTime(d.r.readx(int(d.vs)))
if err != nil {
panic(err)
}
@ -920,7 +862,7 @@ func (d *bincDecDriver) DecodeNaked() {
n.v = valueTypeMap
decodeFurther = true
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 {
@ -950,219 +892,31 @@ func (d *bincDecDriver) DecodeNaked() {
type BincHandle struct {
BasicHandle
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) {
return h.SetExt(rt, tag, &extWrapper{ext, interfaceExtFailer{}})
return h.SetExt(rt, tag, &setExtWrapper{b: ext})
}
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 {
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() {
e.w = e.e.w
e.s = 0
e.c = 0
e.m = nil
}
func (d *bincDecDriver) reset() {
d.r, d.br = d.d.r, d.d.bytes
d.r = d.d.r
d.s = nil
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 _ encDriver = (*bincEncDriver)(nil)

View File

@ -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 "$@"

View File

@ -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.
package codec
@ -6,7 +6,6 @@ package codec
import (
"math"
"reflect"
"time"
)
const (
@ -39,8 +38,6 @@ const (
cborBdBreak = 0xff
)
// These define some in-stream descriptors for
// manual encoding e.g. when doing explicit indefinite-length
const (
CborStreamBytes byte = 0x5f
CborStreamString = 0x7f
@ -60,56 +57,15 @@ const (
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 {
noBuiltInTypes
encDriverNoopContainerWriter
encNoSeparator
e *Encoder
w encWriter
h *CborHandle
x [8]byte
// _ [3]uint64 // padding
}
func (e *cborEncDriver) EncodeNil() {
@ -167,24 +123,6 @@ func (e *cborEncDriver) encLen(bd byte, length int) {
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) {
e.encUint(uint64(xtag), cborBaseTag)
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) {
e.encUint(uint64(re.Tag), cborBaseTag)
// only encodes re.Value (never re.Data)
// if false && re.Data != nil {
// en.encode(re.Data)
// } else if re.Value != nil {
if re.Value != nil {
en.encode(re.Value)
} else {
if re.Data != nil {
en.encode(re.Data)
} else if re.Value == nil {
e.EncodeNil()
}
}
func (e *cborEncDriver) WriteArrayStart(length int) {
if e.h.IndefiniteLength {
e.w.writen1(cborBdIndefiniteArray)
} else {
e.encLen(cborBaseArray, length)
en.encode(re.Value)
}
}
func (e *cborEncDriver) WriteMapStart(length int) {
if e.h.IndefiniteLength {
e.w.writen1(cborBdIndefiniteMap)
} else {
e.encLen(cborBaseMap, length)
}
func (e *cborEncDriver) EncodeArrayStart(length int) {
e.encLen(cborBaseArray, length)
}
func (e *cborEncDriver) WriteMapEnd() {
if e.h.IndefiniteLength {
e.w.writen1(cborBdBreak)
}
}
func (e *cborEncDriver) WriteArrayEnd() {
if e.h.IndefiniteLength {
e.w.writen1(cborBdBreak)
}
func (e *cborEncDriver) EncodeMapStart(length int) {
e.encLen(cborBaseMap, length)
}
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) {
if v == nil {
e.EncodeNil()
} else if c == cRAW {
e.encStringBytesS(cborBaseBytes, stringView(v))
if c == c_RAW {
e.encLen(cborBaseBytes, len(v))
} else {
e.encStringBytesS(cborBaseString, stringView(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.encLen(cborBaseString, len(v))
}
e.w.writeb(v)
}
// ----------------------
@ -287,13 +175,12 @@ type cborDecDriver struct {
d *Decoder
h *CborHandle
r decReader
b [scratchByteArrayLen]byte
br bool // bytes reader
bdRead bool
bd byte
noBuiltInTypes
// decNoSeparator
decDriverNoopContainerReader
// _ [3]uint64 // padding
decNoSeparator
}
func (d *cborDecDriver) readNextBd() {
@ -301,17 +188,7 @@ func (d *cborDecDriver) readNextBd() {
d.bdRead = true
}
func (d *cborDecDriver) uncacheRead() {
if d.bdRead {
d.r.unreadn1()
d.bdRead = false
}
}
func (d *cborDecDriver) ContainerType() (vt valueType) {
if !d.bdRead {
d.readNextBd()
}
if d.bd == cborBdNil {
return valueTypeNil
} else if d.bd == cborBdIndefiniteBytes || (d.bd >= cborBaseBytes && d.bd < cborBaseString) {
@ -322,10 +199,9 @@ func (d *cborDecDriver) ContainerType() (vt valueType) {
return valueTypeArray
} else if d.bd == cborBdIndefiniteMap || (d.bd >= cborBaseMap && d.bd < cborBaseTag) {
return valueTypeMap
} else {
// d.d.errorf("isContainerType: unsupported parameter: %v", vt)
}
// else {
// d.d.errorf("isContainerType: unsupported parameter: %v", vt)
// }
return valueTypeUnset
}
@ -366,7 +242,7 @@ func (d *cborDecDriver) decUint() (ui uint64) {
} else if v == 0x1b {
ui = uint64(bigen.Uint64(d.r.readx(8)))
} 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
}
}
@ -382,36 +258,52 @@ func (d *cborDecDriver) decCheckInteger() (neg bool) {
} else if major == cborMajorNegInt {
neg = true
} 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
}
func (d *cborDecDriver) DecodeInt64() (i int64) {
func (d *cborDecDriver) DecodeInt(bitsize uint8) (i int64) {
neg := d.decCheckInteger()
ui := d.decUint()
// check if this number can be converted to an int without overflow
var overflow bool
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 {
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
return
}
func (d *cborDecDriver) DecodeUint64() (ui uint64) {
func (d *cborDecDriver) DecodeUint(bitsize uint8) (ui uint64) {
if d.decCheckInteger() {
d.d.errorf("assigning negative signed value to unsigned type")
d.d.errorf("Assigning negative signed value to unsigned type")
return
}
ui = d.decUint()
if chkOvf.Uint(ui, bitsize) {
d.d.errorf("cbor: overflow integer: %v", ui)
return
}
d.bdRead = false
return
}
func (d *cborDecDriver) DecodeFloat64() (f float64) {
func (d *cborDecDriver) DecodeFloat(chkOverflow32 bool) (f float64) {
if !d.bdRead {
d.readNextBd()
}
@ -422,9 +314,13 @@ func (d *cborDecDriver) DecodeFloat64() (f float64) {
} else if bd == cborBdFloat64 {
f = math.Float64frombits(bigen.Uint64(d.r.readx(8)))
} else if bd >= cborBaseUint && bd < cborBaseBytes {
f = float64(d.DecodeInt64())
f = float64(d.DecodeInt(64))
} 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
}
d.bdRead = false
@ -440,7 +336,7 @@ func (d *cborDecDriver) DecodeBool() (b bool) {
b = true
} else if bd == cborBdFalse {
} 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
}
d.bdRead = false
@ -448,9 +344,6 @@ func (d *cborDecDriver) DecodeBool() (b bool) {
}
func (d *cborDecDriver) ReadMapStart() (length int) {
if !d.bdRead {
d.readNextBd()
}
d.bdRead = false
if d.bd == cborBdIndefiniteMap {
return -1
@ -459,9 +352,6 @@ func (d *cborDecDriver) ReadMapStart() (length int) {
}
func (d *cborDecDriver) ReadArrayStart() (length int) {
if !d.bdRead {
d.readNextBd()
}
d.bdRead = false
if d.bd == cborBdIndefiniteArray {
return -1
@ -480,8 +370,7 @@ func (d *cborDecDriver) decAppendIndefiniteBytes(bs []byte) []byte {
break
}
if major := d.bd >> 5; major != cborMajorBytes && major != cborMajorText {
d.d.errorf("expect bytes/string major type in indefinite string/bytes;"+
" got major %v from descriptor %x/%x", major, d.bd, cbordesc(d.bd))
d.d.errorf("cbor: expect bytes or string major type in indefinite string/bytes; got: %v, byte: %v", major, d.bd)
return nil
}
n := d.decLen()
@ -502,7 +391,7 @@ func (d *cborDecDriver) decAppendIndefiniteBytes(bs []byte) []byte {
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 {
d.readNextBd()
}
@ -511,84 +400,25 @@ func (d *cborDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
return nil
}
if d.bd == cborBdIndefiniteBytes || d.bd == cborBdIndefiniteString {
d.bdRead = false
if bs == nil {
if zerocopy {
return d.decAppendIndefiniteBytes(d.d.b[:0])
}
return d.decAppendIndefiniteBytes(zeroByteSlice)
return d.decAppendIndefiniteBytes(nil)
}
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()
d.bdRead = false
if zerocopy {
if d.br {
return d.r.readx(clen)
} 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) {
return string(d.DecodeBytes(d.d.b[:], 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
return string(d.DecodeBytes(d.b[:], true, true))
}
func (d *cborDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) {
@ -619,7 +449,7 @@ func (d *cborDecDriver) DecodeNaked() {
d.readNextBd()
}
n := d.d.n
n := &d.d.n
var decodeFurther bool
switch d.bd {
@ -631,12 +461,15 @@ func (d *cborDecDriver) DecodeNaked() {
case cborBdTrue:
n.v = valueTypeBool
n.b = true
case cborBdFloat16, cborBdFloat32, cborBdFloat64:
case cborBdFloat16, cborBdFloat32:
n.v = valueTypeFloat
n.f = d.DecodeFloat64()
n.f = d.DecodeFloat(true)
case cborBdFloat64:
n.v = valueTypeFloat
n.f = d.DecodeFloat(false)
case cborBdIndefiniteBytes:
n.v = valueTypeBytes
n.l = d.DecodeBytes(nil, false)
n.l = d.DecodeBytes(nil, false, false)
case cborBdIndefiniteString:
n.v = valueTypeString
n.s = d.DecodeString()
@ -651,17 +484,17 @@ func (d *cborDecDriver) DecodeNaked() {
case d.bd >= cborBaseUint && d.bd < cborBaseNegInt:
if d.h.SignedInteger {
n.v = valueTypeInt
n.i = d.DecodeInt64()
n.i = d.DecodeInt(64)
} else {
n.v = valueTypeUint
n.u = d.DecodeUint64()
n.u = d.DecodeUint(64)
}
case d.bd >= cborBaseNegInt && d.bd < cborBaseBytes:
n.v = valueTypeInt
n.i = d.DecodeInt64()
n.i = d.DecodeInt(64)
case d.bd >= cborBaseBytes && d.bd < cborBaseString:
n.v = valueTypeBytes
n.l = d.DecodeBytes(nil, false)
n.l = d.DecodeBytes(nil, false, false)
case d.bd >= cborBaseString && d.bd < cborBaseArray:
n.v = valueTypeString
n.s = d.DecodeString()
@ -675,11 +508,6 @@ func (d *cborDecDriver) DecodeNaked() {
n.v = valueTypeExt
n.u = d.decUint()
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.d.decode(&re.Value) // handled by decode itself.
// 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.
// Users can implement them as needed (using SetExt), including spec-documented ones:
// - timestamp, BigNum, BigFloat, Decimals,
// - Encoded Text (e.g. URL, regexp, base64, MIME Message), etc.
// - timestamp, BigNum, BigFloat, Decimals, 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 {
binaryEncodingType
noElemSeparators
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) {
return h.SetExt(rt, tag, &extWrapper{bytesExtFailer{}, ext})
return h.SetExt(rt, tag, &setExtWrapper{i: ext})
}
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 {
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() {
@ -748,7 +577,7 @@ func (e *cborEncDriver) 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
}

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

View File

@ -3,7 +3,10 @@
// 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 fast-path.go.tmpl - DO NOT EDIT.
// ************************************************************
// DO NOT EDIT.
// THIS FILE IS AUTO-GENERATED from fast-path.go.tmpl
// ************************************************************
package codec
@ -15,19 +18,19 @@ package codec
// This file can be omitted without causing a build failure.
//
// The advantage of fast paths is:
// - Many calls bypass reflection altogether
// - Many calls bypass reflection altogether
//
// Currently support
// - slice of all builtin types,
// - map of all builtin types to string or interface value
// - symmetrical maps of all builtin types (e.g. str-str, uint8-uint8)
// - slice of all builtin types,
// - map of all builtin types to string or interface value
// - symetrical maps of all builtin types (e.g. str-str, uint8-uint8)
// This should provide adequate "typical" implementations.
//
// Note that fast track decode functions must handle values for which an address cannot be obtained.
// For example:
// m2 := map[string]int{}
// p2 := []interface{}{m2}
// // decoding into p2 will bomb if fast track functions do not treat like unaddressable.
// m2 := map[string]int{}
// p2 := []interface{}{m2}
// // decoding into p2 will bomb if fast track functions do not treat like unaddressable.
//
import (
@ -35,7 +38,8 @@ import (
"sort"
)
const fastpathEnabled = true
const fastpathCheckNilFalse = false // for reflect
const fastpathCheckNilTrue = true // for type switch
type fastpathT struct {}
@ -44,8 +48,8 @@ var fastpathTV fastpathT
type fastpathE struct {
rtid uintptr
rt reflect.Type
encfn func(*Encoder, *codecFnInfo, reflect.Value)
decfn func(*Decoder, *codecFnInfo, reflect.Value)
encfn func(*encFnInfo, reflect.Value)
decfn func(*decFnInfo, reflect.Value)
}
type fastpathA [{{ .FastpathLen }}]fastpathE
@ -77,22 +81,23 @@ var fastpathAV fastpathA
// due to possible initialization loop error, make fastpath in an init()
func init() {
if !fastpathEnabled {
return
}
i := 0
fn := func(v interface{},
fe func(*Encoder, *codecFnInfo, reflect.Value),
fd func(*Decoder, *codecFnInfo, reflect.Value)) (f fastpathE) {
fn := func(v interface{}, fe func(*encFnInfo, reflect.Value), fd func(*decFnInfo, reflect.Value)) (f fastpathE) {
xrt := reflect.TypeOf(v)
xptr := rt2id(xrt)
xptr := reflect.ValueOf(xrt).Pointer()
fastpathAV[i] = fastpathE{xptr, xrt, fe, fd}
i++
return
}
{{/* do not register []uint8 in fast-path */}}
{{range .Values}}{{if not .Primitive}}{{if not .MapKey }}{{if ne .Elem "uint8"}}
fn([]{{ .Elem }}(nil), (*Encoder).{{ .MethodNamePfx "fastpathEnc" false }}R, (*Decoder).{{ .MethodNamePfx "fastpathDec" false }}R){{end}}{{end}}{{end}}{{end}}
{{range .Values}}{{if not .Primitive}}{{if not .MapKey }}
fn([]{{ .Elem }}(nil), (*encFnInfo).{{ .MethodNamePfx "fastpathEnc" false }}R, (*decFnInfo).{{ .MethodNamePfx "fastpathDec" false }}R){{end}}{{end}}{{end}}
{{range .Values}}{{if not .Primitive}}{{if .MapKey }}
fn(map[{{ .MapKey }}]{{ .Elem }}(nil), (*Encoder).{{ .MethodNamePfx "fastpathEnc" false }}R, (*Decoder).{{ .MethodNamePfx "fastpathDec" false }}R){{end}}{{end}}{{end}}
fn(map[{{ .MapKey }}]{{ .Elem }}(nil), (*encFnInfo).{{ .MethodNamePfx "fastpathEnc" false }}R, (*decFnInfo).{{ .MethodNamePfx "fastpathDec" false }}R){{end}}{{end}}{{end}}
sort.Sort(fastpathAslice(fastpathAV[:]))
}
@ -101,150 +106,128 @@ func init() {
// -- -- fast path type switch
func fastpathEncodeTypeSwitch(iv interface{}, e *Encoder) bool {
if !fastpathEnabled {
return false
}
switch v := iv.(type) {
{{range .Values}}{{if not .Primitive}}{{if not .MapKey }}{{if ne .Elem "uint8"}}
case []{{ .Elem }}:
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, e)
case *[]{{ .Elem }}:
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, e){{/*
*/}}{{end}}{{end}}{{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}}
{{range .Values}}{{if not .Primitive}}{{if not .MapKey }}
case []{{ .Elem }}:{{else}}
case map[{{ .MapKey }}]{{ .Elem }}:{{end}}
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, fastpathCheckNilTrue, e){{if not .MapKey }}
case *[]{{ .Elem }}:{{else}}
case *map[{{ .MapKey }}]{{ .Elem }}:{{end}}
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, fastpathCheckNilTrue, e)
{{end}}{{end}}
default:
_ = v // 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 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 {
if !fastpathEnabled {
return false
}
switch v := iv.(type) {
{{range .Values}}{{if not .Primitive}}{{if not .MapKey }}
case []{{ .Elem }}:
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, e)
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, fastpathCheckNilTrue, e)
case *[]{{ .Elem }}:
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, e)
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, fastpathCheckNilTrue, e)
{{end}}{{end}}{{end}}
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 true
}
func fastpathEncodeTypeSwitchMap(iv interface{}, e *Encoder) bool {
if !fastpathEnabled {
return false
}
switch v := iv.(type) {
{{range .Values}}{{if not .Primitive}}{{if .MapKey }}
case map[{{ .MapKey }}]{{ .Elem }}:
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, e)
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(v, fastpathCheckNilTrue, e)
case *map[{{ .MapKey }}]{{ .Elem }}:
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, e)
fastpathTV.{{ .MethodNamePfx "Enc" false }}V(*v, fastpathCheckNilTrue, e)
{{end}}{{end}}{{end}}
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 true
}
**** removing this block, as they are never called directly ****
**** removing this block, as they are never called directly ****
*/}}
// -- -- fast path functions
{{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 {
fastpathTV.{{ .MethodNamePfx "EncAsMap" false }}V(rv2i(rv).([]{{ .Elem }}), e)
fastpathTV.{{ .MethodNamePfx "EncAsMap" false }}V(rv.Interface().([]{{ .Elem }}), fastpathCheckNilFalse, f.e)
} 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) {
if v == nil { e.e.EncodeNil(); return }
ee, esep := e.e, e.hh.hasElemSeparators()
ee.WriteArrayStart(len(v))
if esep {
for _, v2 := range v {
ee.WriteArrayElem()
{{ encmd .Elem "v2"}}
}
} else {
for _, v2 := range v {
{{ encmd .Elem "v2"}}
}
} {{/*
func (_ fastpathT) {{ .MethodNamePfx "Enc" false }}V(v []{{ .Elem }}, checkNil bool, e *Encoder) {
ee := e.e
cr := e.cr
if checkNil && v == nil {
ee.EncodeNil()
return
}
ee.EncodeArrayStart(len(v))
for _, v2 := range v {
if esep { ee.WriteArrayElem() }
if cr != nil { cr.sendContainerState(containerArrayElem) }
{{ 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 {
e.errorf("mapBySlice requires even slice length, but got %v", len(v))
return
}
ee.WriteMapStart(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"}}
}
} {{/*
ee.EncodeMapStart(len(v) / 2)
for j, v2 := range v {
if esep {
if cr != nil {
if j%2 == 0 {
ee.WriteMapElemKey()
cr.sendContainerState(containerMapKey)
} else {
ee.WriteMapElemValue()
cr.sendContainerState(containerMapValue)
}
}
{{ encmd .Elem "v2"}}
} */}}
ee.WriteMapEnd()
}
if cr != nil { cr.sendContainerState(containerMapEnd) }
}
{{end}}{{end}}{{end}}
{{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) {
if v == nil { e.e.EncodeNil(); return }
ee, esep := e.e, e.hh.hasElemSeparators()
ee.WriteMapStart(len(v))
if e.h.Canonical {
func (_ fastpathT) {{ .MethodNamePfx "Enc" false }}V(v map[{{ .MapKey }}]{{ .Elem }}, checkNil bool, e *Encoder) {
ee := e.e
cr := e.cr
if checkNil && v == nil {
ee.EncodeNil()
return
}
ee.EncodeMapStart(len(v))
{{if eq .MapKey "string"}}asSymbols := e.h.AsSymbols&AsSymbolMapStringKeysFlag != 0
{{end}}if e.h.Canonical {
{{if eq .MapKey "interface{}"}}{{/* out of band
*/}}var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding
e2 := NewEncoderBytes(&mksv, e.hh)
@ -260,126 +243,66 @@ func (_ fastpathT) {{ .MethodNamePfx "Enc" false }}V(v map[{{ .MapKey }}]{{ .Ele
i++
}
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 {
if esep { ee.WriteMapElemKey() }
if cr != nil { cr.sendContainerState(containerMapKey) }
e.asis(v2[j].v)
if esep { ee.WriteMapElemValue() }
if cr != nil { cr.sendContainerState(containerMapValue) }
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
for k, _ := range v {
v2[i] = {{ $x }}(k)
i++
}
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 {
if esep { ee.WriteMapElemKey() }
{{if eq .MapKey "string"}}ee.EncodeString(cUTF8, k2){{else}}{{ $y := printf "%s(k2)" .MapKey }}{{ encmd .MapKey $y }}{{end}}
if esep { ee.WriteMapElemValue() }
if cr != nil { cr.sendContainerState(containerMapKey) }
{{if eq .MapKey "string"}}if asSymbols {
ee.EncodeSymbol(k2)
} else {
ee.EncodeString(c_UTF8, k2)
}{{else}}{{ $y := printf "%s(k2)" .MapKey }}{{ encmd .MapKey $y }}{{end}}
if cr != nil { cr.sendContainerState(containerMapValue) }
{{ $y := printf "v[%s(k2)]" .MapKey }}{{ encmd .Elem $y }}
} */}} {{end}}
} {{end}}
} 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 {
if esep { ee.WriteMapElemKey() }
{{if eq .MapKey "string"}}ee.EncodeString(cUTF8, k2){{else}}{{ encmd .MapKey "k2"}}{{end}}
if esep { ee.WriteMapElemValue() }
if cr != nil { cr.sendContainerState(containerMapKey) }
{{if eq .MapKey "string"}}if asSymbols {
ee.EncodeSymbol(k2)
} else {
ee.EncodeString(c_UTF8, k2)
}{{else}}{{ encmd .MapKey "k2"}}{{end}}
if cr != nil { cr.sendContainerState(containerMapValue) }
{{ encmd .Elem "v2"}}
} */}}
}
}
ee.WriteMapEnd()
if cr != nil { cr.sendContainerState(containerMapEnd) }{{/* ee.EncodeEnd() */}}
}
{{end}}{{end}}{{end}}
// -- decode
// -- -- fast path type switch
func fastpathDecodeTypeSwitch(iv interface{}, d *Decoder) bool {
var changed bool
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
if !fastpathEnabled {
return false
}
return true
}
func fastpathDecodeSetZeroTypeSwitch(iv interface{}) bool {
switch v := iv.(type) {
{{range .Values}}{{if not .Primitive}}{{if not .MapKey }}
case *[]{{ .Elem }}:
*v = nil {{/*
*/}}{{end}}{{end}}{{end}}
{{range .Values}}{{if not .Primitive}}{{if .MapKey }}
case *map[{{ .MapKey }}]{{ .Elem }}:
*v = nil {{/*
*/}}{{end}}{{end}}{{end}}
case []{{ .Elem }}:{{else}}
case map[{{ .MapKey }}]{{ .Elem }}:{{end}}
fastpathTV.{{ .MethodNamePfx "Dec" false }}V(v, fastpathCheckNilFalse, false, d){{if not .MapKey }}
case *[]{{ .Elem }}:{{else}}
case *map[{{ .MapKey }}]{{ .Elem }}:{{end}}
v2, changed2 := fastpathTV.{{ .MethodNamePfx "Dec" false }}V(*v, fastpathCheckNilFalse, true, d)
if changed2 {
*v = v2
}
{{end}}{{end}}
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 true
@ -393,152 +316,225 @@ Slices can change if they
- are addressable (from a ptr)
- are settable (e.g. contained in an interface{})
*/}}
func (d *Decoder) {{ .MethodNamePfx "fastpathDec" false }}R(f *codecFnInfo, rv reflect.Value) {
if array := f.seq == seqTypeArray; !array && rv.Kind() == reflect.Ptr {
vp := rv2i(rv).(*[]{{ .Elem }})
v, changed := fastpathTV.{{ .MethodNamePfx "Dec" false }}V(*vp, !array, d)
if changed { *vp = v }
func (f *decFnInfo) {{ .MethodNamePfx "fastpathDec" false }}R(rv reflect.Value) {
array := f.seq == seqTypeArray
if !array && rv.CanAddr() { {{/* // CanSet => CanAddr + Exported */}}
vp := rv.Addr().Interface().(*[]{{ .Elem }})
v, changed := fastpathTV.{{ .MethodNamePfx "Dec" false }}V(*vp, fastpathCheckNilFalse, !array, f.d)
if changed {
*vp = v
}
} else {
v := rv2i(rv).([]{{ .Elem }})
v2, changed := fastpathTV.{{ .MethodNamePfx "Dec" false }}V(v, !array, d)
if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
copy(v, v2)
}
v := rv.Interface().([]{{ .Elem }})
fastpathTV.{{ .MethodNamePfx "Dec" false }}V(v, fastpathCheckNilFalse, false, f.d)
}
}
func (f fastpathT) {{ .MethodNamePfx "Dec" false }}X(vp *[]{{ .Elem }}, d *Decoder) {
v, changed := f.{{ .MethodNamePfx "Dec" false }}V(*vp, true, d)
if changed { *vp = v }
func (f fastpathT) {{ .MethodNamePfx "Dec" false }}X(vp *[]{{ .Elem }}, checkNil bool, d *Decoder) {
v, changed := f.{{ .MethodNamePfx "Dec" false }}V(*vp, checkNil, true, d)
if changed {
*vp = v
}
}
func (_ fastpathT) {{ .MethodNamePfx "Dec" false }}V(v []{{ .Elem }}, canChange bool, d *Decoder) (_ []{{ .Elem }}, changed bool) {
dd := d.d{{/*
// if dd.isContainerType(valueTypeNil) { dd.TryDecodeAsNil()
*/}}
func (_ fastpathT) {{ .MethodNamePfx "Dec" false }}V(v []{{ .Elem }}, checkNil bool, canChange bool, d *Decoder) (_ []{{ .Elem }}, changed bool) {
dd := d.d
{{/* // if dd.isContainerType(valueTypeNil) { dd.TryDecodeAsNil() */}}
if checkNil && dd.TryDecodeAsNil() {
if v != nil {
changed = true
}
return nil, changed
}
slh, containerLenS := d.decSliceHelperStart()
if containerLenS == 0 {
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
}
slh.End()
return v, changed
}
hasLen := containerLenS > 0
var xlen int
if hasLen && canChange {
if containerLenS > 0 {
x2read := containerLenS
var xtrunc bool
if containerLenS > cap(v) {
xlen = decInferLen(containerLenS, d.h.MaxInitLen, {{ .Size }})
if xlen <= cap(v) {
v = v[:xlen]
} else {
v = make([]{{ .Elem }}, xlen)
}
changed = true
} else if containerLenS != len(v) {
v = v[:containerLenS]
changed = true
}
}
j := 0
for ; (hasLen && j < containerLenS) || !(hasLen || dd.CheckBreak()); j++ {
if j == 0 && len(v) == 0 && canChange {
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 }})
if canChange { {{/*
// fast-path is for "basic" immutable types, so no need to copy them over
// s := make([]{{ .Elem }}, decInferLen(containerLenS, d.h.MaxInitLen))
// copy(s, v[:cap(v)])
// v = s */}}
var xlen int
xlen, xtrunc = decInferLen(containerLenS, d.h.MaxInitLen, {{ .Size }})
if xtrunc {
if xlen <= cap(v) {
v = v[:xlen]
} else {
v = make([]{{ .Elem }}, xlen)
}
} else {
v = make([]{{ .Elem }}, xlen)
}
changed = true
} else {
d.arrayCannotExpand(len(v), j+1)
decodeIntoBlank = true
d.arrayCannotExpand(len(v), containerLenS)
}
}
slh.ElemContainerState(j)
if decodeIntoBlank {
d.swallow()
} else if dd.TryDecodeAsNil() {
v[j] = {{ zerocmd .Elem }}
} else {
x2read = len(v)
} else if containerLenS != len(v) {
if canChange {
v = v[:containerLenS]
changed = true
}
} {{/* // all checks done. cannot go past len. */}}
j := 0
for ; j < x2read; j++ {
slh.ElemContainerState(j)
{{ if eq .Elem "interface{}" }}d.decode(&v[j]){{ else }}v[j] = {{ decmd .Elem }}{{ end }}
}
}
if canChange {
if j < len(v) {
v = v[:j]
if xtrunc { {{/* // means canChange=true, changed=true already. */}}
for ; j < containerLenS; j++ {
v = append(v, {{ zerocmd .Elem }})
slh.ElemContainerState(j)
{{ if eq .Elem "interface{}" }}d.decode(&v[j]){{ else }}v[j] = {{ decmd .Elem }}{{ end }}
}
} else if !canChange {
for ; j < containerLenS; j++ {
slh.ElemContainerState(j)
d.swallow()
}
}
} else {
breakFound := dd.CheckBreak() {{/* check break first, so we can initialize v with a capacity of 4 if necessary */}}
if breakFound {
if canChange {
if v == nil {
v = []{{ .Elem }}{}
} else if len(v) != 0 {
v = v[:0]
}
changed = true
}
slh.End()
return v, changed
}
if cap(v) == 0 {
v = make([]{{ .Elem }}, 1, 4)
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
}
}
slh.End()
return v, changed
}
{{end}}{{end}}{{end}}
{{range .Values}}{{if not .Primitive}}{{if .MapKey }}
{{/*
Maps can change if they are
- addressable (from a ptr)
- settable (e.g. contained in an interface{})
*/}}
func (d *Decoder) {{ .MethodNamePfx "fastpathDec" false }}R(f *codecFnInfo, rv reflect.Value) {
if rv.Kind() == reflect.Ptr {
vp := rv2i(rv).(*map[{{ .MapKey }}]{{ .Elem }})
v, changed := fastpathTV.{{ .MethodNamePfx "Dec" false }}V(*vp, true, d);
if changed { *vp = v }
func (f *decFnInfo) {{ .MethodNamePfx "fastpathDec" false }}R(rv reflect.Value) {
if rv.CanAddr() {
vp := rv.Addr().Interface().(*map[{{ .MapKey }}]{{ .Elem }})
v, changed := fastpathTV.{{ .MethodNamePfx "Dec" false }}V(*vp, fastpathCheckNilFalse, true, f.d)
if changed {
*vp = v
}
} 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) {
v, changed := f.{{ .MethodNamePfx "Dec" false }}V(*vp, true, d)
if changed { *vp = v }
func (f fastpathT) {{ .MethodNamePfx "Dec" false }}X(vp *map[{{ .MapKey }}]{{ .Elem }}, checkNil bool, d *Decoder) {
v, changed := f.{{ .MethodNamePfx "Dec" false }}V(*vp, checkNil, true, d)
if changed {
*vp = v
}
}
func (_ fastpathT) {{ .MethodNamePfx "Dec" false }}V(v map[{{ .MapKey }}]{{ .Elem }}, canChange bool,
func (_ fastpathT) {{ .MethodNamePfx "Dec" false }}V(v map[{{ .MapKey }}]{{ .Elem }}, checkNil bool, canChange bool,
d *Decoder) (_ map[{{ .MapKey }}]{{ .Elem }}, changed bool) {
dd, esep := d.d, d.hh.hasElemSeparators(){{/*
// if dd.isContainerType(valueTypeNil) {dd.TryDecodeAsNil()
*/}}
dd := d.d
cr := d.cr
{{/* // if dd.isContainerType(valueTypeNil) {dd.TryDecodeAsNil() */}}
if checkNil && dd.TryDecodeAsNil() {
if v != nil {
changed = true
}
return nil, changed
}
containerLen := dd.ReadMapStart()
if canChange && v == nil {
xlen := decInferLen(containerLen, d.h.MaxInitLen, {{ .Size }})
xlen, _ := decInferLen(containerLen, d.h.MaxInitLen, {{ .Size }})
v = make(map[{{ .MapKey }}]{{ .Elem }}, xlen)
changed = true
}
if containerLen == 0 {
dd.ReadMapEnd()
return v, changed
}
{{ if eq .Elem "interface{}" }}mapGet := v != nil && !d.h.MapValueReset && !d.h.InterfaceReset
{{end}}var mk {{ .MapKey }}
{{ if eq .Elem "interface{}" }}mapGet := !d.h.MapValueReset && !d.h.InterfaceReset{{end}}
var mk {{ .MapKey }}
var mv {{ .Elem }}
hasLen := containerLen > 0
for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
if esep { dd.ReadMapElemKey() }
{{ 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 esep { dd.ReadMapElemValue() }
if dd.TryDecodeAsNil() {
if v == nil {} else if d.h.DeleteOnNilMapValue { delete(v, mk) } else { v[mk] = {{ zerocmd .Elem }} }
continue
if containerLen > 0 {
for j := 0; j < containerLen; j++ {
if cr != nil { cr.sendContainerState(containerMapKey) }
{{ if eq .MapKey "interface{}" }}mk = nil
d.decode(&mk)
if bv, bok := mk.([]byte); bok {
mk = d.string(bv) {{/* // maps cannot have []byte as key. switch to string. */}}
}{{ else }}mk = {{ decmd .MapKey }}{{ end }}
if cr != nil { cr.sendContainerState(containerMapValue) }
{{ if eq .Elem "interface{}" }}if mapGet { mv = v[mk] } else { mv = nil }
d.decode(&mv){{ else }}mv = {{ decmd .Elem }}{{ end }}
if v != nil {
v[mk] = mv
}
}
} else if containerLen < 0 {
for j := 0; !dd.CheckBreak(); j++ {
if cr != nil { cr.sendContainerState(containerMapKey) }
{{ if eq .MapKey "interface{}" }}mk = nil
d.decode(&mk)
if bv, bok := mk.([]byte); bok {
mk = d.string(bv) {{/* // maps cannot have []byte as key. switch to string. */}}
}{{ else }}mk = {{ decmd .MapKey }}{{ end }}
if cr != nil { cr.sendContainerState(containerMapValue) }
{{ if eq .Elem "interface{}" }}if mapGet { mv = v[mk] } else { mv = nil }
d.decode(&mv){{ else }}mv = {{ decmd .Elem }}{{ end }}
if v != nil {
v[mk] = mv
}
}
{{ 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
}
{{end}}{{end}}{{end}}

View File

@ -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
package codec
import "reflect"
const fastpathEnabled = false
// The generated fast-path code is very large, and adds a few seconds to the build time.
// This causes test execution, execution of small tools which use codec, etc
// to take a long time.
@ -21,27 +16,17 @@ func fastpathDecodeTypeSwitch(iv interface{}, d *Decoder) bool { return fal
func fastpathEncodeTypeSwitch(iv interface{}, e *Encoder) bool { return false }
func fastpathEncodeTypeSwitchSlice(iv interface{}, e *Encoder) bool { return false }
func fastpathEncodeTypeSwitchMap(iv interface{}, e *Encoder) bool { return false }
func fastpathDecodeSetZeroTypeSwitch(iv interface{}) bool { return false }
type fastpathT struct{}
type fastpathE struct {
rtid uintptr
rt reflect.Type
encfn func(*Encoder, *codecFnInfo, reflect.Value)
decfn func(*Decoder, *codecFnInfo, reflect.Value)
encfn func(*encFnInfo, reflect.Value)
decfn func(*decFnInfo, reflect.Value)
}
type fastpathA [0]fastpathE
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 fastpathTV fastpathT
// ----
type TestMammoth2Wrapper struct{} // to allow testMammoth work in notfastpath mode

View File

@ -9,68 +9,94 @@ if {{var "l"}} == 0 {
} else if len({{var "v"}}) != 0 {
{{var "v"}} = {{var "v"}}[:0]
{{var "c"}} = true
} {{else if isChan }}if {{var "v"}} == nil {
} {{end}} {{if isChan }}if {{var "v"}} == nil {
{{var "v"}} = make({{ .CTyp }}, 0)
{{var "c"}} = true
} {{end}}
} else {
{{var "hl"}} := {{var "l"}} > 0
var {{var "rl"}} int
_ = {{var "rl"}}
{{if isSlice }} if {{var "hl"}} {
} else if {{var "l"}} > 0 {
{{if isChan }}if {{var "v"}} == nil {
{{var "rl"}}, _ = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})
{{var "v"}} = make({{ .CTyp }}, {{var "rl"}})
{{var "c"}} = true
}
for {{var "r"}} := 0; {{var "r"}} < {{var "l"}}; {{var "r"}}++ {
{{var "h"}}.ElemContainerState({{var "r"}})
var {{var "t"}} {{ .Typ }}
{{ $x := printf "%st%s" .TempVar .Rand }}{{ decLineVar $x }}
{{var "v"}} <- {{var "t"}}
}
{{ else }} var {{var "rr"}}, {{var "rl"}} int {{/* // num2read, length of slice/array/chan */}}
var {{var "rt"}} bool {{/* truncated */}}
_, _ = {{var "rl"}}, {{var "rt"}}
{{var "rr"}} = {{var "l"}} // len({{var "v"}})
if {{var "l"}} > cap({{var "v"}}) {
{{var "rl"}} = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})
if {{var "rl"}} <= cap({{var "v"}}) {
{{var "v"}} = {{var "v"}}[:{{var "rl"}}]
{{if isArray }}z.DecArrayCannotExpand(len({{var "v"}}), {{var "l"}})
{{ else }}{{if not .Immutable }}
{{var "rg"}} := len({{var "v"}}) > 0
{{var "v2"}} := {{var "v"}} {{end}}
{{var "rl"}}, {{var "rt"}} = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})
if {{var "rt"}} {
if {{var "rl"}} <= cap({{var "v"}}) {
{{var "v"}} = {{var "v"}}[:{{var "rl"}}]
} else {
{{var "v"}} = make([]{{ .Typ }}, {{var "rl"}})
}
} else {
{{var "v"}} = make([]{{ .Typ }}, {{var "rl"}})
}
{{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 "c"}} = true
}
} {{end}}
var {{var "j"}} int
// 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}}
} {{end}} {{/* end isSlice:47 */}}
{{var "j"}} := 0
for ; {{var "j"}} < {{var "rr"}} ; {{var "j"}}++ {
{{var "h"}}.ElemContainerState({{var "j"}})
{{/* {{var "dn"}} = r.TryDecodeAsNil() */}}{{/* commented out, as decLineVar handles this already each time */}}
{{if isChan}}{{ $x := printf "%[1]vvcx%[2]v" .TempVar .Rand }}var {{$x}} {{ .Typ }}
{{ decLineVar $x }}
{{var "v"}} <- {{ $x }}
// println(">>>> sending ", {{ $x }}, " into ", {{var "v"}}) // TODO: remove this
{{else}}{{/* // if indefinite, etc, then expand the slice if necessary */}}
var {{var "db"}} bool
if {{var "j"}} >= len({{var "v"}}) {
{{if isSlice }} {{var "v"}} = append({{var "v"}}, {{ zero }})
{{var "c"}} = true
{{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 }}
}
{{if isArray }}for ; {{var "j"}} < {{var "l"}} ; {{var "j"}}++ {
{{var "h"}}.ElemContainerState({{var "j"}})
z.DecSwallow()
}
{{ else }}if {{var "rt"}} {
for ; {{var "j"}} < {{var "l"}} ; {{var "j"}}++ {
{{var "v"}} = append({{var "v"}}, {{ zero}})
{{var "h"}}.ElemContainerState({{var "j"}})
{{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }}
}
{{end}}
} {{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 "c"}} = true
} else if {{var "j"}} == 0 && {{var "v"}} == nil {
{{var "v"}} = make([]{{ .Typ }}, 0)
{{var "v"}} = []{{ .Typ }}{}
{{var "c"}} = true
} {{end}}
}{{end}}
}
{{var "h"}}.End()
{{if not isArray }}if {{var "c"}} {

View File

@ -2,22 +2,21 @@
{{var "l"}} := r.ReadMapStart()
{{var "bh"}} := z.DecBasicHandle()
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"}})
*{{ .Varname }} = {{var "v"}}
}
var {{var "mk"}} {{ .KTyp }}
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 decElemKindPtr}}{{var "mg"}} = true
{{else if decElemKindIntf}}if !{{var "bh"}}.InterfaceReset { {{var "mg"}} = true }
{{else if not decElemKindImmutable}}{{var "mg"}} = true
{{end}} }
if {{var "l"}} != 0 {
{{var "hl"}} := {{var "l"}} > 0
for {{var "j"}} := 0; ({{var "hl"}} && {{var "j"}} < {{var "l"}}) || !({{var "hl"}} || r.CheckBreak()); {{var "j"}}++ {
r.ReadMapElemKey() {{/* z.DecSendContainerState(codecSelfer_containerMapKey{{ .Sfx }}) */}}
if {{var "l"}} > 0 {
for {{var "j"}} := 0; {{var "j"}} < {{var "l"}}; {{var "j"}}++ {
z.DecSendContainerState(codecSelfer_containerMapKey{{ .Sfx }})
{{ $x := printf "%vmk%v" .TempVar .Rand }}{{ decLineVarK $x }}
{{ if eq .KTyp "interface{}" }}{{/* // special case if a byte array. */}}if {{var "bv"}}, {{var "bok"}} := {{var "mk"}}.([]byte); {{var "bok"}} {
{{var "mk"}} = string({{var "bv"}})
@ -29,14 +28,31 @@ if {{var "l"}} != 0 {
{{var "ms"}} = false
} {{else}}{{var "mv"}} = {{var "v"}}[{{var "mk"}}] {{end}}
} {{if not decElemKindImmutable}}else { {{var "mv"}} = {{decElemZero}} }{{end}}
r.ReadMapElemValue() {{/* z.DecSendContainerState(codecSelfer_containerMapValue{{ .Sfx }}) */}}
{{var "mdn"}} = false
{{ $x := printf "%vmv%v" .TempVar .Rand }}{{ $y := printf "%vmdn%v" .TempVar .Rand }}{{ decLineVar $x $y }}
if {{var "mdn"}} {
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 {
z.DecSendContainerState(codecSelfer_containerMapValue{{ .Sfx }})
{{ $x := printf "%vmv%v" .TempVar .Rand }}{{ decLineVar $x }}
if {{if decElemKindPtr}} {{var "ms"}} && {{end}} {{var "v"}} != nil {
{{var "v"}}[{{var "mk"}}] = {{var "mv"}}
}
}
} else if {{var "l"}} < 0 {
for {{var "j"}} := 0; !r.CheckBreak(); {{var "j"}}++ {
z.DecSendContainerState(codecSelfer_containerMapKey{{ .Sfx }})
{{ $x := printf "%vmk%v" .TempVar .Rand }}{{ decLineVarK $x }}
{{ if eq .KTyp "interface{}" }}{{/* // special case if a byte array. */}}if {{var "bv"}}, {{var "bok"}} := {{var "mk"}}.([]byte); {{var "bok"}} {
{{var "mk"}} = string({{var "bv"}})
}{{ end }}{{if decElemKindPtr}}
{{var "ms"}} = true {{ end }}
if {{var "mg"}} {
{{if decElemKindPtr}}{{var "mv"}}, {{var "mok"}} = {{var "v"}}[{{var "mk"}}]
if {{var "mok"}} {
{{var "ms"}} = false
} {{else}}{{var "mv"}} = {{var "v"}}[{{var "mk"}}] {{end}}
} {{if not decElemKindImmutable}}else { {{var "mv"}} = {{decElemZero}} }{{end}}
z.DecSendContainerState(codecSelfer_containerMapValue{{ .Sfx }})
{{ $x := printf "%vmv%v" .TempVar .Rand }}{{ decLineVar $x }}
if {{if decElemKindPtr}} {{var "ms"}} && {{end}} {{var "v"}} != nil {
{{var "v"}}[{{var "mk"}}] = {{var "mv"}}
}
}
} // else len==0: TODO: Should we clear map entries?
r.ReadMapEnd() {{/* z.DecSendContainerState(codecSelfer_containerMapEnd{{ .Sfx }}) */}}
z.DecSendContainerState(codecSelfer_containerMapEnd{{ .Sfx }})

View File

@ -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}})
}
}

View File

@ -1,24 +1,23 @@
/* // +build ignore */
// //+build ignore
// 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 gen-helper.go.tmpl - DO NOT EDIT.
// ************************************************************
// DO NOT EDIT.
// THIS FILE IS AUTO-GENERATED from gen-helper.go.tmpl
// ************************************************************
package codec
import (
"encoding"
"reflect"
"strconv"
)
// GenVersion is the current version of codecgen.
const GenVersion = 8
// This file is used to generate helper code for codecgen.
// The values here i.e. genHelper(En|De)coder are not to be used directly by
// library users. They WILL change 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.
// 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.
// GenHelperEncoder is exported so that it can be used externally by codecgen.
//
// Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE.
func GenHelperEncoder(e *Encoder) (ge genHelperEncoder, ee genHelperEncDriver) {
ge = genHelperEncoder{e: e}
ee = genHelperEncDriver{encDriver: e.e}
return
func GenHelperEncoder(e *Encoder) (genHelperEncoder, encDriver) {
return genHelperEncoder{e: e}, e.e
}
// GenHelperDecoder is exported so that it can be used externally by codecgen.
//
// Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE.
func GenHelperDecoder(d *Decoder) (gd genHelperDecoder, dd genHelperDecDriver) {
gd = genHelperDecoder{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
func GenHelperDecoder(d *Decoder) (genHelperDecoder, decDriver) {
return genHelperDecoder{d: d}, d.d
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
type genHelperEncoder struct {
M must
e *Encoder
F fastpathT
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
type genHelperDecoder struct {
C checkOverflow
d *Decoder
F fastpathT
}
@ -120,91 +59,69 @@ func (f genHelperEncoder) EncBinary() bool {
return f.e.be // f.e.hh.isBinaryEncoding()
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
func (f genHelperEncoder) IsJSONHandle() bool {
return f.e.js
}
// 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)
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, cUTF8)
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, cUTF8)
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, cRAW)
f.e.marshal(bs, fnerr, false, c_RAW)
}
// 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)
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) Extension(rtid uintptr) (xfn *extTypeTagFn) {
return f.e.h.getExt(rtid)
func (f genHelperEncoder) IsJSONHandle() bool {
return f.e.js
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
func (f genHelperEncoder) 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 {
return len(f.e.h.extHandle) != 0
}
// 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) {
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)
return true
}
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 -----------------
// 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*
func (f genHelperDecoder) DecSwallow() { f.d.swallow() }
func (f genHelperDecoder) DecSwallow() {
f.d.swallow()
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
func (f genHelperDecoder) DecScratchBuffer() []byte {
return f.d.b[:]
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
func (f genHelperDecoder) DecScratchArrayBuffer() *[decScratchByteArrayLen]byte {
return &f.d.b
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
func (f genHelperDecoder) DecFallback(iv interface{}, chkPtr bool) {
// println(">>>>>>>>> DecFallback")
rv := reflect.ValueOf(iv)
if chkPtr {
rv = f.d.ensureDecodeable(rv)
}
f.d.decodeValue(rv, nil, false)
// f.d.decodeValueFallback(rv)
f.d.decodeI(iv, chkPtr, false, false, false)
}
// 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*
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 {
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*
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.
fnerr := tm.UnmarshalJSON(f.d.nextValueBytes())
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*
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 {
panic(fnerr)
}
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
func (f genHelperDecoder) DecRaw() []byte { return f.d.rawBytes() }
// 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 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
// }
func (f genHelperDecoder) TimeRtidIfBinc() uintptr {
if _, ok := f.d.hh.(*BincHandle); ok {
return timeTypId
}
return 0
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
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*
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 {
return len(f.d.h.extHandle) != 0
}
// 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) {
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)
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*
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)
}
// 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) StringView(v []byte) string { return stringView(v) }
func (f genHelperDecoder) DecSendContainerState(c containerState) {
if f.d.cr != nil {
f.d.cr.sendContainerState(c)
}
}

View File

@ -1,24 +1,23 @@
/* // +build ignore */
// //+build ignore
// 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 gen-helper.go.tmpl - DO NOT EDIT.
// ************************************************************
// DO NOT EDIT.
// THIS FILE IS AUTO-GENERATED from gen-helper.go.tmpl
// ************************************************************
package codec
import (
"encoding"
"reflect"
"strconv"
)
// GenVersion is the current version of codecgen.
const GenVersion = {{ .Version }}
// This file is used to generate helper code for codecgen.
// The values here i.e. genHelper(En|De)coder are not to be used directly by
// library users. They WILL change 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.
// The only way to get the type is via the one exported type that we control (somewhat).
@ -27,85 +26,25 @@ const GenVersion = {{ .Version }}
// to perform encoding or decoding of primitives or known slice or map types.
// GenHelperEncoder is exported so that it can be used externally by codecgen.
//
// Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE.
func GenHelperEncoder(e *Encoder) (ge genHelperEncoder, ee genHelperEncDriver) {
ge = genHelperEncoder{e: e}
ee = genHelperEncDriver{encDriver: e.e}
return
func GenHelperEncoder(e *Encoder) (genHelperEncoder, encDriver) {
return genHelperEncoder{e:e}, e.e
}
// GenHelperDecoder is exported so that it can be used externally by codecgen.
//
// Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE.
func GenHelperDecoder(d *Decoder) (gd genHelperDecoder, dd genHelperDecDriver) {
gd = genHelperDecoder{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
func GenHelperDecoder(d *Decoder) (genHelperDecoder, decDriver) {
return genHelperDecoder{d:d}, d.d
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
type genHelperEncoder struct {
M must
e *Encoder
F fastpathT
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
type genHelperDecoder struct {
C checkOverflow
d *Decoder
F fastpathT
}
@ -114,82 +53,65 @@ type genHelperDecoder struct {
func (f genHelperEncoder) EncBasicHandle() *BasicHandle {
return f.e.h
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
func (f genHelperEncoder) EncBinary() bool {
return f.e.be // f.e.hh.isBinaryEncoding()
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
func (f genHelperEncoder) EncFallback(iv interface{}) {
// println(">>>>>>>>> EncFallback")
f.e.encodeI(iv, false, false)
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
func (f genHelperEncoder) EncTextMarshal(iv encoding.TextMarshaler) {
bs, fnerr := iv.MarshalText()
f.e.marshal(bs, fnerr, false, c_UTF8)
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
func (f genHelperEncoder) EncJSONMarshal(iv jsonMarshaler) {
bs, fnerr := iv.MarshalJSON()
f.e.marshal(bs, fnerr, true, c_UTF8)
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
func (f genHelperEncoder) EncBinaryMarshal(iv encoding.BinaryMarshaler) {
bs, fnerr := iv.MarshalBinary()
f.e.marshal(bs, fnerr, false, c_RAW)
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
func (f genHelperEncoder) TimeRtidIfBinc() uintptr {
if _, ok := f.e.hh.(*BincHandle); ok {
return timeTypId
}
return 0
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
func (f genHelperEncoder) IsJSONHandle() bool {
return f.e.js
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
func (f genHelperEncoder) 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 {
return len(f.e.h.extHandle) != 0
}
// 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) {
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)
return true
}
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 -----------------
@ -202,24 +124,17 @@ func (f genHelperDecoder) DecBinary() bool {
return f.d.be // f.d.hh.isBinaryEncoding()
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
func (f genHelperDecoder) DecSwallow() { f.d.swallow() }
func (f genHelperDecoder) DecSwallow() {
f.d.swallow()
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
func (f genHelperDecoder) DecScratchBuffer() []byte {
return f.d.b[:]
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
func (f genHelperDecoder) DecScratchArrayBuffer() *[decScratchByteArrayLen]byte {
return &f.d.b
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
func (f genHelperDecoder) DecFallback(iv interface{}, chkPtr bool) {
// println(">>>>>>>>> DecFallback")
rv := reflect.ValueOf(iv)
if chkPtr {
rv = f.d.ensureDecodeable(rv)
}
f.d.decodeValue(rv, nil, false)
// f.d.decodeValueFallback(rv)
f.d.decodeI(iv, chkPtr, false, false, false)
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
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*
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 {
panic(fnerr)
}
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
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.
fnerr := tm.UnmarshalJSON(f.d.nextValueBytes())
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*
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 {
panic(fnerr)
}
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
func (f genHelperDecoder) DecRaw() []byte { return f.d.rawBytes() }
// 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 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
// }
func (f genHelperDecoder) TimeRtidIfBinc() uintptr {
if _, ok := f.d.hh.(*BincHandle); ok {
return timeTypId
}
return 0
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
func (f genHelperDecoder) IsJSONHandle() bool {
return f.d.js
}
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
func (f genHelperDecoder) 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 {
return len(f.d.h.extHandle) != 0
}
// 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) {
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)
return true
}
return false
}
// 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)
}
// 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) StringView(v []byte) string { return stringView(v) }
func (f genHelperDecoder) DecSendContainerState(c containerState) {
if f.d.cr != nil {
f.d.cr.sendContainerState(c)
}
}
{{/*
// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
func (f genHelperEncoder) EncDriver() encDriver {
return f.e.e
}
// 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 }}
*/}}

View File

@ -1,5 +1,3 @@
// +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.
@ -12,22 +10,21 @@ const genDecMapTmpl = `
{{var "l"}} := r.ReadMapStart()
{{var "bh"}} := z.DecBasicHandle()
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"}})
*{{ .Varname }} = {{var "v"}}
}
var {{var "mk"}} {{ .KTyp }}
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 decElemKindPtr}}{{var "mg"}} = true
{{else if decElemKindIntf}}if !{{var "bh"}}.InterfaceReset { {{var "mg"}} = true }
{{else if not decElemKindImmutable}}{{var "mg"}} = true
{{end}} }
if {{var "l"}} != 0 {
{{var "hl"}} := {{var "l"}} > 0
for {{var "j"}} := 0; ({{var "hl"}} && {{var "j"}} < {{var "l"}}) || !({{var "hl"}} || r.CheckBreak()); {{var "j"}}++ {
r.ReadMapElemKey() {{/* z.DecSendContainerState(codecSelfer_containerMapKey{{ .Sfx }}) */}}
if {{var "l"}} > 0 {
for {{var "j"}} := 0; {{var "j"}} < {{var "l"}}; {{var "j"}}++ {
z.DecSendContainerState(codecSelfer_containerMapKey{{ .Sfx }})
{{ $x := printf "%vmk%v" .TempVar .Rand }}{{ decLineVarK $x }}
{{ if eq .KTyp "interface{}" }}{{/* // special case if a byte array. */}}if {{var "bv"}}, {{var "bok"}} := {{var "mk"}}.([]byte); {{var "bok"}} {
{{var "mk"}} = string({{var "bv"}})
@ -39,17 +36,34 @@ if {{var "l"}} != 0 {
{{var "ms"}} = false
} {{else}}{{var "mv"}} = {{var "v"}}[{{var "mk"}}] {{end}}
} {{if not decElemKindImmutable}}else { {{var "mv"}} = {{decElemZero}} }{{end}}
r.ReadMapElemValue() {{/* z.DecSendContainerState(codecSelfer_containerMapValue{{ .Sfx }}) */}}
{{var "mdn"}} = false
{{ $x := printf "%vmv%v" .TempVar .Rand }}{{ $y := printf "%vmdn%v" .TempVar .Rand }}{{ decLineVar $x $y }}
if {{var "mdn"}} {
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 {
z.DecSendContainerState(codecSelfer_containerMapValue{{ .Sfx }})
{{ $x := printf "%vmv%v" .TempVar .Rand }}{{ decLineVar $x }}
if {{if decElemKindPtr}} {{var "ms"}} && {{end}} {{var "v"}} != nil {
{{var "v"}}[{{var "mk"}}] = {{var "mv"}}
}
}
} else if {{var "l"}} < 0 {
for {{var "j"}} := 0; !r.CheckBreak(); {{var "j"}}++ {
z.DecSendContainerState(codecSelfer_containerMapKey{{ .Sfx }})
{{ $x := printf "%vmk%v" .TempVar .Rand }}{{ decLineVarK $x }}
{{ if eq .KTyp "interface{}" }}{{/* // special case if a byte array. */}}if {{var "bv"}}, {{var "bok"}} := {{var "mk"}}.([]byte); {{var "bok"}} {
{{var "mk"}} = string({{var "bv"}})
}{{ end }}{{if decElemKindPtr}}
{{var "ms"}} = true {{ end }}
if {{var "mg"}} {
{{if decElemKindPtr}}{{var "mv"}}, {{var "mok"}} = {{var "v"}}[{{var "mk"}}]
if {{var "mok"}} {
{{var "ms"}} = false
} {{else}}{{var "mv"}} = {{var "v"}}[{{var "mk"}}] {{end}}
} {{if not decElemKindImmutable}}else { {{var "mv"}} = {{decElemZero}} }{{end}}
z.DecSendContainerState(codecSelfer_containerMapValue{{ .Sfx }})
{{ $x := printf "%vmv%v" .TempVar .Rand }}{{ decLineVar $x }}
if {{if decElemKindPtr}} {{var "ms"}} && {{end}} {{var "v"}} != nil {
{{var "v"}}[{{var "mk"}}] = {{var "mv"}}
}
}
} // else len==0: TODO: Should we clear map entries?
r.ReadMapEnd() {{/* z.DecSendContainerState(codecSelfer_containerMapEnd{{ .Sfx }}) */}}
z.DecSendContainerState(codecSelfer_containerMapEnd{{ .Sfx }})
`
const genDecListTmpl = `
@ -64,68 +78,94 @@ if {{var "l"}} == 0 {
} else if len({{var "v"}}) != 0 {
{{var "v"}} = {{var "v"}}[:0]
{{var "c"}} = true
} {{else if isChan }}if {{var "v"}} == nil {
} {{end}} {{if isChan }}if {{var "v"}} == nil {
{{var "v"}} = make({{ .CTyp }}, 0)
{{var "c"}} = true
} {{end}}
} else {
{{var "hl"}} := {{var "l"}} > 0
var {{var "rl"}} int
_ = {{var "rl"}}
{{if isSlice }} if {{var "hl"}} {
} else if {{var "l"}} > 0 {
{{if isChan }}if {{var "v"}} == nil {
{{var "rl"}}, _ = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})
{{var "v"}} = make({{ .CTyp }}, {{var "rl"}})
{{var "c"}} = true
}
for {{var "r"}} := 0; {{var "r"}} < {{var "l"}}; {{var "r"}}++ {
{{var "h"}}.ElemContainerState({{var "r"}})
var {{var "t"}} {{ .Typ }}
{{ $x := printf "%st%s" .TempVar .Rand }}{{ decLineVar $x }}
{{var "v"}} <- {{var "t"}}
}
{{ else }} var {{var "rr"}}, {{var "rl"}} int {{/* // num2read, length of slice/array/chan */}}
var {{var "rt"}} bool {{/* truncated */}}
_, _ = {{var "rl"}}, {{var "rt"}}
{{var "rr"}} = {{var "l"}} // len({{var "v"}})
if {{var "l"}} > cap({{var "v"}}) {
{{var "rl"}} = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})
if {{var "rl"}} <= cap({{var "v"}}) {
{{var "v"}} = {{var "v"}}[:{{var "rl"}}]
{{if isArray }}z.DecArrayCannotExpand(len({{var "v"}}), {{var "l"}})
{{ else }}{{if not .Immutable }}
{{var "rg"}} := len({{var "v"}}) > 0
{{var "v2"}} := {{var "v"}} {{end}}
{{var "rl"}}, {{var "rt"}} = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})
if {{var "rt"}} {
if {{var "rl"}} <= cap({{var "v"}}) {
{{var "v"}} = {{var "v"}}[:{{var "rl"}}]
} else {
{{var "v"}} = make([]{{ .Typ }}, {{var "rl"}})
}
} else {
{{var "v"}} = make([]{{ .Typ }}, {{var "rl"}})
}
{{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 "c"}} = true
}
} {{end}}
var {{var "j"}} int
// 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}}
} {{end}} {{/* end isSlice:47 */}}
{{var "j"}} := 0
for ; {{var "j"}} < {{var "rr"}} ; {{var "j"}}++ {
{{var "h"}}.ElemContainerState({{var "j"}})
{{/* {{var "dn"}} = r.TryDecodeAsNil() */}}{{/* commented out, as decLineVar handles this already each time */}}
{{if isChan}}{{ $x := printf "%[1]vvcx%[2]v" .TempVar .Rand }}var {{$x}} {{ .Typ }}
{{ decLineVar $x }}
{{var "v"}} <- {{ $x }}
// println(">>>> sending ", {{ $x }}, " into ", {{var "v"}}) // TODO: remove this
{{else}}{{/* // if indefinite, etc, then expand the slice if necessary */}}
var {{var "db"}} bool
if {{var "j"}} >= len({{var "v"}}) {
{{if isSlice }} {{var "v"}} = append({{var "v"}}, {{ zero }})
{{var "c"}} = true
{{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 }}
}
{{if isArray }}for ; {{var "j"}} < {{var "l"}} ; {{var "j"}}++ {
{{var "h"}}.ElemContainerState({{var "j"}})
z.DecSwallow()
}
{{ else }}if {{var "rt"}} {
for ; {{var "j"}} < {{var "l"}} ; {{var "j"}}++ {
{{var "v"}} = append({{var "v"}}, {{ zero}})
{{var "h"}}.ElemContainerState({{var "j"}})
{{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }}
}
{{end}}
} {{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 "c"}} = true
} else if {{var "j"}} == 0 && {{var "v"}} == nil {
{{var "v"}} = make([]{{ .Typ }}, 0)
{{var "v"}} = []{{ .Typ }}{}
{{var "c"}} = true
} {{end}}
}{{end}}
}
{{var "h"}}.End()
{{if not isArray }}if {{var "c"}} {
@ -133,32 +173,3 @@ if {{var "l"}} == 0 {
}{{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

View File

@ -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)
}

View File

@ -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")
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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

View File

@ -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

View File

@ -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")
}

View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -6,6 +6,74 @@ package codec
// All non-std package dependencies live in this file,
// so porting to different environment is easy (just update functions).
import (
"errors"
"fmt"
"math"
"reflect"
)
func panicValToErr(panicVal interface{}, err *error) {
if panicVal == nil {
return
}
// case nil
switch xerr := panicVal.(type) {
case error:
*err = xerr
case string:
*err = errors.New(xerr)
default:
*err = fmt.Errorf("%v", panicVal)
}
return
}
func hIsEmptyValue(v reflect.Value, deref, checkStruct bool) bool {
switch v.Kind() {
case reflect.Invalid:
return true
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
return v.Len() == 0
case reflect.Bool:
return !v.Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return v.Int() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return v.Uint() == 0
case reflect.Float32, reflect.Float64:
return v.Float() == 0
case reflect.Interface, reflect.Ptr:
if deref {
if v.IsNil() {
return true
}
return hIsEmptyValue(v.Elem(), deref, checkStruct)
} else {
return v.IsNil()
}
case reflect.Struct:
if !checkStruct {
return false
}
// return true if all fields are empty. else return false.
// we cannot use equality check, because some fields may be maps/slices/etc
// and consequently the structs are not comparable.
// return v.Interface() == reflect.Zero(v.Type()).Interface()
for i, n := 0, v.NumField(); i < n; i++ {
if !hIsEmptyValue(v.Field(i), deref, checkStruct) {
return false
}
}
return true
}
return false
}
func isEmptyValue(v reflect.Value) bool {
return hIsEmptyValue(v, derefForIsEmptyValue, checkStructForEmptyValue)
}
func pruneSignExt(v []byte, pos bool) (n int) {
if len(v) < 2 {
} else if pos && v[0] == 0 {
@ -18,6 +86,37 @@ func pruneSignExt(v []byte, pos bool) (n int) {
return
}
func implementsIntf(typ, iTyp reflect.Type) (success bool, indir int8) {
if typ == nil {
return
}
rt := typ
// The type might be a pointer and we need to keep
// dereferencing to the base type until we find an implementation.
for {
if rt.Implements(iTyp) {
return true, indir
}
if p := rt; p.Kind() == reflect.Ptr {
indir++
if indir >= math.MaxInt8 { // insane number of indirections
return false, 0
}
rt = p.Elem()
continue
}
break
}
// No luck yet, but if this is a base type (non-pointer), the pointer might satisfy.
if typ.Kind() != reflect.Ptr {
// Not a pointer, but does the pointer work?
if reflect.PtrTo(typ).Implements(iTyp) {
return true, -1
}
}
return false, 0
}
// validate that this function is correct ...
// culled from OGRE (Object-Oriented Graphics Rendering Engine)
// function: halfToFloatI (http://stderr.org/doc/ogre-doc/api/OgreBitwise_8h-source.html)
@ -30,20 +129,21 @@ func halfFloatToFloatBits(yy uint16) (d uint32) {
if e == 0 {
if m == 0 { // plu or minus 0
return s << 31
} else { // Denormalized number -- renormalize it
for (m & 0x00000400) == 0 {
m <<= 1
e -= 1
}
e += 1
const zz uint32 = 0x0400
m &= ^zz
}
// Denormalized number -- renormalize it
for (m & 0x00000400) == 0 {
m <<= 1
e -= 1
}
e += 1
const zz uint32 = 0x0400
m &= ^zz
} else if e == 31 {
if m == 0 { // Inf
return (s << 31) | 0x7f800000
} else { // NaN
return (s << 31) | 0x7f800000 | (m << 13)
}
return (s << 31) | 0x7f800000 | (m << 13) // NaN
}
e = e + (127 - 15)
m = m << 13
@ -119,3 +219,24 @@ func growCap(oldCap, unit, num int) (newCap int) {
}
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
}

View File

@ -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.
package codec
import (
"reflect"
"sync/atomic"
"time"
)
const safeMode = true
// stringView returns a view of the []byte as a string.
// In unsafe mode, it doesn't incur allocation and copying caused by conversion.
// In regular safe mode, it is an allocation and copy.
//
// 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 {
return string(v)
}
@ -26,247 +15,6 @@ func stringView(v []byte) string {
// 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.
//
// 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 {
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
// }
// }

View File

@ -1,639 +1,45 @@
// +build !safe
// +build !appengine
// +build go1.7
//+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.
package codec
import (
"reflect"
"sync/atomic"
"time"
"unsafe"
)
// 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 {
Data unsafe.Pointer
Data uintptr
Len int
}
type unsafeSlice struct {
Data unsafe.Pointer
type unsafeBytes struct {
Data uintptr
Len int
Cap int
}
type unsafeIntf struct {
typ unsafe.Pointer
word unsafe.Pointer
}
type unsafeReflectValue struct {
typ unsafe.Pointer
ptr unsafe.Pointer
flag uintptr
}
// stringView returns a view of the []byte as a string.
// In unsafe mode, it doesn't incur allocation and copying caused by conversion.
// In regular safe mode, it is an allocation and copy.
func stringView(v []byte) string {
if len(v) == 0 {
return ""
}
bx := (*unsafeSlice)(unsafe.Pointer(&v))
return *(*string)(unsafe.Pointer(&unsafeString{bx.Data, bx.Len}))
x := unsafeString{uintptr(unsafe.Pointer(&v[0])), len(v)}
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 {
if len(v) == 0 {
return zeroByteSlice
}
sx := (*unsafeString)(unsafe.Pointer(&v))
return *(*[]byte)(unsafe.Pointer(&unsafeSlice{sx.Data, sx.Len, sx.Len}))
x := unsafeBytes{uintptr(unsafe.Pointer(&v)), len(v), len(v)}
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

View File

@ -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)
}

View File

@ -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
}

View File

@ -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.
/*
@ -15,8 +15,8 @@ For compatibility with behaviour of msgpack-c reference implementation:
- Go intX (<0)
IS ENCODED AS
msgpack -ve fixnum, signed
*/
*/
package codec
import (
@ -25,7 +25,6 @@ import (
"math"
"net/rpc"
"reflect"
"time"
)
const (
@ -79,89 +78,6 @@ const (
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
// that the backend RPC service takes multiple arguments, which have been arranged
// in sequence in the slice.
@ -178,31 +94,21 @@ type msgpackContainerType struct {
}
var (
msgpackContainerStr = msgpackContainerType{
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,
}
msgpackContainerMap = msgpackContainerType{
16, mpFixMapMin, 0, mpMap16, mpMap32, true, false, false,
}
msgpackContainerStr = msgpackContainerType{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}
msgpackContainerMap = msgpackContainerType{16, mpFixMapMin, 0, mpMap16, mpMap32, true, false, false}
)
//---------------------------------------------
type msgpackEncDriver struct {
noBuiltInTypes
encDriverNoopContainerWriter
// encNoSeparator
encNoSeparator
e *Encoder
w encWriter
h *MsgpackHandle
x [8]byte
// _ [3]uint64 // padding
}
func (e *msgpackEncDriver) EncodeNil() {
@ -210,25 +116,10 @@ func (e *msgpackEncDriver) EncodeNil() {
}
func (e *msgpackEncDriver) EncodeInt(i int64) {
if e.h.PositiveIntUnsigned && i >= 0 {
if i >= 0 {
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 {
if e.h.NoFixedNum {
e.w.writen2(mpInt8, byte(i))
} else {
e.w.writen1(byte(i))
}
e.w.writen1(byte(i))
} else if i >= math.MinInt8 {
e.w.writen2(mpInt8, byte(i))
} else if i >= math.MinInt16 {
@ -245,11 +136,7 @@ func (e *msgpackEncDriver) EncodeInt(i int64) {
func (e *msgpackEncDriver) EncodeUint(i uint64) {
if i <= math.MaxInt8 {
if e.h.NoFixedNum {
e.w.writen2(mpUint8, byte(i))
} else {
e.w.writen1(byte(i))
}
e.w.writen1(byte(i))
} else if i <= math.MaxUint8 {
e.w.writen2(mpUint8, byte(i))
} 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))
}
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) {
bs := ext.WriteExt(v)
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.w.writeb(bs)
} 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)
}
func (e *msgpackEncDriver) WriteMapStart(length int) {
func (e *msgpackEncDriver) EncodeMapStart(length int) {
e.writeContainerLen(msgpackContainerMap, length)
}
func (e *msgpackEncDriver) EncodeString(c charEncoding, s string) {
slen := len(s)
if c == cRAW && e.h.WriteExt {
e.writeContainerLen(msgpackContainerBin, slen)
if c == c_RAW && e.h.WriteExt {
e.writeContainerLen(msgpackContainerBin, len(s))
} else {
e.writeContainerLen(msgpackContainerStr, slen)
e.writeContainerLen(msgpackContainerStr, len(s))
}
if slen > 0 {
if len(s) > 0 {
e.w.writestr(s)
}
}
func (e *msgpackEncDriver) EncodeSymbol(v string) {
e.EncodeString(c_UTF8, v)
}
func (e *msgpackEncDriver) EncodeStringBytes(c charEncoding, bs []byte) {
if bs == nil {
e.EncodeNil()
return
}
slen := len(bs)
if c == cRAW && e.h.WriteExt {
e.writeContainerLen(msgpackContainerBin, slen)
if c == c_RAW && e.h.WriteExt {
e.writeContainerLen(msgpackContainerBin, len(bs))
} else {
e.writeContainerLen(msgpackContainerStr, slen)
e.writeContainerLen(msgpackContainerStr, len(bs))
}
if slen > 0 {
if len(bs) > 0 {
e.w.writeb(bs)
}
}
@ -412,18 +264,16 @@ func (e *msgpackEncDriver) writeContainerLen(ct msgpackContainerType, l int) {
//---------------------------------------------
type msgpackDecDriver struct {
d *Decoder
r decReader
h *MsgpackHandle
// b [scratchByteArrayLen]byte
d *Decoder
r decReader // *Decoder decReader decReaderT
h *MsgpackHandle
b [scratchByteArrayLen]byte
bd byte
bdRead bool
br bool // bytes reader
noBuiltInTypes
// noStreamingCodec
// decNoSeparator
decDriverNoopContainerReader
// _ [3]uint64 // padding
noStreamingCodec
decNoSeparator
}
// Note: This returns either a primitive (int, bool, etc) for non-containers,
@ -436,7 +286,7 @@ func (d *msgpackDecDriver) DecodeNaked() {
d.readNextBd()
}
bd := d.bd
n := d.d.n
n := &d.d.n
var decodeFurther bool
switch bd {
@ -499,11 +349,11 @@ func (d *msgpackDecDriver) DecodeNaked() {
n.s = d.DecodeString()
} else {
n.v = valueTypeBytes
n.l = d.DecodeBytes(nil, false)
n.l = d.DecodeBytes(nil, false, false)
}
case bd == mpBin8, bd == mpBin16, bd == mpBin32:
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:
n.v = valueTypeArray
decodeFurther = true
@ -514,14 +364,9 @@ func (d *msgpackDecDriver) DecodeNaked() {
n.v = valueTypeExt
clen := d.readExtLen()
n.u = uint64(d.r.readn1())
if n.u == uint64(mpTimeExtTagU) {
n.v = valueTypeTime
n.t = d.decodeTime(clen)
} else {
n.l = d.r.readx(clen)
}
n.l = d.r.readx(clen)
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 {
@ -535,7 +380,7 @@ func (d *msgpackDecDriver) DecodeNaked() {
}
// 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 {
d.readNextBd()
}
@ -563,7 +408,14 @@ func (d *msgpackDecDriver) DecodeInt64() (i int64) {
case d.bd >= mpNegFixNumMin && d.bd <= mpNegFixNumMax:
i = int64(int8(d.bd))
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
}
}
@ -572,7 +424,7 @@ func (d *msgpackDecDriver) DecodeInt64() (i int64) {
}
// 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 {
d.readNextBd()
}
@ -589,28 +441,28 @@ func (d *msgpackDecDriver) DecodeUint64() (ui uint64) {
if i := int64(int8(d.r.readn1())); i >= 0 {
ui = uint64(i)
} 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
}
case mpInt16:
if i := int64(int16(bigen.Uint16(d.r.readx(2)))); i >= 0 {
ui = uint64(i)
} 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
}
case mpInt32:
if i := int64(int32(bigen.Uint32(d.r.readx(4)))); i >= 0 {
ui = uint64(i)
} 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
}
case mpInt64:
if i := int64(bigen.Uint64(d.r.readx(8))); i >= 0 {
ui = uint64(i)
} 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
}
default:
@ -618,10 +470,17 @@ func (d *msgpackDecDriver) DecodeUint64() (ui uint64) {
case d.bd >= mpPosFixNumMin && d.bd <= mpPosFixNumMax:
ui = uint64(d.bd)
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
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
}
}
@ -630,7 +489,7 @@ func (d *msgpackDecDriver) DecodeUint64() (ui uint64) {
}
// 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 {
d.readNextBd()
}
@ -639,7 +498,11 @@ func (d *msgpackDecDriver) DecodeFloat64() (f float64) {
} else if d.bd == mpDouble {
f = math.Float64frombits(bigen.Uint64(d.r.readx(8)))
} 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
return
@ -655,45 +518,25 @@ func (d *msgpackDecDriver) DecodeBool() (b bool) {
} else if d.bd == mpTrue || d.bd == 1 {
b = true
} 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
}
d.bdRead = false
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 {
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
vt := d.ContainerType()
switch vt {
case valueTypeBytes:
// valueTypeBytes may be a mpBin or an mpStr container
if bd == mpBin8 || bd == mpBin16 || bd == mpBin32 {
clen = d.readContainerLen(msgpackContainerBin)
} else {
clen = d.readContainerLen(msgpackContainerStr)
}
case valueTypeString:
// ignore isstring. Expect that the bytes may be found from msgpackContainerStr or msgpackContainerBin
if bd := d.bd; bd == mpBin8 || bd == mpBin16 || bd == mpBin32 {
clen = d.readContainerLen(msgpackContainerBin)
} else {
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
}
// these are (bin|str)(8|16|32)
// println("DecodeBytes: clen: ", clen)
d.bdRead = false
// bytes may be nil, so handle it. if nil, clen=-1.
if clen < 0 {
@ -703,18 +546,14 @@ func (d *msgpackDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte)
if d.br {
return d.r.readx(clen)
} 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) {
return string(d.DecodeBytes(d.d.b[:], true))
}
func (d *msgpackDecDriver) DecodeStringAsBytes() (s []byte) {
return d.DecodeBytes(d.d.b[:], true)
return string(d.DecodeBytes(d.b[:], true, true))
}
func (d *msgpackDecDriver) readNextBd() {
@ -722,17 +561,7 @@ func (d *msgpackDecDriver) readNextBd() {
d.bdRead = true
}
func (d *msgpackDecDriver) uncacheRead() {
if d.bdRead {
d.r.unreadn1()
d.bdRead = false
}
}
func (d *msgpackDecDriver) ContainerType() (vt valueType) {
if !d.bdRead {
d.readNextBd()
}
bd := d.bd
if bd == mpNil {
return valueTypeNil
@ -747,10 +576,9 @@ func (d *msgpackDecDriver) ContainerType() (vt valueType) {
return valueTypeArray
} else if bd == mpMap16 || bd == mpMap32 || (bd >= mpFixMapMin && bd <= mpFixMapMax) {
return valueTypeMap
} else {
// d.d.errorf("isContainerType: unsupported parameter: %v", vt)
}
// else {
// d.d.errorf("isContainerType: unsupported parameter: %v", vt)
// }
return valueTypeUnset
}
@ -760,7 +588,7 @@ func (d *msgpackDecDriver) TryDecodeAsNil() (v bool) {
}
if d.bd == mpNil {
d.bdRead = false
return true
v = true
}
return
}
@ -778,7 +606,7 @@ func (d *msgpackDecDriver) readContainerLen(ct msgpackContainerType) (clen int)
} else if (ct.bFixMin & bd) == ct.bFixMin {
clen = int(ct.bFixMin ^ bd)
} 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
}
d.bdRead = false
@ -786,16 +614,10 @@ func (d *msgpackDecDriver) readContainerLen(ct msgpackContainerType) (clen int)
}
func (d *msgpackDecDriver) ReadMapStart() int {
if !d.bdRead {
d.readNextBd()
}
return d.readContainerLen(msgpackContainerMap)
}
func (d *msgpackDecDriver) ReadArrayStart() int {
if !d.bdRead {
d.readNextBd()
}
return d.readContainerLen(msgpackContainerList)
}
@ -826,60 +648,9 @@ func (d *msgpackDecDriver) readExtLen() (clen int) {
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) {
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
}
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
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 ||
(xbd >= mpFixStrMin && xbd <= mpFixStrMax) {
xbs = d.DecodeStringAsBytes()
xbs = d.DecodeBytes(nil, true, true)
} else {
clen := d.readExtLen()
xtag = d.r.readn1()
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
}
xbs = d.r.readx(clen)
@ -926,9 +697,6 @@ type MsgpackHandle struct {
// RawToString controls how raw bytes are decoded into a nil interface{}.
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.
// 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
// a []byte or string based on the setting of RawToString.
WriteExt bool
// PositiveIntUnsigned says to encode positive integers as unsigned.
PositiveIntUnsigned bool
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) {
return h.SetExt(rt, tag, &extWrapper{ext, interfaceExtFailer{}})
return h.SetExt(rt, tag, &setExtWrapper{b: ext})
}
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 {
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() {
@ -971,7 +728,7 @@ func (e *msgpackEncDriver) 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
}
@ -993,7 +750,7 @@ func (c *msgpackSpecRpcCodec) WriteRequest(r *rpc.Request, body interface{}) err
bodyArr = []interface{}{body}
}
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 {
@ -1005,7 +762,7 @@ func (c *msgpackSpecRpcCodec) WriteResponse(r *rpc.Response, body interface{}) e
body = nil
}
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 {
@ -1025,6 +782,7 @@ func (c *msgpackSpecRpcCodec) ReadRequestBody(body interface{}) error {
}
func (c *msgpackSpecRpcCodec) parseCustomHeader(expectTypeByte byte, msgid *uint64, methodOrError *string) (err error) {
if c.isClosed() {
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)
// return
// }
var ba [1]byte
var n int
for {
n, err = c.r.Read(ba[:])
if err != nil {
return
}
if n == 1 {
break
}
var b byte
b, err = c.br.ReadByte()
if err != nil {
return
}
if b != fia {
err = fmt.Errorf("Unexpected value for array descriptor: Expecting %v. Received %v", fia, b)
return
}
var b = ba[0]
if b != fia {
err = fmt.Errorf("not array - %s %x/%s", msgBadDesc, b, mpdesc(b))
} else {
err = c.read(&b)
if err == nil {
if b != expectTypeByte {
err = fmt.Errorf("%s - expecting %v but got %x/%s",
msgBadDesc, expectTypeByte, b, mpdesc(b))
} else {
err = c.read(msgid)
if err == nil {
err = c.read(methodOrError)
}
}
}
if err = c.read(&b); err != nil {
return
}
if b != expectTypeByte {
err = fmt.Errorf("Unexpected byte descriptor in header. Expecting %v. Received %v", expectTypeByte, b)
return
}
if err = c.read(msgid); err != nil {
return
}
if err = c.read(methodOrError); err != nil {
return
}
return
}
@ -1078,8 +830,7 @@ type msgpackSpecRpc struct{}
// MsgpackSpecRpc implements Rpc using the communication protocol defined in
// the msgpack spec at https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md .
//
// See GoRpc documentation, for information on buffering for better performance.
// Its methods (ServerCodec and ClientCodec) return values that implement RpcCodecBuffered.
var MsgpackSpecRpc msgpackSpecRpc
func (x msgpackSpecRpc) ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec {

View File

@ -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.
package codec
import (
"bufio"
"errors"
"io"
"net/rpc"
"sync"
)
// rpcEncodeTerminator allows a handler specify a []byte terminator to send after each Encode.
//
// Some codecs like json need to put a space after each encoded value, to serve as a
// delimiter for things like numbers (else json codec will continue reading till EOF).
type rpcEncodeTerminator interface {
rpcEncodeTerminate() []byte
}
// Rpc provides a rpc Server or Client Codec for rpc communication.
type Rpc interface {
ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec
ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec
}
// RPCOptions holds options specific to rpc functionality
type RPCOptions struct {
// RPCNoBuffer configures whether we attempt to buffer reads and writes during RPC calls.
//
// Set RPCNoBuffer=true to turn buffering off.
// Buffering can still be done if buffered connections are passed in, or
// buffering is configured on the handle.
RPCNoBuffer bool
// RpcCodecBuffered allows access to the underlying bufio.Reader/Writer
// used by the rpc connection. It accomodates use-cases where the connection
// should be used by rpc and non-rpc functions, e.g. streaming a file after
// sending an rpc response.
type RpcCodecBuffered interface {
BufferedReader() *bufio.Reader
BufferedWriter() *bufio.Writer
}
// -------------------------------------
// rpcCodec defines the struct members and common methods.
type rpcCodec struct {
c io.Closer
r io.Reader
w io.Writer
f ioFlusher
rwc io.ReadWriteCloser
dec *Decoder
enc *Encoder
// bw *bufio.Writer
// br *bufio.Reader
mu sync.Mutex
h Handle
bw *bufio.Writer
br *bufio.Reader
mu sync.Mutex
h Handle
cls bool
clsmu sync.RWMutex
clsErr error
cls bool
clsmu sync.RWMutex
}
func newRPCCodec(conn io.ReadWriteCloser, h Handle) rpcCodec {
// return newRPCCodec2(bufio.NewReader(conn), bufio.NewWriter(conn), conn, h)
return newRPCCodec2(conn, conn, conn, h)
}
func newRPCCodec2(r io.Reader, w io.Writer, c io.Closer, h Handle) rpcCodec {
// defensive: ensure that jsonH has TermWhitespace turned on.
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
}
}
}
}
bw := bufio.NewWriter(conn)
br := bufio.NewReader(conn)
return rpcCodec{
c: c,
w: w,
r: r,
f: f,
rwc: conn,
bw: bw,
br: br,
enc: NewEncoder(bw, h),
dec: NewDecoder(br, 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() {
return c.clsErr
return io.EOF
}
err = c.enc.Encode(obj1)
if err == nil {
if writeObj2 {
err = c.enc.Encode(obj2)
}
// if err == nil && c.f != nil {
// err = c.f.Flush()
// }
if err = c.enc.Encode(obj1); err != nil {
return
}
if c.f != nil {
if err == nil {
err = c.f.Flush()
} else {
_ = c.f.Flush() // swallow flush error, so we maintain prior error on write
t, tOk := c.h.(rpcEncodeTerminator)
if tOk {
c.bw.Write(t.rpcEncodeTerminate())
}
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
}
func (c *rpcCodec) swallow(err *error) {
defer panicToErr(c.dec, err)
c.dec.swallow()
}
func (c *rpcCodec) read(obj interface{}) (err error) {
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 {
// var obj2 interface{}
// return c.dec.Decode(&obj2)
c.swallow(&err)
return
var obj2 interface{}
return c.dec.Decode(&obj2)
}
return c.dec.Decode(obj)
}
func (c *rpcCodec) isClosed() (b bool) {
if c.c != nil {
c.clsmu.RLock()
b = c.cls
c.clsmu.RUnlock()
}
return
func (c *rpcCodec) isClosed() bool {
c.clsmu.RLock()
x := c.cls
c.clsmu.RUnlock()
return x
}
func (c *rpcCodec) Close() error {
if c.c == nil || c.isClosed() {
return c.clsErr
if c.isClosed() {
return io.EOF
}
c.clsmu.Lock()
c.cls = true
c.clsErr = c.c.Close()
c.clsmu.Unlock()
return c.clsErr
return c.rwc.Close()
}
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
c.mu.Lock()
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 {
c.mu.Lock()
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 {
@ -191,36 +166,7 @@ func (c *goRpcCodec) ReadRequestBody(body interface{}) error {
type goRpc struct{}
// GoRpc implements Rpc using the communication protocol defined in net/rpc package.
//
// 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)
//
// Its methods (ServerCodec and ClientCodec) return values that implement RpcCodecBuffered.
var GoRpc goRpc
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 {
return &goRpcCodec{newRPCCodec(conn, h)}
}
var _ RpcCodecBuffered = (*rpcCodec)(nil) // ensure *rpcCodec implements RpcCodecBuffered

View File

@ -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.
package codec
@ -6,7 +6,6 @@ package codec
import (
"math"
"reflect"
"time"
)
const (
@ -21,8 +20,6 @@ const (
simpleVdPosInt = 8
simpleVdNegInt = 12
simpleVdTime = 24
// containers: each lasts for 4 (ie n, n+1, n+2, ... n+7)
simpleVdString = 216
simpleVdByteArray = 224
@ -33,15 +30,11 @@ const (
type simpleEncDriver struct {
noBuiltInTypes
// encNoSeparator
encNoSeparator
e *Encoder
h *SimpleHandle
w encWriter
b [8]byte
// c containerState
encDriverTrackContainerWriter
// encDriverNoopContainerWriter
_ [3]uint64 // padding
}
func (e *simpleEncDriver) EncodeNil() {
@ -49,10 +42,6 @@ func (e *simpleEncDriver) EncodeNil() {
}
func (e *simpleEncDriver) EncodeBool(b bool) {
if e.h.EncZeroValuesAsNil && e.c != containerMapKey && !b {
e.EncodeNil()
return
}
if b {
e.w.writen1(simpleVdTrue)
} else {
@ -61,19 +50,11 @@ func (e *simpleEncDriver) EncodeBool(b bool) {
}
func (e *simpleEncDriver) EncodeFloat32(f float32) {
if e.h.EncZeroValuesAsNil && e.c != containerMapKey && f == 0.0 {
e.EncodeNil()
return
}
e.w.writen1(simpleVdFloat32)
bigenHelper{e.b[:4], e.w}.writeUint32(math.Float32bits(f))
}
func (e *simpleEncDriver) EncodeFloat64(f float64) {
if e.h.EncZeroValuesAsNil && e.c != containerMapKey && f == 0.0 {
e.EncodeNil()
return
}
e.w.writen1(simpleVdFloat64)
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) {
if e.h.EncZeroValuesAsNil && e.c != containerMapKey && v == 0 {
e.EncodeNil()
return
}
if v <= math.MaxUint8 {
e.w.writen2(bd, uint8(v))
} else if v <= math.MaxUint16 {
@ -147,52 +124,25 @@ func (e *simpleEncDriver) encodeExtPreamble(xtag byte, length int) {
e.w.writen1(xtag)
}
func (e *simpleEncDriver) WriteArrayStart(length int) {
e.c = containerArrayStart
func (e *simpleEncDriver) EncodeArrayStart(length int) {
e.encLen(simpleVdArray, length)
}
func (e *simpleEncDriver) WriteMapStart(length int) {
e.c = containerMapStart
func (e *simpleEncDriver) EncodeMapStart(length int) {
e.encLen(simpleVdMap, length)
}
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.w.writestr(v)
}
// func (e *simpleEncDriver) EncodeSymbol(v string) {
// e.EncodeString(cUTF8, 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) EncodeSymbol(v string) {
e.EncodeString(c_UTF8, v)
}
func (e *simpleEncDriver) EncodeTime(t time.Time) {
// if e.h.EncZeroValuesAsNil && e.c != containerMapKey && t.IsZero() {
if t.IsZero() {
e.EncodeNil()
return
}
v, err := t.MarshalBinary()
if err != nil {
e.e.errorv(err)
return
}
// time.Time marshalbinary takes about 14 bytes.
e.w.writen2(simpleVdTime, uint8(len(v)))
func (e *simpleEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
e.encLen(simpleVdByteArray, len(v))
e.w.writeb(v)
}
@ -204,13 +154,11 @@ type simpleDecDriver struct {
r decReader
bdRead bool
bd byte
br bool // a bytes reader?
c containerState
// b [scratchByteArrayLen]byte
br bool // bytes reader
noBuiltInTypes
// noStreamingCodec
decDriverNoopContainerReader
// _ [3]uint64 // padding
noStreamingCodec
decNoSeparator
b [scratchByteArrayLen]byte
}
func (d *simpleDecDriver) readNextBd() {
@ -218,38 +166,24 @@ func (d *simpleDecDriver) readNextBd() {
d.bdRead = true
}
func (d *simpleDecDriver) uncacheRead() {
if d.bdRead {
d.r.unreadn1()
d.bdRead = false
}
}
func (d *simpleDecDriver) ContainerType() (vt valueType) {
if !d.bdRead {
d.readNextBd()
}
switch d.bd {
case simpleVdNil:
if d.bd == simpleVdNil {
return valueTypeNil
case simpleVdByteArray, simpleVdByteArray + 1,
simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
} else if d.bd == simpleVdByteArray || d.bd == simpleVdByteArray+1 ||
d.bd == simpleVdByteArray+2 || d.bd == simpleVdByteArray+3 || d.bd == simpleVdByteArray+4 {
return valueTypeBytes
case simpleVdString, simpleVdString + 1,
simpleVdString + 2, simpleVdString + 3, simpleVdString + 4:
} else if d.bd == simpleVdString || d.bd == simpleVdString+1 ||
d.bd == simpleVdString+2 || d.bd == simpleVdString+3 || d.bd == simpleVdString+4 {
return valueTypeString
case simpleVdArray, simpleVdArray + 1,
simpleVdArray + 2, simpleVdArray + 3, simpleVdArray + 4:
} else if d.bd == simpleVdArray || d.bd == simpleVdArray+1 ||
d.bd == simpleVdArray+2 || d.bd == simpleVdArray+3 || d.bd == simpleVdArray+4 {
return valueTypeArray
case simpleVdMap, simpleVdMap + 1,
simpleVdMap + 2, simpleVdMap + 3, simpleVdMap + 4:
} else if d.bd == simpleVdMap || d.bd == simpleVdMap+1 ||
d.bd == simpleVdMap+2 || d.bd == simpleVdMap+3 || d.bd == simpleVdMap+4 {
return valueTypeMap
// case simpleVdTime:
// return valueTypeTime
} else {
// d.d.errorf("isContainerType: unsupported parameter: %v", vt)
}
// else {
// d.d.errorf("isContainerType: unsupported parameter: %v", vt)
// }
return valueTypeUnset
}
@ -290,7 +224,7 @@ func (d *simpleDecDriver) decCheckInteger() (ui uint64, neg bool) {
ui = uint64(bigen.Uint64(d.r.readx(8)))
neg = true
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
}
// 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
}
func (d *simpleDecDriver) DecodeInt64() (i int64) {
func (d *simpleDecDriver) DecodeInt(bitsize uint8) (i int64) {
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 {
i = -i
}
d.bdRead = false
return
}
func (d *simpleDecDriver) DecodeUint64() (ui uint64) {
ui, neg := d.decCheckInteger()
if neg {
d.d.errorf("assigning negative signed value to unsigned type")
if chkOvf.Int(i, bitsize) {
d.d.errorf("simple: overflow integer: %v", i)
return
}
d.bdRead = false
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 {
d.readNextBd()
}
@ -331,12 +277,16 @@ func (d *simpleDecDriver) DecodeFloat64() (f float64) {
f = math.Float64frombits(bigen.Uint64(d.r.readx(8)))
} else {
if d.bd >= simpleVdPosInt && d.bd <= simpleVdNegInt+3 {
f = float64(d.DecodeInt64())
f = float64(d.DecodeInt(64))
} 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
}
}
if chkOverflow32 && chkOvf.Float32(f) {
d.d.errorf("msgpack: float32 overflow: %v", f)
return
}
d.bdRead = false
return
}
@ -350,7 +300,7 @@ func (d *simpleDecDriver) DecodeBool() (b bool) {
b = true
} else if d.bd == simpleVdFalse {
} 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
}
d.bdRead = false
@ -358,43 +308,15 @@ func (d *simpleDecDriver) DecodeBool() (b bool) {
}
func (d *simpleDecDriver) ReadMapStart() (length int) {
if !d.bdRead {
d.readNextBd()
}
d.bdRead = false
d.c = containerMapStart
return d.decLen()
}
func (d *simpleDecDriver) ReadArrayStart() (length int) {
if !d.bdRead {
d.readNextBd()
}
d.bdRead = false
d.c = containerArrayStart
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 {
switch d.bd % 8 {
case 0:
@ -406,31 +328,27 @@ func (d *simpleDecDriver) decLen() int {
case 3:
ui := uint64(bigen.Uint32(d.r.readx(4)))
if chkOvf.Uint(ui, intBitsize) {
d.d.errorf("overflow integer: %v", ui)
d.d.errorf("simple: overflow integer: %v", ui)
return 0
}
return int(ui)
case 4:
ui := bigen.Uint64(d.r.readx(8))
if chkOvf.Uint(ui, intBitsize) {
d.d.errorf("overflow integer: %v", ui)
d.d.errorf("simple: overflow integer: %v", ui)
return 0
}
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
}
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) {
return d.DecodeBytes(d.d.b[:], true)
}
func (d *simpleDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
func (d *simpleDecDriver) DecodeBytes(bs []byte, isstring, zerocopy bool) (bsOut []byte) {
if !d.bdRead {
d.readNextBd()
}
@ -438,51 +356,21 @@ func (d *simpleDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
d.bdRead = false
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()
d.bdRead = false
if zerocopy {
if d.br {
return d.r.readx(clen)
} else if len(bs) == 0 {
bs = d.d.b[:]
bs = d.b[:]
}
}
return decByteSlice(d.r, clen, d.d.h.MaxInitLen, 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
return decByteSlice(d.r, clen, bs)
}
func (d *simpleDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) {
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
}
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()
xtag = d.r.readn1()
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
}
xbs = d.r.readx(l)
case simpleVdByteArray, simpleVdByteArray + 1,
simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
xbs = d.DecodeBytes(nil, true)
case simpleVdByteArray, simpleVdByteArray + 1, simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
xbs = d.DecodeBytes(nil, false, true)
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
}
d.bdRead = false
@ -526,7 +413,7 @@ func (d *simpleDecDriver) DecodeNaked() {
d.readNextBd()
}
n := d.d.n
n := &d.d.n
var decodeFurther bool
switch d.bd {
@ -541,45 +428,39 @@ func (d *simpleDecDriver) DecodeNaked() {
case simpleVdPosInt, simpleVdPosInt + 1, simpleVdPosInt + 2, simpleVdPosInt + 3:
if d.h.SignedInteger {
n.v = valueTypeInt
n.i = d.DecodeInt64()
n.i = d.DecodeInt(64)
} else {
n.v = valueTypeUint
n.u = d.DecodeUint64()
n.u = d.DecodeUint(64)
}
case simpleVdNegInt, simpleVdNegInt + 1, simpleVdNegInt + 2, simpleVdNegInt + 3:
n.v = valueTypeInt
n.i = d.DecodeInt64()
n.i = d.DecodeInt(64)
case simpleVdFloat32:
n.v = valueTypeFloat
n.f = d.DecodeFloat64()
n.f = d.DecodeFloat(true)
case simpleVdFloat64:
n.v = valueTypeFloat
n.f = d.DecodeFloat64()
case simpleVdTime:
n.v = valueTypeTime
n.t = d.DecodeTime()
case simpleVdString, simpleVdString + 1,
simpleVdString + 2, simpleVdString + 3, simpleVdString + 4:
n.f = d.DecodeFloat(false)
case simpleVdString, simpleVdString + 1, simpleVdString + 2, simpleVdString + 3, simpleVdString + 4:
n.v = valueTypeString
n.s = d.DecodeString()
case simpleVdByteArray, simpleVdByteArray + 1,
simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
case simpleVdByteArray, simpleVdByteArray + 1, simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
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:
n.v = valueTypeExt
l := d.decLen()
n.u = uint64(d.r.readn1())
n.l = d.r.readx(l)
case simpleVdArray, simpleVdArray + 1, simpleVdArray + 2,
simpleVdArray + 3, simpleVdArray + 4:
case simpleVdArray, simpleVdArray + 1, simpleVdArray + 2, simpleVdArray + 3, simpleVdArray + 4:
n.v = valueTypeArray
decodeFurther = true
case simpleVdMap, simpleVdMap + 1, simpleVdMap + 2, simpleVdMap + 3, simpleVdMap + 4:
n.v = valueTypeMap
decodeFurther = true
default:
d.d.errorf("cannot infer value - %s 0x%x", msgBadDesc, d.bd)
d.d.errorf("decodeNaked: Unrecognized d.bd: 0x%x", d.bd)
}
if !decodeFurther {
@ -593,12 +474,12 @@ func (d *simpleDecDriver) DecodeNaked() {
// SimpleHandle is a Handle for a very simple encoding format.
//
// simple is a simplistic codec similar to binc, but not as compact.
// - Encoding of a value is always 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)
// - Integers (intXXX, uintXXX) are encoded in 1, 2, 4 or 8 bytes (plus a descriptor byte).
// There are positive (uintXXX and intXXX >= 0) and negative (intXXX < 0) integers.
// - Floats are encoded in 4 or 8 bytes (plus a descriptor byte)
// - Length of containers (strings, bytes, array, map, extensions)
// - Lenght of containers (strings, bytes, array, map, extensions)
// are encoded in 0, 1, 2, 4 or 8 bytes.
// Zero-length containers have no length encoded.
// For others, the number of bytes is given by pow(2, bd%3)
@ -606,45 +487,31 @@ func (d *simpleDecDriver) DecodeNaked() {
// - arrays are encoded as [bd] [length] [value]...
// - extensions are encoded as [bd] [length] [tag] [byte]...
// - strings/bytearrays are encoded as [bd] [length] [byte]...
// - time.Time are encoded as [bd] [length] [byte]...
//
// The full spec will be published soon.
type SimpleHandle struct {
BasicHandle
binaryEncodingType
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) {
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 {
return &simpleEncDriver{e: e, w: e.w, h: h}
}
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() {
e.c = 0
e.w = e.e.w
}
func (d *simpleDecDriver) reset() {
d.c = 0
d.r, d.br = d.d.r, d.d.bytes
d.r = d.d.r
d.bd, d.bdRead = 0, false
}

View File

@ -34,7 +34,7 @@ def get_test_data_list():
True,
u"null",
None,
u"some&day>some<day",
u"someday",
1328176922000002000,
u"",
-2206187877999998000,
@ -84,7 +84,7 @@ def doRpcServer(port, stopTimeSec):
def EchoStruct(self, msg):
return ("%s" % msg)
addr = msgpackrpc.Address('127.0.0.1', port)
addr = msgpackrpc.Address('localhost', port)
server = msgpackrpc.Server(EchoHandler())
server.listen(addr)
# run thread to stop it after stopTimeSec seconds if > 0
@ -96,14 +96,14 @@ def doRpcServer(port, stopTimeSec):
server.start()
def doRpcClientToPythonSvc(port):
address = msgpackrpc.Address('127.0.0.1', port)
address = msgpackrpc.Address('localhost', port)
client = msgpackrpc.Client(address, unpack_encoding='utf-8')
print client.call("Echo123", "A1", "B2", "C3")
print client.call("EchoStruct", {"A" :"Aa", "B":"Bb", "C":"Cc"})
def doRpcClientToGoSvc(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')
print client.call("TestRpcInt.Echo123", ["A1", "B2", "C3"])
print client.call("TestRpcInt.EchoStruct", {"A" :"Aa", "B":"Bb", "C":"Cc"})

6
vendor/modules.txt vendored
View File

@ -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/cvm/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/utils
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/response
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/ugorji/go v0.0.0-20180813092308-00b869d2f4a5
# github.com/ugorji/go v0.0.0-20151218193438-646ae4a518c1
github.com/ugorji/go/codec
# github.com/ulikunitz/xz v0.5.5
github.com/ulikunitz/xz