Merge pull request #12876 from tagomoris/logger-driver-fluentd
Add new Logging driver "fluentd"
This commit is contained in:
commit
b96f109344
33 changed files with 7763 additions and 3 deletions
|
@ -3,6 +3,7 @@ package daemon
|
|||
// Importing packages here only to make sure their init gets called and
|
||||
// therefore they register themselves to the logdriver factory.
|
||||
import (
|
||||
_ "github.com/docker/docker/daemon/logger/fluentd"
|
||||
_ "github.com/docker/docker/daemon/logger/gelf"
|
||||
_ "github.com/docker/docker/daemon/logger/journald"
|
||||
_ "github.com/docker/docker/daemon/logger/jsonfilelog"
|
||||
|
|
129
daemon/logger/fluentd/fluentd.go
Normal file
129
daemon/logger/fluentd/fluentd.go
Normal file
|
@ -0,0 +1,129 @@
|
|||
package fluentd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"math"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/daemon/logger"
|
||||
"github.com/fluent/fluent-logger-golang/fluent"
|
||||
)
|
||||
|
||||
type Fluentd struct {
|
||||
tag string
|
||||
containerID string
|
||||
containerName string
|
||||
writer *fluent.Fluent
|
||||
}
|
||||
|
||||
type Receiver struct {
|
||||
ID string
|
||||
FullID string
|
||||
Name string
|
||||
}
|
||||
|
||||
const (
|
||||
name = "fluentd"
|
||||
defaultHostName = "localhost"
|
||||
defaultPort = 24224
|
||||
defaultTagPrefix = "docker"
|
||||
)
|
||||
|
||||
func init() {
|
||||
if err := logger.RegisterLogDriver(name, New); err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func parseConfig(ctx logger.Context) (string, int, string, error) {
|
||||
host := defaultHostName
|
||||
port := defaultPort
|
||||
tag := "docker." + ctx.ContainerID[:12]
|
||||
|
||||
config := ctx.Config
|
||||
|
||||
if address := config["fluentd-address"]; address != "" {
|
||||
if h, p, err := net.SplitHostPort(address); err != nil {
|
||||
if !strings.Contains(err.Error(), "missing port in address") {
|
||||
return "", 0, "", err
|
||||
}
|
||||
host = h
|
||||
} else {
|
||||
portnum, err := strconv.Atoi(p)
|
||||
if err != nil {
|
||||
return "", 0, "", err
|
||||
}
|
||||
host = h
|
||||
port = portnum
|
||||
}
|
||||
}
|
||||
|
||||
if config["fluentd-tag"] != "" {
|
||||
receiver := &Receiver{
|
||||
ID: ctx.ContainerID[:12],
|
||||
FullID: ctx.ContainerID,
|
||||
Name: ctx.ContainerName,
|
||||
}
|
||||
tmpl, err := template.New("tag").Parse(config["fluentd-tag"])
|
||||
if err != nil {
|
||||
return "", 0, "", err
|
||||
}
|
||||
buf := new(bytes.Buffer)
|
||||
if err := tmpl.Execute(buf, receiver); err != nil {
|
||||
return "", 0, "", err
|
||||
}
|
||||
tag = buf.String()
|
||||
}
|
||||
|
||||
return host, port, tag, nil
|
||||
}
|
||||
|
||||
func New(ctx logger.Context) (logger.Logger, error) {
|
||||
host, port, tag, err := parseConfig(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logrus.Debugf("logging driver fluentd configured for container:%s, host:%s, port:%d, tag:%s.", ctx.ContainerID, host, port, tag)
|
||||
|
||||
// logger tries to recoonect 2**64 - 1 times
|
||||
// failed (and panic) after 204 years [ 1.5 ** (2**32 - 1) - 1 seconds]
|
||||
log, err := fluent.New(fluent.Config{FluentPort: port, FluentHost: host, RetryWait: 1000, MaxRetry: math.MaxUint32})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Fluentd{
|
||||
tag: tag,
|
||||
containerID: ctx.ContainerID,
|
||||
containerName: ctx.ContainerName,
|
||||
writer: log,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (f *Fluentd) Log(msg *logger.Message) error {
|
||||
data := map[string]string{
|
||||
"container_id": f.containerID,
|
||||
"container_name": f.containerName,
|
||||
"source": msg.Source,
|
||||
"log": string(msg.Line),
|
||||
}
|
||||
// fluent-logger-golang buffers logs from failures and disconnections,
|
||||
// and these are transferred again automatically.
|
||||
return f.writer.PostWithTime(f.tag, msg.Timestamp, data)
|
||||
}
|
||||
|
||||
func (f *Fluentd) Close() error {
|
||||
return f.writer.Close()
|
||||
}
|
||||
|
||||
func (f *Fluentd) Name() string {
|
||||
return name
|
||||
}
|
||||
|
||||
func (s *Fluentd) GetReader() (io.Reader, error) {
|
||||
return nil, logger.ReadLogsNotSupported
|
||||
}
|
|
@ -884,6 +884,16 @@ container's logging driver. The following options are supported:
|
|||
driver. For detailed information on working with logging drivers, see
|
||||
[Configure a logging driver](reference/logging/).
|
||||
|
||||
#### Logging driver: fluentd
|
||||
|
||||
Fluentd logging driver for Docker. Writes log messages to fluentd (forward input). `docker logs`
|
||||
command is not available for this logging driver.
|
||||
|
||||
Some options are supported by specifying `--log-opt` as many as needed, like `--log-opt fluentd-address=localhost:24224 --log-opt fluentd-tag=docker.{{.Name}}`.
|
||||
|
||||
- `fluentd-address`: specify `host:port` to connect [localhost:24224]
|
||||
- `fluentd-tag`: specify tag for fluentd message, which interpret some markup, ex `{{.ID}}`, `{{.FullID}}` or `{{.Name}}` [docker.{{.ID}}]
|
||||
|
||||
## Overriding Dockerfile image defaults
|
||||
|
||||
When a developer builds an image from a [*Dockerfile*](/reference/builder)
|
||||
|
|
|
@ -42,4 +42,9 @@ clone git github.com/syndtr/gocapability 66ef2aa7a23ba682594e2b6f74cf40c0692b49f
|
|||
clone git github.com/golang/protobuf 655cdfa588ea
|
||||
clone git github.com/Graylog2/go-gelf 6c62a85f1d47a67f2a5144c0e745b325889a8120
|
||||
|
||||
clone git github.com/fluent/fluent-logger-golang v1.0.0
|
||||
# fluent-logger-golang deps
|
||||
clone git github.com/philhofer/fwd 899e4efba8eaa1fea74175308f3fae18ff3319fa
|
||||
clone git github.com/tinylib/msgp 75ee40d2601edf122ef667e2a07d600d4c44490c
|
||||
|
||||
clean
|
||||
|
|
|
@ -155,7 +155,7 @@ two memory nodes.
|
|||
**--lxc-conf**=[]
|
||||
(lxc exec-driver only) Add custom lxc options --lxc-conf="lxc.cgroup.cpuset.cpus = 0,1"
|
||||
|
||||
**--log-driver**="|*json-file*|*syslog*|*journald*|*gelf*|*none*"
|
||||
**--log-driver**="|*json-file*|*syslog*|*journald*|*gelf*|*fluentd*|*none*"
|
||||
Logging driver for container. Default is defined by daemon `--log-driver` flag.
|
||||
**Warning**: `docker logs` command works only for `json-file` logging driver.
|
||||
|
||||
|
|
|
@ -252,7 +252,7 @@ which interface and port to use.
|
|||
**--lxc-conf**=[]
|
||||
(lxc exec-driver only) Add custom lxc options --lxc-conf="lxc.cgroup.cpuset.cpus = 0,1"
|
||||
|
||||
**--log-driver**="|*json-file*|*syslog*|*journald*|*gelf*|*none*"
|
||||
**--log-driver**="|*json-file*|*syslog*|*journald*|*gelf*|*fluentd*|*none*"
|
||||
Logging driver for container. Default is defined by daemon `--log-driver` flag.
|
||||
**Warning**: `docker logs` command works only for `json-file` logging driver.
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ unix://[/path/to/socket] to use.
|
|||
**--label**="[]"
|
||||
Set key=value labels to the daemon (displayed in `docker info`)
|
||||
|
||||
**--log-driver**="*json-file*|*syslog*|*journald*|*gelf*|*none*"
|
||||
**--log-driver**="*json-file*|*syslog*|*journald*|*gelf*|*fluentd*|*none*"
|
||||
Default driver for container logs. Default is `json-file`.
|
||||
**Warning**: `docker logs` command works only for `json-file` logging driver.
|
||||
|
||||
|
|
245
vendor/src/github.com/fluent/fluent-logger-golang/fluent/fluent.go
vendored
Normal file
245
vendor/src/github.com/fluent/fluent-logger-golang/fluent/fluent.go
vendored
Normal file
|
@ -0,0 +1,245 @@
|
|||
package fluent
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultHost = "127.0.0.1"
|
||||
defaultPort = 24224
|
||||
defaultTimeout = 3 * time.Second
|
||||
defaultBufferLimit = 8 * 1024 * 1024
|
||||
defaultRetryWait = 500
|
||||
defaultMaxRetry = 13
|
||||
defaultReconnectWaitIncreRate = 1.5
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
FluentPort int
|
||||
FluentHost string
|
||||
Timeout time.Duration
|
||||
BufferLimit int
|
||||
RetryWait int
|
||||
MaxRetry int
|
||||
TagPrefix string
|
||||
}
|
||||
|
||||
type Fluent struct {
|
||||
Config
|
||||
conn net.Conn
|
||||
pending []byte
|
||||
reconnecting bool
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// New creates a new Logger.
|
||||
func New(config Config) (f *Fluent, err error) {
|
||||
if config.FluentHost == "" {
|
||||
config.FluentHost = defaultHost
|
||||
}
|
||||
if config.FluentPort == 0 {
|
||||
config.FluentPort = defaultPort
|
||||
}
|
||||
if config.Timeout == 0 {
|
||||
config.Timeout = defaultTimeout
|
||||
}
|
||||
if config.BufferLimit == 0 {
|
||||
config.BufferLimit = defaultBufferLimit
|
||||
}
|
||||
if config.RetryWait == 0 {
|
||||
config.RetryWait = defaultRetryWait
|
||||
}
|
||||
if config.MaxRetry == 0 {
|
||||
config.MaxRetry = defaultMaxRetry
|
||||
}
|
||||
f = &Fluent{Config: config, reconnecting: false}
|
||||
err = f.connect()
|
||||
return
|
||||
}
|
||||
|
||||
// Post writes the output for a logging event.
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// // send string
|
||||
// f.Post("tag_name", "data")
|
||||
//
|
||||
// // send map[string]
|
||||
// mapStringData := map[string]string{
|
||||
// "foo": "bar",
|
||||
// }
|
||||
// f.Post("tag_name", mapStringData)
|
||||
//
|
||||
// // send message with specified time
|
||||
// mapStringData := map[string]string{
|
||||
// "foo": "bar",
|
||||
// }
|
||||
// tm := time.Now()
|
||||
// f.PostWithTime("tag_name", tm, mapStringData)
|
||||
//
|
||||
// // send struct
|
||||
// structData := struct {
|
||||
// Name string `msg:"name"`
|
||||
// } {
|
||||
// "john smith",
|
||||
// }
|
||||
// f.Post("tag_name", structData)
|
||||
//
|
||||
func (f *Fluent) Post(tag string, message interface{}) error {
|
||||
timeNow := time.Now()
|
||||
return f.PostWithTime(tag, timeNow, message)
|
||||
}
|
||||
|
||||
func (f *Fluent) PostWithTime(tag string, tm time.Time, message interface{}) error {
|
||||
if len(f.TagPrefix) > 0 {
|
||||
tag = f.TagPrefix + "." + tag
|
||||
}
|
||||
|
||||
msg := reflect.ValueOf(message)
|
||||
msgtype := msg.Type()
|
||||
|
||||
if msgtype.Kind() == reflect.Struct {
|
||||
// message should be tagged by "codec" or "msg"
|
||||
kv := make(map[string]interface{})
|
||||
fields := msgtype.NumField()
|
||||
for i := 0; i < fields; i++ {
|
||||
field := msgtype.Field(i)
|
||||
name := field.Name
|
||||
if n1 := field.Tag.Get("msg"); n1 != "" {
|
||||
name = n1
|
||||
} else if n2 := field.Tag.Get("codec"); n2 != "" {
|
||||
name = n2
|
||||
}
|
||||
kv[name] = msg.FieldByIndex(field.Index).Interface()
|
||||
}
|
||||
return f.EncodeAndPostData(tag, tm, kv)
|
||||
}
|
||||
|
||||
if msgtype.Kind() != reflect.Map {
|
||||
return errors.New("messge must be a map")
|
||||
} else if msgtype.Key().Kind() != reflect.String {
|
||||
return errors.New("map keys must be strings")
|
||||
}
|
||||
|
||||
kv := make(map[string]interface{})
|
||||
for _, k := range msg.MapKeys() {
|
||||
kv[k.String()] = msg.MapIndex(k).Interface()
|
||||
}
|
||||
|
||||
return f.EncodeAndPostData(tag, tm, kv)
|
||||
}
|
||||
|
||||
func (f *Fluent) EncodeAndPostData(tag string, tm time.Time, message interface{}) error {
|
||||
if data, dumperr := f.EncodeData(tag, tm, message); dumperr != nil {
|
||||
return fmt.Errorf("fluent#EncodeAndPostData: can't convert '%s' to msgpack:%s", message, dumperr)
|
||||
// fmt.Println("fluent#Post: can't convert to msgpack:", message, dumperr)
|
||||
} else {
|
||||
f.PostRawData(data)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Fluent) PostRawData(data []byte) {
|
||||
f.mu.Lock()
|
||||
f.pending = append(f.pending, data...)
|
||||
f.mu.Unlock()
|
||||
if err := f.send(); err != nil {
|
||||
f.close()
|
||||
if len(f.pending) > f.Config.BufferLimit {
|
||||
f.flushBuffer()
|
||||
}
|
||||
} else {
|
||||
f.flushBuffer()
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Fluent) EncodeData(tag string, tm time.Time, message interface{}) (data []byte, err error) {
|
||||
timeUnix := tm.Unix()
|
||||
msg := &Message{Tag: tag, Time: timeUnix, Record: message}
|
||||
data, err = msg.MarshalMsg(nil)
|
||||
return
|
||||
}
|
||||
|
||||
// Close closes the connection.
|
||||
func (f *Fluent) Close() (err error) {
|
||||
if len(f.pending) > 0 {
|
||||
_ = f.send()
|
||||
}
|
||||
err = f.close()
|
||||
return
|
||||
}
|
||||
|
||||
// close closes the connection.
|
||||
func (f *Fluent) close() (err error) {
|
||||
if f.conn != nil {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
} else {
|
||||
return
|
||||
}
|
||||
if f.conn != nil {
|
||||
f.conn.Close()
|
||||
f.conn = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// connect establishes a new connection using the specified transport.
|
||||
func (f *Fluent) connect() (err error) {
|
||||
f.conn, err = net.DialTimeout("tcp", f.Config.FluentHost+":"+strconv.Itoa(f.Config.FluentPort), f.Config.Timeout)
|
||||
return
|
||||
}
|
||||
|
||||
func e(x, y float64) int {
|
||||
return int(math.Pow(x, y))
|
||||
}
|
||||
|
||||
func (f *Fluent) reconnect() {
|
||||
go func() {
|
||||
for i := 0; ; i++ {
|
||||
err := f.connect()
|
||||
if err == nil {
|
||||
f.mu.Lock()
|
||||
f.reconnecting = false
|
||||
f.mu.Unlock()
|
||||
break
|
||||
} else {
|
||||
if i == f.Config.MaxRetry {
|
||||
panic("fluent#reconnect: failed to reconnect!")
|
||||
}
|
||||
waitTime := f.Config.RetryWait * e(defaultReconnectWaitIncreRate, float64(i-1))
|
||||
time.Sleep(time.Duration(waitTime) * time.Millisecond)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (f *Fluent) flushBuffer() {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
f.pending = f.pending[0:0]
|
||||
}
|
||||
|
||||
func (f *Fluent) send() (err error) {
|
||||
if f.conn == nil {
|
||||
if f.reconnecting == false {
|
||||
f.mu.Lock()
|
||||
f.reconnecting = true
|
||||
f.mu.Unlock()
|
||||
f.reconnect()
|
||||
}
|
||||
err = errors.New("fluent#send: can't send logs, client is reconnecting")
|
||||
} else {
|
||||
f.mu.Lock()
|
||||
_, err = f.conn.Write(f.pending)
|
||||
f.mu.Unlock()
|
||||
}
|
||||
return
|
||||
}
|
24
vendor/src/github.com/fluent/fluent-logger-golang/fluent/proto.go
vendored
Normal file
24
vendor/src/github.com/fluent/fluent-logger-golang/fluent/proto.go
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
//go:generate msgp
|
||||
|
||||
package fluent
|
||||
|
||||
//msgp:tuple Entry
|
||||
type Entry struct {
|
||||
Time int64 `msg:"time"`
|
||||
Record interface{} `msg:"record"`
|
||||
}
|
||||
|
||||
//msgp:tuple Forward
|
||||
type Forward struct {
|
||||
Tag string `msg:"tag"`
|
||||
Entries []Entry `msg:"entries"`
|
||||
Option interface{} `msg:"option"`
|
||||
}
|
||||
|
||||
//msgp:tuple Message
|
||||
type Message struct {
|
||||
Tag string `msg:"tag"`
|
||||
Time int64 `msg:"time"`
|
||||
Record interface{} `msg:"record"`
|
||||
Option interface{} `msg:"option"`
|
||||
}
|
372
vendor/src/github.com/fluent/fluent-logger-golang/fluent/proto_gen.go
vendored
Normal file
372
vendor/src/github.com/fluent/fluent-logger-golang/fluent/proto_gen.go
vendored
Normal file
|
@ -0,0 +1,372 @@
|
|||
package fluent
|
||||
|
||||
// NOTE: THIS FILE WAS PRODUCED BY THE
|
||||
// MSGP CODE GENERATION TOOL (github.com/tinylib/msgp)
|
||||
// DO NOT EDIT
|
||||
|
||||
import (
|
||||
"github.com/tinylib/msgp/msgp"
|
||||
)
|
||||
|
||||
// DecodeMsg implements msgp.Decodable
|
||||
func (z *Entry) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||
var ssz uint32
|
||||
ssz, err = dc.ReadArrayHeader()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if ssz != 2 {
|
||||
err = msgp.ArrayError{Wanted: 2, Got: ssz}
|
||||
return
|
||||
}
|
||||
z.Time, err = dc.ReadInt64()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
z.Record, err = dc.ReadIntf()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// EncodeMsg implements msgp.Encodable
|
||||
func (z Entry) EncodeMsg(en *msgp.Writer) (err error) {
|
||||
err = en.WriteArrayHeader(2)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteInt64(z.Time)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteIntf(z.Record)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalMsg implements msgp.Marshaler
|
||||
func (z Entry) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
o = msgp.AppendArrayHeader(o, 2)
|
||||
o = msgp.AppendInt64(o, z.Time)
|
||||
o, err = msgp.AppendIntf(o, z.Record)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *Entry) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
{
|
||||
var ssz uint32
|
||||
ssz, bts, err = msgp.ReadArrayHeaderBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if ssz != 2 {
|
||||
err = msgp.ArrayError{Wanted: 2, Got: ssz}
|
||||
return
|
||||
}
|
||||
}
|
||||
z.Time, bts, err = msgp.ReadInt64Bytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
z.Record, bts, err = msgp.ReadIntfBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
func (z Entry) Msgsize() (s int) {
|
||||
s = msgp.ArrayHeaderSize + msgp.Int64Size + msgp.GuessSize(z.Record)
|
||||
return
|
||||
}
|
||||
|
||||
// DecodeMsg implements msgp.Decodable
|
||||
func (z *Forward) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||
var ssz uint32
|
||||
ssz, err = dc.ReadArrayHeader()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if ssz != 3 {
|
||||
err = msgp.ArrayError{Wanted: 3, Got: ssz}
|
||||
return
|
||||
}
|
||||
z.Tag, err = dc.ReadString()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var xsz uint32
|
||||
xsz, err = dc.ReadArrayHeader()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if cap(z.Entries) >= int(xsz) {
|
||||
z.Entries = z.Entries[:xsz]
|
||||
} else {
|
||||
z.Entries = make([]Entry, xsz)
|
||||
}
|
||||
for xvk := range z.Entries {
|
||||
var ssz uint32
|
||||
ssz, err = dc.ReadArrayHeader()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if ssz != 2 {
|
||||
err = msgp.ArrayError{Wanted: 2, Got: ssz}
|
||||
return
|
||||
}
|
||||
z.Entries[xvk].Time, err = dc.ReadInt64()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
z.Entries[xvk].Record, err = dc.ReadIntf()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
z.Option, err = dc.ReadIntf()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// EncodeMsg implements msgp.Encodable
|
||||
func (z *Forward) EncodeMsg(en *msgp.Writer) (err error) {
|
||||
err = en.WriteArrayHeader(3)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteString(z.Tag)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteArrayHeader(uint32(len(z.Entries)))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for xvk := range z.Entries {
|
||||
err = en.WriteArrayHeader(2)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteInt64(z.Entries[xvk].Time)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteIntf(z.Entries[xvk].Record)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
err = en.WriteIntf(z.Option)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalMsg implements msgp.Marshaler
|
||||
func (z *Forward) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
o = msgp.AppendArrayHeader(o, 3)
|
||||
o = msgp.AppendString(o, z.Tag)
|
||||
o = msgp.AppendArrayHeader(o, uint32(len(z.Entries)))
|
||||
for xvk := range z.Entries {
|
||||
o = msgp.AppendArrayHeader(o, 2)
|
||||
o = msgp.AppendInt64(o, z.Entries[xvk].Time)
|
||||
o, err = msgp.AppendIntf(o, z.Entries[xvk].Record)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
o, err = msgp.AppendIntf(o, z.Option)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *Forward) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
{
|
||||
var ssz uint32
|
||||
ssz, bts, err = msgp.ReadArrayHeaderBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if ssz != 3 {
|
||||
err = msgp.ArrayError{Wanted: 3, Got: ssz}
|
||||
return
|
||||
}
|
||||
}
|
||||
z.Tag, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var xsz uint32
|
||||
xsz, bts, err = msgp.ReadArrayHeaderBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if cap(z.Entries) >= int(xsz) {
|
||||
z.Entries = z.Entries[:xsz]
|
||||
} else {
|
||||
z.Entries = make([]Entry, xsz)
|
||||
}
|
||||
for xvk := range z.Entries {
|
||||
{
|
||||
var ssz uint32
|
||||
ssz, bts, err = msgp.ReadArrayHeaderBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if ssz != 2 {
|
||||
err = msgp.ArrayError{Wanted: 2, Got: ssz}
|
||||
return
|
||||
}
|
||||
}
|
||||
z.Entries[xvk].Time, bts, err = msgp.ReadInt64Bytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
z.Entries[xvk].Record, bts, err = msgp.ReadIntfBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
z.Option, bts, err = msgp.ReadIntfBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
func (z *Forward) Msgsize() (s int) {
|
||||
s = msgp.ArrayHeaderSize + msgp.StringPrefixSize + len(z.Tag) + msgp.ArrayHeaderSize
|
||||
for xvk := range z.Entries {
|
||||
s += msgp.ArrayHeaderSize + msgp.Int64Size + msgp.GuessSize(z.Entries[xvk].Record)
|
||||
}
|
||||
s += msgp.GuessSize(z.Option)
|
||||
return
|
||||
}
|
||||
|
||||
// DecodeMsg implements msgp.Decodable
|
||||
func (z *Message) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||
var ssz uint32
|
||||
ssz, err = dc.ReadArrayHeader()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if ssz != 4 {
|
||||
err = msgp.ArrayError{Wanted: 4, Got: ssz}
|
||||
return
|
||||
}
|
||||
z.Tag, err = dc.ReadString()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
z.Time, err = dc.ReadInt64()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
z.Record, err = dc.ReadIntf()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
z.Option, err = dc.ReadIntf()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// EncodeMsg implements msgp.Encodable
|
||||
func (z *Message) EncodeMsg(en *msgp.Writer) (err error) {
|
||||
err = en.WriteArrayHeader(4)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteString(z.Tag)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteInt64(z.Time)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteIntf(z.Record)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteIntf(z.Option)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalMsg implements msgp.Marshaler
|
||||
func (z *Message) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
o = msgp.AppendArrayHeader(o, 4)
|
||||
o = msgp.AppendString(o, z.Tag)
|
||||
o = msgp.AppendInt64(o, z.Time)
|
||||
o, err = msgp.AppendIntf(o, z.Record)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
o, err = msgp.AppendIntf(o, z.Option)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *Message) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
{
|
||||
var ssz uint32
|
||||
ssz, bts, err = msgp.ReadArrayHeaderBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if ssz != 4 {
|
||||
err = msgp.ArrayError{Wanted: 4, Got: ssz}
|
||||
return
|
||||
}
|
||||
}
|
||||
z.Tag, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
z.Time, bts, err = msgp.ReadInt64Bytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
z.Record, bts, err = msgp.ReadIntfBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
z.Option, bts, err = msgp.ReadIntfBytes(bts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
func (z *Message) Msgsize() (s int) {
|
||||
s = msgp.ArrayHeaderSize + msgp.StringPrefixSize + len(z.Tag) + msgp.Int64Size + msgp.GuessSize(z.Record) + msgp.GuessSize(z.Option)
|
||||
return
|
||||
}
|
3
vendor/src/github.com/fluent/fluent-logger-golang/fluent/version.go
vendored
Normal file
3
vendor/src/github.com/fluent/fluent-logger-golang/fluent/version.go
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
package fluent
|
||||
|
||||
const Version = "0.5.1"
|
311
vendor/src/github.com/philhofer/fwd/README.md
vendored
Normal file
311
vendor/src/github.com/philhofer/fwd/README.md
vendored
Normal file
|
@ -0,0 +1,311 @@
|
|||
|
||||
# fwd
|
||||
import "github.com/philhofer/fwd"
|
||||
|
||||
The `fwd` package provides a buffered reader
|
||||
and writer. Each has methods that help improve
|
||||
the encoding/decoding performance of some binary
|
||||
protocols.
|
||||
|
||||
The `fwd.Writer` and `fwd.Reader` type provide similar
|
||||
functionality to their counterparts in `bufio`, plus
|
||||
a few extra utility methods that simplify read-ahead
|
||||
and write-ahead. I wrote this package to improve serialization
|
||||
performance for <a href="http://github.com/philhofer/msgp">http://github.com/philhofer/msgp</a>,
|
||||
where it provided about a 2x speedup over `bufio`. However,
|
||||
care must be taken to understand the semantics of the
|
||||
extra methods provided by this package, as they allow
|
||||
the user to access and manipulate the buffer memory
|
||||
directly.
|
||||
|
||||
The extra methods for `fwd.Reader` are `Peek`, `Skip`
|
||||
and `Next`. `(*fwd.Reader).Peek`, unlike `(*bufio.Reader).Peek`,
|
||||
will re-allocate the read buffer in order to accommodate arbitrarily
|
||||
large read-ahead. `(*fwd.Reader).Skip` skips the next `n` bytes
|
||||
in the stream, and uses the `io.Seeker` interface if the underlying
|
||||
stream implements it. `(*fwd.Reader).Next` returns a slice pointing
|
||||
to the next `n` bytes in the read buffer (like `Peek`), but also
|
||||
increments the read position. This allows users to process streams
|
||||
in aribtrary block sizes without having to manage appropriately-sized
|
||||
slices. Additionally, obviating the need to copy the data from the
|
||||
buffer to another location in memory can improve performance dramatically
|
||||
in CPU-bound applications.
|
||||
|
||||
`fwd.Writer` only has one extra method, which is `(*fwd.Writer).Next`, which
|
||||
returns a slice pointing to the next `n` bytes of the writer, and increments
|
||||
the write position by the length of the returned slice. This allows users
|
||||
to write directly to the end of the buffer.
|
||||
|
||||
|
||||
|
||||
|
||||
## Constants
|
||||
``` go
|
||||
const (
|
||||
// DefaultReaderSize is the default size of the read buffer
|
||||
DefaultReaderSize = 2048
|
||||
)
|
||||
```
|
||||
``` go
|
||||
const (
|
||||
// DefaultWriterSize is the
|
||||
// default write buffer size.
|
||||
DefaultWriterSize = 2048
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
|
||||
## type Reader
|
||||
``` go
|
||||
type Reader struct {
|
||||
// contains filtered or unexported fields
|
||||
}
|
||||
```
|
||||
Reader is a buffered look-ahead reader
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### func NewReader
|
||||
``` go
|
||||
func NewReader(r io.Reader) *Reader
|
||||
```
|
||||
NewReader returns a new *Reader that reads from 'r'
|
||||
|
||||
|
||||
### func NewReaderSize
|
||||
``` go
|
||||
func NewReaderSize(r io.Reader, n int) *Reader
|
||||
```
|
||||
NewReaderSize returns a new *Reader that
|
||||
reads from 'r' and has a buffer size 'n'
|
||||
|
||||
|
||||
|
||||
|
||||
### func (\*Reader) BufferSize
|
||||
``` go
|
||||
func (r *Reader) BufferSize() int
|
||||
```
|
||||
BufferSize returns the total size of the buffer
|
||||
|
||||
|
||||
|
||||
### func (\*Reader) Buffered
|
||||
``` go
|
||||
func (r *Reader) Buffered() int
|
||||
```
|
||||
Buffered returns the number of bytes currently in the buffer
|
||||
|
||||
|
||||
|
||||
### func (\*Reader) Next
|
||||
``` go
|
||||
func (r *Reader) Next(n int) ([]byte, error)
|
||||
```
|
||||
Next returns the next 'n' bytes in the stream.
|
||||
If the returned slice has a length less than 'n',
|
||||
an error will also be returned.
|
||||
Unlike Peek, Next advances the reader position.
|
||||
The returned bytes point to the same
|
||||
data as the buffer, so the slice is
|
||||
only valid until the next reader method call.
|
||||
An EOF is considered an unexpected error.
|
||||
|
||||
|
||||
|
||||
### func (\*Reader) Peek
|
||||
``` go
|
||||
func (r *Reader) Peek(n int) ([]byte, error)
|
||||
```
|
||||
Peek returns the next 'n' buffered bytes,
|
||||
reading from the underlying reader if necessary.
|
||||
It will only return a slice shorter than 'n' bytes
|
||||
if it also returns an error. Peek does not advance
|
||||
the reader. EOF errors are *not* returned as
|
||||
io.ErrUnexpectedEOF.
|
||||
|
||||
|
||||
|
||||
### func (\*Reader) Read
|
||||
``` go
|
||||
func (r *Reader) Read(b []byte) (int, error)
|
||||
```
|
||||
Read implements `io.Reader`
|
||||
|
||||
|
||||
|
||||
### func (\*Reader) ReadByte
|
||||
``` go
|
||||
func (r *Reader) ReadByte() (byte, error)
|
||||
```
|
||||
ReadByte implements `io.ByteReader`
|
||||
|
||||
|
||||
|
||||
### func (\*Reader) ReadFull
|
||||
``` go
|
||||
func (r *Reader) ReadFull(b []byte) (int, error)
|
||||
```
|
||||
ReadFull attempts to read len(b) bytes into
|
||||
'b'. It returns the number of bytes read into
|
||||
'b', and an error if it does not return len(b).
|
||||
|
||||
|
||||
|
||||
### func (\*Reader) Reset
|
||||
``` go
|
||||
func (r *Reader) Reset(rd io.Reader)
|
||||
```
|
||||
Reset resets the underlying reader
|
||||
and the read buffer.
|
||||
|
||||
|
||||
|
||||
### func (\*Reader) Skip
|
||||
``` go
|
||||
func (r *Reader) Skip(n int) (int, error)
|
||||
```
|
||||
Skip moves the reader forward 'n' bytes.
|
||||
Returns the number of bytes skipped and any
|
||||
errors encountered. It is analagous to Seek(n, 1).
|
||||
If the underlying reader implements io.Seeker, then
|
||||
that method will be used to skip forward.
|
||||
|
||||
If the reader encounters
|
||||
an EOF before skipping 'n' bytes, it
|
||||
returns io.ErrUnexpectedEOF. If the
|
||||
underlying reader implements io.Seeker, then
|
||||
those rules apply instead. (Many implementations
|
||||
will not return `io.EOF` until the next call
|
||||
to Read.)
|
||||
|
||||
|
||||
|
||||
### func (\*Reader) WriteTo
|
||||
``` go
|
||||
func (r *Reader) WriteTo(w io.Writer) (int64, error)
|
||||
```
|
||||
WriteTo implements `io.WriterTo`
|
||||
|
||||
|
||||
|
||||
## type Writer
|
||||
``` go
|
||||
type Writer struct {
|
||||
// contains filtered or unexported fields
|
||||
}
|
||||
```
|
||||
Writer is a buffered writer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### func NewWriter
|
||||
``` go
|
||||
func NewWriter(w io.Writer) *Writer
|
||||
```
|
||||
NewWriter returns a new writer
|
||||
that writes to 'w' and has a buffer
|
||||
that is `DefaultWriterSize` bytes.
|
||||
|
||||
|
||||
### func NewWriterSize
|
||||
``` go
|
||||
func NewWriterSize(w io.Writer, size int) *Writer
|
||||
```
|
||||
NewWriterSize returns a new writer
|
||||
that writes to 'w' and has a buffer
|
||||
that is 'size' bytes.
|
||||
|
||||
|
||||
|
||||
|
||||
### func (\*Writer) BufferSize
|
||||
``` go
|
||||
func (w *Writer) BufferSize() int
|
||||
```
|
||||
BufferSize returns the maximum size of the buffer.
|
||||
|
||||
|
||||
|
||||
### func (\*Writer) Buffered
|
||||
``` go
|
||||
func (w *Writer) Buffered() int
|
||||
```
|
||||
Buffered returns the number of buffered bytes
|
||||
in the reader.
|
||||
|
||||
|
||||
|
||||
### func (\*Writer) Flush
|
||||
``` go
|
||||
func (w *Writer) Flush() error
|
||||
```
|
||||
Flush flushes any buffered bytes
|
||||
to the underlying writer.
|
||||
|
||||
|
||||
|
||||
### func (\*Writer) Next
|
||||
``` go
|
||||
func (w *Writer) Next(n int) ([]byte, error)
|
||||
```
|
||||
Next returns the next 'n' free bytes
|
||||
in the write buffer, flushing the writer
|
||||
as necessary. Next will return `io.ErrShortBuffer`
|
||||
if 'n' is greater than the size of the write buffer.
|
||||
|
||||
|
||||
|
||||
### func (\*Writer) ReadFrom
|
||||
``` go
|
||||
func (w *Writer) ReadFrom(r io.Reader) (int64, error)
|
||||
```
|
||||
ReadFrom implements `io.ReaderFrom`
|
||||
|
||||
|
||||
|
||||
### func (\*Writer) Write
|
||||
``` go
|
||||
func (w *Writer) Write(p []byte) (int, error)
|
||||
```
|
||||
Write implements `io.Writer`
|
||||
|
||||
|
||||
|
||||
### func (\*Writer) WriteByte
|
||||
``` go
|
||||
func (w *Writer) WriteByte(b byte) error
|
||||
```
|
||||
WriteByte implements `io.ByteWriter`
|
||||
|
||||
|
||||
|
||||
### func (\*Writer) WriteString
|
||||
``` go
|
||||
func (w *Writer) WriteString(s string) (int, error)
|
||||
```
|
||||
WriteString is analagous to Write, but it takes a string.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- - -
|
||||
Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md)
|
358
vendor/src/github.com/philhofer/fwd/reader.go
vendored
Normal file
358
vendor/src/github.com/philhofer/fwd/reader.go
vendored
Normal file
|
@ -0,0 +1,358 @@
|
|||
// The `fwd` package provides a buffered reader
|
||||
// and writer. Each has methods that help improve
|
||||
// the encoding/decoding performance of some binary
|
||||
// protocols.
|
||||
//
|
||||
// The `fwd.Writer` and `fwd.Reader` type provide similar
|
||||
// functionality to their counterparts in `bufio`, plus
|
||||
// a few extra utility methods that simplify read-ahead
|
||||
// and write-ahead. I wrote this package to improve serialization
|
||||
// performance for http://github.com/tinylib/msgp,
|
||||
// where it provided about a 2x speedup over `bufio` for certain
|
||||
// workloads. However, care must be taken to understand the semantics of the
|
||||
// extra methods provided by this package, as they allow
|
||||
// the user to access and manipulate the buffer memory
|
||||
// directly.
|
||||
//
|
||||
// The extra methods for `fwd.Reader` are `Peek`, `Skip`
|
||||
// and `Next`. `(*fwd.Reader).Peek`, unlike `(*bufio.Reader).Peek`,
|
||||
// will re-allocate the read buffer in order to accommodate arbitrarily
|
||||
// large read-ahead. `(*fwd.Reader).Skip` skips the next `n` bytes
|
||||
// in the stream, and uses the `io.Seeker` interface if the underlying
|
||||
// stream implements it. `(*fwd.Reader).Next` returns a slice pointing
|
||||
// to the next `n` bytes in the read buffer (like `Peek`), but also
|
||||
// increments the read position. This allows users to process streams
|
||||
// in aribtrary block sizes without having to manage appropriately-sized
|
||||
// slices. Additionally, obviating the need to copy the data from the
|
||||
// buffer to another location in memory can improve performance dramatically
|
||||
// in CPU-bound applications.
|
||||
//
|
||||
// `fwd.Writer` only has one extra method, which is `(*fwd.Writer).Next`, which
|
||||
// returns a slice pointing to the next `n` bytes of the writer, and increments
|
||||
// the write position by the length of the returned slice. This allows users
|
||||
// to write directly to the end of the buffer.
|
||||
//
|
||||
package fwd
|
||||
|
||||
import "io"
|
||||
|
||||
const (
|
||||
// DefaultReaderSize is the default size of the read buffer
|
||||
DefaultReaderSize = 2048
|
||||
|
||||
// minimum read buffer; straight from bufio
|
||||
minReaderSize = 16
|
||||
)
|
||||
|
||||
// NewReader returns a new *Reader that reads from 'r'
|
||||
func NewReader(r io.Reader) *Reader {
|
||||
return NewReaderSize(r, DefaultReaderSize)
|
||||
}
|
||||
|
||||
// NewReaderSize returns a new *Reader that
|
||||
// reads from 'r' and has a buffer size 'n'
|
||||
func NewReaderSize(r io.Reader, n int) *Reader {
|
||||
rd := &Reader{
|
||||
r: r,
|
||||
data: make([]byte, 0, max(minReaderSize, n)),
|
||||
}
|
||||
if s, ok := r.(io.Seeker); ok {
|
||||
rd.rs = s
|
||||
}
|
||||
return rd
|
||||
}
|
||||
|
||||
// Reader is a buffered look-ahead reader
|
||||
type Reader struct {
|
||||
r io.Reader // underlying reader
|
||||
|
||||
// data[n:len(data)] is buffered data; data[len(data):cap(data)] is free buffer space
|
||||
data []byte // data
|
||||
n int // read offset
|
||||
state error // last read error
|
||||
|
||||
// if the reader past to NewReader was
|
||||
// also an io.Seeker, this is non-nil
|
||||
rs io.Seeker
|
||||
}
|
||||
|
||||
// Reset resets the underlying reader
|
||||
// and the read buffer.
|
||||
func (r *Reader) Reset(rd io.Reader) {
|
||||
r.r = rd
|
||||
r.data = r.data[0:0]
|
||||
r.n = 0
|
||||
r.state = nil
|
||||
if s, ok := rd.(io.Seeker); ok {
|
||||
r.rs = s
|
||||
} else {
|
||||
r.rs = nil
|
||||
}
|
||||
}
|
||||
|
||||
// more() does one read on the underlying reader
|
||||
func (r *Reader) more() {
|
||||
// move data backwards so that
|
||||
// the read offset is 0; this way
|
||||
// we can supply the maximum number of
|
||||
// bytes to the reader
|
||||
if r.n != 0 {
|
||||
r.data = r.data[:copy(r.data[0:], r.data[r.n:])]
|
||||
r.n = 0
|
||||
}
|
||||
var a int
|
||||
a, r.state = r.r.Read(r.data[len(r.data):cap(r.data)])
|
||||
if a == 0 && r.state == nil {
|
||||
r.state = io.ErrNoProgress
|
||||
return
|
||||
}
|
||||
r.data = r.data[:len(r.data)+a]
|
||||
}
|
||||
|
||||
// pop error
|
||||
func (r *Reader) err() (e error) {
|
||||
e, r.state = r.state, nil
|
||||
return
|
||||
}
|
||||
|
||||
// pop error; EOF -> io.ErrUnexpectedEOF
|
||||
func (r *Reader) noEOF() (e error) {
|
||||
e, r.state = r.state, nil
|
||||
if e == io.EOF {
|
||||
e = io.ErrUnexpectedEOF
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// buffered bytes
|
||||
func (r *Reader) buffered() int { return len(r.data) - r.n }
|
||||
|
||||
// Buffered returns the number of bytes currently in the buffer
|
||||
func (r *Reader) Buffered() int { return len(r.data) - r.n }
|
||||
|
||||
// BufferSize returns the total size of the buffer
|
||||
func (r *Reader) BufferSize() int { return cap(r.data) }
|
||||
|
||||
// Peek returns the next 'n' buffered bytes,
|
||||
// reading from the underlying reader if necessary.
|
||||
// It will only return a slice shorter than 'n' bytes
|
||||
// if it also returns an error. Peek does not advance
|
||||
// the reader. EOF errors are *not* returned as
|
||||
// io.ErrUnexpectedEOF.
|
||||
func (r *Reader) Peek(n int) ([]byte, error) {
|
||||
// in the degenerate case,
|
||||
// we may need to realloc
|
||||
// (the caller asked for more
|
||||
// bytes than the size of the buffer)
|
||||
if cap(r.data) < n {
|
||||
old := r.data[r.n:]
|
||||
r.data = make([]byte, n+r.buffered())
|
||||
r.data = r.data[:copy(r.data, old)]
|
||||
}
|
||||
|
||||
// keep filling until
|
||||
// we hit an error or
|
||||
// read enough bytes
|
||||
for r.buffered() < n && r.state == nil {
|
||||
r.more()
|
||||
}
|
||||
|
||||
// we must have hit an error
|
||||
if r.buffered() < n {
|
||||
return r.data[r.n:], r.err()
|
||||
}
|
||||
|
||||
return r.data[r.n : r.n+n], nil
|
||||
}
|
||||
|
||||
// Skip moves the reader forward 'n' bytes.
|
||||
// Returns the number of bytes skipped and any
|
||||
// errors encountered. It is analagous to Seek(n, 1).
|
||||
// If the underlying reader implements io.Seeker, then
|
||||
// that method will be used to skip forward.
|
||||
//
|
||||
// If the reader encounters
|
||||
// an EOF before skipping 'n' bytes, it
|
||||
// returns io.ErrUnexpectedEOF. If the
|
||||
// underlying reader implements io.Seeker, then
|
||||
// those rules apply instead. (Many implementations
|
||||
// will not return `io.EOF` until the next call
|
||||
// to Read.)
|
||||
func (r *Reader) Skip(n int) (int, error) {
|
||||
|
||||
// fast path
|
||||
if r.buffered() >= n {
|
||||
r.n += n
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// use seeker implementation
|
||||
// if we can
|
||||
if r.rs != nil {
|
||||
return r.skipSeek(n)
|
||||
}
|
||||
|
||||
// loop on filling
|
||||
// and then erasing
|
||||
o := n
|
||||
for r.buffered() < n && r.state == nil {
|
||||
r.more()
|
||||
// we can skip forward
|
||||
// up to r.buffered() bytes
|
||||
step := min(r.buffered(), n)
|
||||
r.n += step
|
||||
n -= step
|
||||
}
|
||||
// at this point, n should be
|
||||
// 0 if everything went smoothly
|
||||
return o - n, r.noEOF()
|
||||
}
|
||||
|
||||
// Next returns the next 'n' bytes in the stream.
|
||||
// Unlike Peek, Next advances the reader position.
|
||||
// The returned bytes point to the same
|
||||
// data as the buffer, so the slice is
|
||||
// only valid until the next reader method call.
|
||||
// An EOF is considered an unexpected error.
|
||||
// If an the returned slice is less than the
|
||||
// length asked for, an error will be returned,
|
||||
// and the reader position will not be incremented.
|
||||
func (r *Reader) Next(n int) ([]byte, error) {
|
||||
|
||||
// in case the buffer is too small
|
||||
if cap(r.data) < n {
|
||||
old := r.data[r.n:]
|
||||
r.data = make([]byte, n+r.buffered())
|
||||
r.data = r.data[:copy(r.data, old)]
|
||||
}
|
||||
|
||||
// fill at least 'n' bytes
|
||||
for r.buffered() < n && r.state == nil {
|
||||
r.more()
|
||||
}
|
||||
|
||||
if r.buffered() < n {
|
||||
return r.data[r.n:], r.noEOF()
|
||||
}
|
||||
out := r.data[r.n : r.n+n]
|
||||
r.n += n
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// skipSeek uses the io.Seeker to seek forward.
|
||||
// only call this function when n > r.buffered()
|
||||
func (r *Reader) skipSeek(n int) (int, error) {
|
||||
o := r.buffered()
|
||||
// first, clear buffer
|
||||
n -= o
|
||||
r.n = 0
|
||||
r.data = r.data[:0]
|
||||
|
||||
// then seek forward remaning bytes
|
||||
i, err := r.rs.Seek(int64(n), 1)
|
||||
return int(i) + o, err
|
||||
}
|
||||
|
||||
// Read implements `io.Reader`
|
||||
func (r *Reader) Read(b []byte) (int, error) {
|
||||
if len(b) <= r.buffered() {
|
||||
x := copy(b, r.data[r.n:])
|
||||
r.n += x
|
||||
return x, nil
|
||||
}
|
||||
r.more()
|
||||
if r.buffered() > 0 {
|
||||
x := copy(b, r.data[r.n:])
|
||||
r.n += x
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// io.Reader is supposed to return
|
||||
// 0 read bytes on error
|
||||
return 0, r.err()
|
||||
}
|
||||
|
||||
// ReadFull attempts to read len(b) bytes into
|
||||
// 'b'. It returns the number of bytes read into
|
||||
// 'b', and an error if it does not return len(b).
|
||||
// EOF is considered an unexpected error.
|
||||
func (r *Reader) ReadFull(b []byte) (int, error) {
|
||||
var x int
|
||||
l := len(b)
|
||||
for x < l {
|
||||
if r.buffered() == 0 {
|
||||
r.more()
|
||||
}
|
||||
c := copy(b[x:], r.data[r.n:])
|
||||
x += c
|
||||
r.n += c
|
||||
if r.state != nil {
|
||||
return x, r.noEOF()
|
||||
}
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// ReadByte implements `io.ByteReader`
|
||||
func (r *Reader) ReadByte() (byte, error) {
|
||||
for r.buffered() < 1 && r.state == nil {
|
||||
r.more()
|
||||
}
|
||||
if r.buffered() < 1 {
|
||||
return 0, r.err()
|
||||
}
|
||||
b := r.data[r.n]
|
||||
r.n++
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// WriteTo implements `io.WriterTo`
|
||||
func (r *Reader) WriteTo(w io.Writer) (int64, error) {
|
||||
var (
|
||||
i int64
|
||||
ii int
|
||||
err error
|
||||
)
|
||||
// first, clear buffer
|
||||
if r.buffered() > 0 {
|
||||
ii, err = w.Write(r.data[r.n:])
|
||||
i += int64(ii)
|
||||
if err != nil {
|
||||
return i, err
|
||||
}
|
||||
r.data = r.data[0:0]
|
||||
r.n = 0
|
||||
}
|
||||
for r.state == nil {
|
||||
// here we just do
|
||||
// 1:1 reads and writes
|
||||
r.more()
|
||||
if r.buffered() > 0 {
|
||||
ii, err = w.Write(r.data)
|
||||
i += int64(ii)
|
||||
if err != nil {
|
||||
return i, err
|
||||
}
|
||||
r.data = r.data[0:0]
|
||||
r.n = 0
|
||||
}
|
||||
}
|
||||
if r.state != io.EOF {
|
||||
return i, r.err()
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func min(a int, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func max(a int, b int) int {
|
||||
if a < b {
|
||||
return b
|
||||
}
|
||||
return a
|
||||
}
|
224
vendor/src/github.com/philhofer/fwd/writer.go
vendored
Normal file
224
vendor/src/github.com/philhofer/fwd/writer.go
vendored
Normal file
|
@ -0,0 +1,224 @@
|
|||
package fwd
|
||||
|
||||
import "io"
|
||||
|
||||
const (
|
||||
// DefaultWriterSize is the
|
||||
// default write buffer size.
|
||||
DefaultWriterSize = 2048
|
||||
|
||||
minWriterSize = minReaderSize
|
||||
)
|
||||
|
||||
// Writer is a buffered writer
|
||||
type Writer struct {
|
||||
w io.Writer // writer
|
||||
buf []byte // 0:len(buf) is bufered data
|
||||
}
|
||||
|
||||
// NewWriter returns a new writer
|
||||
// that writes to 'w' and has a buffer
|
||||
// that is `DefaultWriterSize` bytes.
|
||||
func NewWriter(w io.Writer) *Writer {
|
||||
if wr, ok := w.(*Writer); ok {
|
||||
return wr
|
||||
}
|
||||
return &Writer{
|
||||
w: w,
|
||||
buf: make([]byte, 0, DefaultWriterSize),
|
||||
}
|
||||
}
|
||||
|
||||
// NewWriterSize returns a new writer
|
||||
// that writes to 'w' and has a buffer
|
||||
// that is 'size' bytes.
|
||||
func NewWriterSize(w io.Writer, size int) *Writer {
|
||||
if wr, ok := w.(*Writer); ok && cap(wr.buf) >= size {
|
||||
return wr
|
||||
}
|
||||
return &Writer{
|
||||
w: w,
|
||||
buf: make([]byte, 0, max(size, minWriterSize)),
|
||||
}
|
||||
}
|
||||
|
||||
// Buffered returns the number of buffered bytes
|
||||
// in the reader.
|
||||
func (w *Writer) Buffered() int { return len(w.buf) }
|
||||
|
||||
// BufferSize returns the maximum size of the buffer.
|
||||
func (w *Writer) BufferSize() int { return cap(w.buf) }
|
||||
|
||||
// Flush flushes any buffered bytes
|
||||
// to the underlying writer.
|
||||
func (w *Writer) Flush() error {
|
||||
l := len(w.buf)
|
||||
if l > 0 {
|
||||
n, err := w.w.Write(w.buf)
|
||||
|
||||
// if we didn't write the whole
|
||||
// thing, copy the unwritten
|
||||
// bytes to the beginnning of the
|
||||
// buffer.
|
||||
if n < l && n > 0 {
|
||||
w.pushback(n)
|
||||
if err == nil {
|
||||
err = io.ErrShortWrite
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
w.buf = w.buf[:0]
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Write implements `io.Writer`
|
||||
func (w *Writer) Write(p []byte) (int, error) {
|
||||
c, l, ln := cap(w.buf), len(w.buf), len(p)
|
||||
avail := c - l
|
||||
|
||||
// requires flush
|
||||
if avail < ln {
|
||||
if err := w.Flush(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
l = len(w.buf)
|
||||
}
|
||||
// too big to fit in buffer;
|
||||
// write directly to w.w
|
||||
if c < ln {
|
||||
return w.w.Write(p)
|
||||
}
|
||||
|
||||
// grow buf slice; copy; return
|
||||
w.buf = w.buf[:l+ln]
|
||||
return copy(w.buf[l:], p), nil
|
||||
}
|
||||
|
||||
// WriteString is analagous to Write, but it takes a string.
|
||||
func (w *Writer) WriteString(s string) (int, error) {
|
||||
c, l, ln := cap(w.buf), len(w.buf), len(s)
|
||||
avail := c - l
|
||||
|
||||
// requires flush
|
||||
if avail < ln {
|
||||
if err := w.Flush(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
l = len(w.buf)
|
||||
}
|
||||
// too big to fit in buffer;
|
||||
// write directly to w.w
|
||||
//
|
||||
// yes, this is unsafe. *but*
|
||||
// io.Writer is not allowed
|
||||
// to mutate its input or
|
||||
// maintain a reference to it,
|
||||
// per the spec in package io.
|
||||
//
|
||||
// plus, if the string is really
|
||||
// too big to fit in the buffer, then
|
||||
// creating a copy to write it is
|
||||
// expensive (and, strictly speaking,
|
||||
// unnecessary)
|
||||
if c < ln {
|
||||
return w.w.Write(unsafestr(s))
|
||||
}
|
||||
|
||||
// grow buf slice; copy; return
|
||||
w.buf = w.buf[:l+ln]
|
||||
return copy(w.buf[l:], s), nil
|
||||
}
|
||||
|
||||
// WriteByte implements `io.ByteWriter`
|
||||
func (w *Writer) WriteByte(b byte) error {
|
||||
if len(w.buf) == cap(w.buf) {
|
||||
if err := w.Flush(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
w.buf = append(w.buf, b)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Next returns the next 'n' free bytes
|
||||
// in the write buffer, flushing the writer
|
||||
// as necessary. Next will return `io.ErrShortBuffer`
|
||||
// if 'n' is greater than the size of the write buffer.
|
||||
// Calls to 'next' increment the write position by
|
||||
// the size of the returned buffer.
|
||||
func (w *Writer) Next(n int) ([]byte, error) {
|
||||
c, l := cap(w.buf), len(w.buf)
|
||||
if n > c {
|
||||
return nil, io.ErrShortBuffer
|
||||
}
|
||||
avail := c - l
|
||||
if avail < n {
|
||||
if err := w.Flush(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
l = len(w.buf)
|
||||
}
|
||||
w.buf = w.buf[:l+n]
|
||||
return w.buf[l:], nil
|
||||
}
|
||||
|
||||
// take the bytes from w.buf[n:len(w.buf)]
|
||||
// and put them at the beginning of w.buf,
|
||||
// and resize to the length of the copied segment.
|
||||
func (w *Writer) pushback(n int) {
|
||||
w.buf = w.buf[:copy(w.buf, w.buf[n:])]
|
||||
}
|
||||
|
||||
// ReadFrom implements `io.ReaderFrom`
|
||||
func (w *Writer) ReadFrom(r io.Reader) (int64, error) {
|
||||
// anticipatory flush
|
||||
if err := w.Flush(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
w.buf = w.buf[0:cap(w.buf)] // expand buffer
|
||||
|
||||
var nn int64 // written
|
||||
var err error // error
|
||||
var x int // read
|
||||
|
||||
// 1:1 reads and writes
|
||||
for err == nil {
|
||||
x, err = r.Read(w.buf)
|
||||
if x > 0 {
|
||||
n, werr := w.w.Write(w.buf[:x])
|
||||
nn += int64(n)
|
||||
|
||||
if err != nil {
|
||||
if n < x && n > 0 {
|
||||
w.pushback(n - x)
|
||||
}
|
||||
return nn, werr
|
||||
}
|
||||
if n < x {
|
||||
w.pushback(n - x)
|
||||
return nn, io.ErrShortWrite
|
||||
}
|
||||
} else if err == nil {
|
||||
err = io.ErrNoProgress
|
||||
break
|
||||
}
|
||||
}
|
||||
if err != io.EOF {
|
||||
return nn, err
|
||||
}
|
||||
|
||||
// we only clear here
|
||||
// because we are sure
|
||||
// the writes have
|
||||
// suceeded. otherwise,
|
||||
// we retain the data in case
|
||||
// future writes succeed.
|
||||
w.buf = w.buf[0:0]
|
||||
|
||||
return nn, nil
|
||||
}
|
5
vendor/src/github.com/philhofer/fwd/writer_appengine.go
vendored
Normal file
5
vendor/src/github.com/philhofer/fwd/writer_appengine.go
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
// +build appengine
|
||||
|
||||
package fwd
|
||||
|
||||
func unsafestr(s string) []byte { return []byte(s) }
|
18
vendor/src/github.com/philhofer/fwd/writer_unsafe.go
vendored
Normal file
18
vendor/src/github.com/philhofer/fwd/writer_unsafe.go
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
// +build !appengine
|
||||
|
||||
package fwd
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// unsafe cast string as []byte
|
||||
func unsafestr(b string) []byte {
|
||||
l := len(b)
|
||||
return *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
|
||||
Len: l,
|
||||
Cap: l,
|
||||
Data: (*reflect.StringHeader)(unsafe.Pointer(&b)).Data,
|
||||
}))
|
||||
}
|
38
vendor/src/github.com/tinylib/msgp/msgp/circular.go
vendored
Normal file
38
vendor/src/github.com/tinylib/msgp/msgp/circular.go
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
package msgp
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// EndlessReader is an io.Reader
|
||||
// that loops over the same data
|
||||
// endlessly. It is used for benchmarking.
|
||||
type EndlessReader struct {
|
||||
tb *testing.B
|
||||
data []byte
|
||||
offset int
|
||||
}
|
||||
|
||||
// NewEndlessReader returns a new endless reader
|
||||
func NewEndlessReader(b []byte, tb *testing.B) *EndlessReader {
|
||||
return &EndlessReader{tb: tb, data: b, offset: 0}
|
||||
}
|
||||
|
||||
// Read implements io.Reader. In practice, it
|
||||
// always returns (len(p), nil), although it
|
||||
// fills the supplied slice while the benchmark
|
||||
// timer is stopped.
|
||||
func (c *EndlessReader) Read(p []byte) (int, error) {
|
||||
c.tb.StopTimer()
|
||||
var n int
|
||||
l := len(p)
|
||||
m := len(c.data)
|
||||
for n < l {
|
||||
nn := copy(p[n:], c.data[c.offset:])
|
||||
n += nn
|
||||
c.offset += nn
|
||||
c.offset %= m
|
||||
}
|
||||
c.tb.StartTimer()
|
||||
return n, nil
|
||||
}
|
142
vendor/src/github.com/tinylib/msgp/msgp/defs.go
vendored
Normal file
142
vendor/src/github.com/tinylib/msgp/msgp/defs.go
vendored
Normal file
|
@ -0,0 +1,142 @@
|
|||
// This package is the support library for the msgp code generator (http://github.com/tinylib/msgp).
|
||||
//
|
||||
// This package defines the utilites used by the msgp code generator for encoding and decoding MessagePack
|
||||
// from []byte and io.Reader/io.Writer types. Much of this package is devoted to helping the msgp code
|
||||
// generator implement the Marshaler/Unmarshaler and Encodable/Decodable interfaces.
|
||||
//
|
||||
// This package defines four "families" of functions:
|
||||
// - AppendXxxx() appends an object to a []byte in MessagePack encoding.
|
||||
// - ReadXxxxBytes() reads an object from a []byte and returns the remaining bytes.
|
||||
// - (*Writer).WriteXxxx() writes an object to the buffered *Writer type.
|
||||
// - (*Reader).ReadXxxx() reads an object from a buffered *Reader type.
|
||||
//
|
||||
// Once a type has satisfied the `Encodable` and `Decodable` interfaces,
|
||||
// it can be written and read from arbitrary `io.Writer`s and `io.Reader`s using
|
||||
// msgp.Encode(io.Writer, msgp.Encodable)
|
||||
// and
|
||||
// msgp.Decode(io.Reader, msgp.Decodable)
|
||||
//
|
||||
// There are also methods for converting MessagePack to JSON without
|
||||
// an explicit de-serialization step.
|
||||
//
|
||||
// For additional tips, tricks, and gotchas, please visit
|
||||
// the wiki at http://github.com/tinylib/msgp
|
||||
package msgp
|
||||
|
||||
const last4 = 0x0f
|
||||
const first4 = 0xf0
|
||||
const last5 = 0x1f
|
||||
const first3 = 0xe0
|
||||
const last7 = 0x7f
|
||||
|
||||
func isfixint(b byte) bool {
|
||||
return b>>7 == 0
|
||||
}
|
||||
|
||||
func isnfixint(b byte) bool {
|
||||
return b&first3 == mnfixint
|
||||
}
|
||||
|
||||
func isfixmap(b byte) bool {
|
||||
return b&first4 == mfixmap
|
||||
}
|
||||
|
||||
func isfixarray(b byte) bool {
|
||||
return b&first4 == mfixarray
|
||||
}
|
||||
|
||||
func isfixstr(b byte) bool {
|
||||
return b&first3 == mfixstr
|
||||
}
|
||||
|
||||
func wfixint(u uint8) byte {
|
||||
return u & last7
|
||||
}
|
||||
|
||||
func rfixint(b byte) uint8 {
|
||||
return b
|
||||
}
|
||||
|
||||
func wnfixint(i int8) byte {
|
||||
return byte(i) | mnfixint
|
||||
}
|
||||
|
||||
func rnfixint(b byte) int8 {
|
||||
return int8(b)
|
||||
}
|
||||
|
||||
func rfixmap(b byte) uint8 {
|
||||
return b & last4
|
||||
}
|
||||
|
||||
func wfixmap(u uint8) byte {
|
||||
return mfixmap | (u & last4)
|
||||
}
|
||||
|
||||
func rfixstr(b byte) uint8 {
|
||||
return b & last5
|
||||
}
|
||||
|
||||
func wfixstr(u uint8) byte {
|
||||
return (u & last5) | mfixstr
|
||||
}
|
||||
|
||||
func rfixarray(b byte) uint8 {
|
||||
return (b & last4)
|
||||
}
|
||||
|
||||
func wfixarray(u uint8) byte {
|
||||
return (u & last4) | mfixarray
|
||||
}
|
||||
|
||||
// These are all the byte
|
||||
// prefixes defined by the
|
||||
// msgpack standard
|
||||
const (
|
||||
// 0XXXXXXX
|
||||
mfixint uint8 = 0x00
|
||||
|
||||
// 111XXXXX
|
||||
mnfixint uint8 = 0xe0
|
||||
|
||||
// 1000XXXX
|
||||
mfixmap uint8 = 0x80
|
||||
|
||||
// 1001XXXX
|
||||
mfixarray uint8 = 0x90
|
||||
|
||||
// 101XXXXX
|
||||
mfixstr uint8 = 0xa0
|
||||
|
||||
mnil uint8 = 0xc0
|
||||
mfalse uint8 = 0xc2
|
||||
mtrue uint8 = 0xc3
|
||||
mbin8 uint8 = 0xc4
|
||||
mbin16 uint8 = 0xc5
|
||||
mbin32 uint8 = 0xc6
|
||||
mext8 uint8 = 0xc7
|
||||
mext16 uint8 = 0xc8
|
||||
mext32 uint8 = 0xc9
|
||||
mfloat32 uint8 = 0xca
|
||||
mfloat64 uint8 = 0xcb
|
||||
muint8 uint8 = 0xcc
|
||||
muint16 uint8 = 0xcd
|
||||
muint32 uint8 = 0xce
|
||||
muint64 uint8 = 0xcf
|
||||
mint8 uint8 = 0xd0
|
||||
mint16 uint8 = 0xd1
|
||||
mint32 uint8 = 0xd2
|
||||
mint64 uint8 = 0xd3
|
||||
mfixext1 uint8 = 0xd4
|
||||
mfixext2 uint8 = 0xd5
|
||||
mfixext4 uint8 = 0xd6
|
||||
mfixext8 uint8 = 0xd7
|
||||
mfixext16 uint8 = 0xd8
|
||||
mstr8 uint8 = 0xd9
|
||||
mstr16 uint8 = 0xda
|
||||
mstr32 uint8 = 0xdb
|
||||
marray16 uint8 = 0xdc
|
||||
marray32 uint8 = 0xdd
|
||||
mmap16 uint8 = 0xde
|
||||
mmap32 uint8 = 0xdf
|
||||
)
|
241
vendor/src/github.com/tinylib/msgp/msgp/edit.go
vendored
Normal file
241
vendor/src/github.com/tinylib/msgp/msgp/edit.go
vendored
Normal file
|
@ -0,0 +1,241 @@
|
|||
package msgp
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
// Locate returns a []byte pointing to the field
|
||||
// in a messagepack map with the provided key. (The returned []byte
|
||||
// points to a sub-slice of 'raw'; Locate does no allocations.) If the
|
||||
// key doesn't exist in the map, a zero-length []byte will be returned.
|
||||
func Locate(key string, raw []byte) []byte {
|
||||
s, n := locate(raw, key)
|
||||
return raw[s:n]
|
||||
}
|
||||
|
||||
// Replace takes a key ("key") in a messagepack map ("raw")
|
||||
// and replaces its value with the one provided and returns
|
||||
// the new []byte. The returned []byte may point to the same
|
||||
// memory as "raw". Replace makes no effort to evaluate the validity
|
||||
// of the contents of 'val'. It may use up to the full capacity of 'raw.'
|
||||
// Replace returns 'nil' if the field doesn't exist or if the object in 'raw'
|
||||
// is not a map.
|
||||
func Replace(key string, raw []byte, val []byte) []byte {
|
||||
start, end := locate(raw, key)
|
||||
if start == end {
|
||||
return nil
|
||||
}
|
||||
return replace(raw, start, end, val, true)
|
||||
}
|
||||
|
||||
// CopyReplace works similarly to Replace except that the returned
|
||||
// byte slice does not point to the same memory as 'raw'. CopyReplace
|
||||
// returns 'nil' if the field doesn't exist or 'raw' isn't a map.
|
||||
func CopyReplace(key string, raw []byte, val []byte) []byte {
|
||||
start, end := locate(raw, key)
|
||||
if start == end {
|
||||
return nil
|
||||
}
|
||||
return replace(raw, start, end, val, false)
|
||||
}
|
||||
|
||||
// Remove removes a key-value pair from 'raw'. It returns
|
||||
// 'raw' unchanged if the key didn't exist.
|
||||
func Remove(key string, raw []byte) []byte {
|
||||
start, end := locateKV(raw, key)
|
||||
if start == end {
|
||||
return raw
|
||||
}
|
||||
raw = raw[:start+copy(raw[start:], raw[end:])]
|
||||
return resizeMap(raw, -1)
|
||||
}
|
||||
|
||||
// HasKey returns whether the map in 'raw' has
|
||||
// a field with key 'key'
|
||||
func HasKey(key string, raw []byte) bool {
|
||||
sz, bts, err := ReadMapHeaderBytes(raw)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
var field []byte
|
||||
for i := uint32(0); i < sz; i++ {
|
||||
field, bts, err = ReadStringZC(bts)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if UnsafeString(field) == key {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func replace(raw []byte, start int, end int, val []byte, inplace bool) []byte {
|
||||
ll := end - start // length of segment to replace
|
||||
lv := len(val)
|
||||
|
||||
if inplace {
|
||||
extra := lv - ll
|
||||
|
||||
// fastest case: we're doing
|
||||
// a 1:1 replacement
|
||||
if extra == 0 {
|
||||
copy(raw[start:], val)
|
||||
return raw
|
||||
|
||||
} else if extra < 0 {
|
||||
// 'val' smaller than replaced value
|
||||
// copy in place and shift back
|
||||
|
||||
x := copy(raw[start:], val)
|
||||
y := copy(raw[start+x:], raw[end:])
|
||||
return raw[:start+x+y]
|
||||
|
||||
} else if extra < cap(raw)-len(raw) {
|
||||
// 'val' less than (cap-len) extra bytes
|
||||
// copy in place and shift forward
|
||||
raw = raw[0 : len(raw)+extra]
|
||||
// shift end forward
|
||||
copy(raw[end+extra:], raw[end:])
|
||||
copy(raw[start:], val)
|
||||
return raw
|
||||
}
|
||||
}
|
||||
|
||||
// we have to allocate new space
|
||||
out := make([]byte, len(raw)+len(val)-ll)
|
||||
x := copy(out, raw[:start])
|
||||
y := copy(out[x:], val)
|
||||
copy(out[x+y:], raw[end:])
|
||||
return out
|
||||
}
|
||||
|
||||
// locate does a naive O(n) search for the map key; returns start, end
|
||||
// (returns 0,0 on error)
|
||||
func locate(raw []byte, key string) (start int, end int) {
|
||||
var (
|
||||
sz uint32
|
||||
bts []byte
|
||||
field []byte
|
||||
err error
|
||||
)
|
||||
sz, bts, err = ReadMapHeaderBytes(raw)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// loop and locate field
|
||||
for i := uint32(0); i < sz; i++ {
|
||||
field, bts, err = ReadStringZC(bts)
|
||||
if err != nil {
|
||||
return 0, 0
|
||||
}
|
||||
if UnsafeString(field) == key {
|
||||
// start location
|
||||
l := len(raw)
|
||||
start = l - len(bts)
|
||||
bts, err = Skip(bts)
|
||||
if err != nil {
|
||||
return 0, 0
|
||||
}
|
||||
end = l - len(bts)
|
||||
return
|
||||
}
|
||||
bts, err = Skip(bts)
|
||||
if err != nil {
|
||||
return 0, 0
|
||||
}
|
||||
}
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
// locate key AND value
|
||||
func locateKV(raw []byte, key string) (start int, end int) {
|
||||
var (
|
||||
sz uint32
|
||||
bts []byte
|
||||
field []byte
|
||||
err error
|
||||
)
|
||||
sz, bts, err = ReadMapHeaderBytes(raw)
|
||||
if err != nil {
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
for i := uint32(0); i < sz; i++ {
|
||||
tmp := len(bts)
|
||||
field, bts, err = ReadStringZC(bts)
|
||||
if err != nil {
|
||||
return 0, 0
|
||||
}
|
||||
if UnsafeString(field) == key {
|
||||
start = len(raw) - tmp
|
||||
bts, err = Skip(bts)
|
||||
if err != nil {
|
||||
return 0, 0
|
||||
}
|
||||
end = len(raw) - len(bts)
|
||||
return
|
||||
}
|
||||
bts, err = Skip(bts)
|
||||
if err != nil {
|
||||
return 0, 0
|
||||
}
|
||||
}
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
// delta is delta on map size
|
||||
func resizeMap(raw []byte, delta int64) []byte {
|
||||
var sz int64
|
||||
switch raw[0] {
|
||||
case mmap16:
|
||||
sz = int64(big.Uint16(raw[1:]))
|
||||
if sz+delta <= math.MaxUint16 {
|
||||
big.PutUint16(raw[1:], uint16(sz+delta))
|
||||
return raw
|
||||
}
|
||||
if cap(raw)-len(raw) >= 2 {
|
||||
raw = raw[0 : len(raw)+2]
|
||||
copy(raw[5:], raw[3:])
|
||||
big.PutUint32(raw[1:], uint32(sz+delta))
|
||||
return raw
|
||||
}
|
||||
n := make([]byte, 0, len(raw)+5)
|
||||
n = AppendMapHeader(n, uint32(sz+delta))
|
||||
return append(n, raw[3:]...)
|
||||
|
||||
case mmap32:
|
||||
sz = int64(big.Uint32(raw[1:]))
|
||||
big.PutUint32(raw[1:], uint32(sz+delta))
|
||||
return raw
|
||||
|
||||
default:
|
||||
sz = int64(rfixmap(raw[0]))
|
||||
if sz+delta < 16 {
|
||||
raw[0] = wfixmap(uint8(sz + delta))
|
||||
return raw
|
||||
} else if sz+delta <= math.MaxUint16 {
|
||||
if cap(raw)-len(raw) >= 2 {
|
||||
raw = raw[0 : len(raw)+2]
|
||||
copy(raw[3:], raw[1:])
|
||||
raw[0] = mmap16
|
||||
big.PutUint16(raw[1:], uint16(sz+delta))
|
||||
return raw
|
||||
}
|
||||
n := make([]byte, 0, len(raw)+5)
|
||||
n = AppendMapHeader(n, uint32(sz+delta))
|
||||
return append(n, raw[1:]...)
|
||||
}
|
||||
if cap(raw)-len(raw) >= 4 {
|
||||
raw = raw[0 : len(raw)+4]
|
||||
copy(raw[5:], raw[1:])
|
||||
raw[0] = mmap32
|
||||
big.PutUint32(raw[1:], uint32(sz+delta))
|
||||
return raw
|
||||
}
|
||||
n := make([]byte, 0, len(raw)+5)
|
||||
n = AppendMapHeader(n, uint32(sz+delta))
|
||||
return append(n, raw[1:]...)
|
||||
}
|
||||
}
|
99
vendor/src/github.com/tinylib/msgp/msgp/elsize.go
vendored
Normal file
99
vendor/src/github.com/tinylib/msgp/msgp/elsize.go
vendored
Normal file
|
@ -0,0 +1,99 @@
|
|||
package msgp
|
||||
|
||||
// size of every object on the wire,
|
||||
// plus type information. gives us
|
||||
// constant-time type information
|
||||
// for traversing composite objects.
|
||||
//
|
||||
var sizes = [256]bytespec{
|
||||
mnil: {size: 1, extra: constsize, typ: NilType},
|
||||
mfalse: {size: 1, extra: constsize, typ: BoolType},
|
||||
mtrue: {size: 1, extra: constsize, typ: BoolType},
|
||||
mbin8: {size: 2, extra: extra8, typ: BinType},
|
||||
mbin16: {size: 3, extra: extra16, typ: BinType},
|
||||
mbin32: {size: 5, extra: extra32, typ: BinType},
|
||||
mext8: {size: 3, extra: extra8, typ: ExtensionType},
|
||||
mext16: {size: 4, extra: extra16, typ: ExtensionType},
|
||||
mext32: {size: 6, extra: extra32, typ: ExtensionType},
|
||||
mfloat32: {size: 5, extra: constsize, typ: Float32Type},
|
||||
mfloat64: {size: 9, extra: constsize, typ: Float64Type},
|
||||
muint8: {size: 2, extra: constsize, typ: UintType},
|
||||
muint16: {size: 3, extra: constsize, typ: UintType},
|
||||
muint32: {size: 5, extra: constsize, typ: UintType},
|
||||
muint64: {size: 9, extra: constsize, typ: UintType},
|
||||
mint8: {size: 2, extra: constsize, typ: IntType},
|
||||
mint16: {size: 3, extra: constsize, typ: IntType},
|
||||
mint32: {size: 5, extra: constsize, typ: IntType},
|
||||
mint64: {size: 9, extra: constsize, typ: IntType},
|
||||
mfixext1: {size: 3, extra: constsize, typ: ExtensionType},
|
||||
mfixext2: {size: 4, extra: constsize, typ: ExtensionType},
|
||||
mfixext4: {size: 6, extra: constsize, typ: ExtensionType},
|
||||
mfixext8: {size: 10, extra: constsize, typ: ExtensionType},
|
||||
mfixext16: {size: 18, extra: constsize, typ: ExtensionType},
|
||||
mstr8: {size: 2, extra: extra8, typ: StrType},
|
||||
mstr16: {size: 3, extra: extra16, typ: StrType},
|
||||
mstr32: {size: 5, extra: extra32, typ: StrType},
|
||||
marray16: {size: 3, extra: array16v, typ: ArrayType},
|
||||
marray32: {size: 5, extra: array32v, typ: ArrayType},
|
||||
mmap16: {size: 3, extra: map16v, typ: MapType},
|
||||
mmap32: {size: 5, extra: map32v, typ: MapType},
|
||||
}
|
||||
|
||||
func init() {
|
||||
// set up fixed fields
|
||||
|
||||
// fixint
|
||||
for i := mfixint; i < 0x80; i++ {
|
||||
sizes[i] = bytespec{size: 1, extra: constsize, typ: IntType}
|
||||
}
|
||||
|
||||
// nfixint
|
||||
for i := uint16(mnfixint); i < 0x100; i++ {
|
||||
sizes[uint8(i)] = bytespec{size: 1, extra: constsize, typ: IntType}
|
||||
}
|
||||
|
||||
// fixstr gets constsize,
|
||||
// since the prefix yields the size
|
||||
for i := mfixstr; i < 0xc0; i++ {
|
||||
sizes[i] = bytespec{size: 1 + rfixstr(i), extra: constsize, typ: StrType}
|
||||
}
|
||||
|
||||
// fixmap
|
||||
for i := mfixmap; i < 0x90; i++ {
|
||||
sizes[i] = bytespec{size: 1, extra: varmode(2 * rfixmap(i)), typ: MapType}
|
||||
}
|
||||
|
||||
// fixarray
|
||||
for i := mfixarray; i < 0xa0; i++ {
|
||||
sizes[i] = bytespec{size: 1, extra: varmode(rfixarray(i)), typ: ArrayType}
|
||||
}
|
||||
}
|
||||
|
||||
// a valid bytespsec has
|
||||
// non-zero 'size' and
|
||||
// non-zero 'typ'
|
||||
type bytespec struct {
|
||||
size uint8 // prefix size information
|
||||
extra varmode // extra size information
|
||||
typ Type // type
|
||||
_ byte // makes bytespec 4 bytes (yes, this matters)
|
||||
}
|
||||
|
||||
// size mode
|
||||
// if positive, # elements for composites
|
||||
type varmode int8
|
||||
|
||||
const (
|
||||
constsize varmode = 0 // constant size (size bytes + uint8(varmode) objects)
|
||||
extra8 = -1 // has uint8(p[1]) extra bytes
|
||||
extra16 = -2 // has be16(p[1:]) extra bytes
|
||||
extra32 = -3 // has be32(p[1:]) extra bytes
|
||||
map16v = -4 // use map16
|
||||
map32v = -5 // use map32
|
||||
array16v = -6 // use array16
|
||||
array32v = -7 // use array32
|
||||
)
|
||||
|
||||
func getType(v byte) Type {
|
||||
return sizes[v].typ
|
||||
}
|
142
vendor/src/github.com/tinylib/msgp/msgp/errors.go
vendored
Normal file
142
vendor/src/github.com/tinylib/msgp/msgp/errors.go
vendored
Normal file
|
@ -0,0 +1,142 @@
|
|||
package msgp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrShortBytes is returned when the
|
||||
// slice being decoded is too short to
|
||||
// contain the contents of the message
|
||||
ErrShortBytes error = errShort{}
|
||||
|
||||
// this error is only returned
|
||||
// if we reach code that should
|
||||
// be unreachable
|
||||
fatal error = errFatal{}
|
||||
)
|
||||
|
||||
// Error is the interface satisfied
|
||||
// by all of the errors that originate
|
||||
// from this package.
|
||||
type Error interface {
|
||||
error
|
||||
|
||||
// Resumable returns whether
|
||||
// or not the error means that
|
||||
// the stream of data is malformed
|
||||
// and the information is unrecoverable.
|
||||
Resumable() bool
|
||||
}
|
||||
|
||||
type errShort struct{}
|
||||
|
||||
func (e errShort) Error() string { return "msgp: too few bytes left to read object" }
|
||||
func (e errShort) Resumable() bool { return false }
|
||||
|
||||
type errFatal struct{}
|
||||
|
||||
func (f errFatal) Error() string { return "msgp: fatal decoding error (unreachable code)" }
|
||||
func (f errFatal) Resumable() bool { return false }
|
||||
|
||||
// ArrayError is an error returned
|
||||
// when decoding a fix-sized array
|
||||
// of the wrong size
|
||||
type ArrayError struct {
|
||||
Wanted uint32
|
||||
Got uint32
|
||||
}
|
||||
|
||||
// Error implements the error interface
|
||||
func (a ArrayError) Error() string {
|
||||
return fmt.Sprintf("msgp: wanted array of size %d; got %d", a.Wanted, a.Got)
|
||||
}
|
||||
|
||||
// Resumable is always 'true' for ArrayErrors
|
||||
func (a ArrayError) Resumable() bool { return true }
|
||||
|
||||
// IntOverflow is returned when a call
|
||||
// would downcast an integer to a type
|
||||
// with too few bits to hold its value.
|
||||
type IntOverflow struct {
|
||||
Value int64 // the value of the integer
|
||||
FailedBitsize int // the bit size that the int64 could not fit into
|
||||
}
|
||||
|
||||
// Error implements the error interface
|
||||
func (i IntOverflow) Error() string {
|
||||
return fmt.Sprintf("msgp: %d overflows int%d", i.Value, i.FailedBitsize)
|
||||
}
|
||||
|
||||
// Resumable is always 'true' for overflows
|
||||
func (i IntOverflow) Resumable() bool { return true }
|
||||
|
||||
// UintOverflow is returned when a call
|
||||
// would downcast an unsigned integer to a type
|
||||
// with too few bits to hold its value
|
||||
type UintOverflow struct {
|
||||
Value uint64 // value of the uint
|
||||
FailedBitsize int // the bit size that couldn't fit the value
|
||||
}
|
||||
|
||||
// Error implements the error interface
|
||||
func (u UintOverflow) Error() string {
|
||||
return fmt.Sprintf("msgp: %d overflows uint%d", u.Value, u.FailedBitsize)
|
||||
}
|
||||
|
||||
// Resumable is always 'true' for overflows
|
||||
func (u UintOverflow) Resumable() bool { return true }
|
||||
|
||||
// A TypeError is returned when a particular
|
||||
// decoding method is unsuitable for decoding
|
||||
// a particular MessagePack value.
|
||||
type TypeError struct {
|
||||
Method Type // Type expected by method
|
||||
Encoded Type // Type actually encoded
|
||||
}
|
||||
|
||||
// Error implements the error interface
|
||||
func (t TypeError) Error() string {
|
||||
return fmt.Sprintf("msgp: attempted to decode type %q with method for %q", t.Encoded, t.Method)
|
||||
}
|
||||
|
||||
// Resumable returns 'true' for TypeErrors
|
||||
func (t TypeError) Resumable() bool { return true }
|
||||
|
||||
// returns either InvalidPrefixError or
|
||||
// TypeError depending on whether or not
|
||||
// the prefix is recognized
|
||||
func badPrefix(want Type, lead byte) error {
|
||||
t := sizes[lead].typ
|
||||
if t == InvalidType {
|
||||
return InvalidPrefixError(lead)
|
||||
}
|
||||
return TypeError{Method: want, Encoded: t}
|
||||
}
|
||||
|
||||
// InvalidPrefixError is returned when a bad encoding
|
||||
// uses a prefix that is not recognized in the MessagePack standard.
|
||||
// This kind of error is unrecoverable.
|
||||
type InvalidPrefixError byte
|
||||
|
||||
// Error implements the error interface
|
||||
func (i InvalidPrefixError) Error() string {
|
||||
return fmt.Sprintf("msgp: unrecognized type prefix 0x%x", byte(i))
|
||||
}
|
||||
|
||||
// Resumable returns 'false' for InvalidPrefixErrors
|
||||
func (i InvalidPrefixError) Resumable() bool { return false }
|
||||
|
||||
// ErrUnsupportedType is returned
|
||||
// when a bad argument is supplied
|
||||
// to a function that takes `interface{}`.
|
||||
type ErrUnsupportedType struct {
|
||||
T reflect.Type
|
||||
}
|
||||
|
||||
// Error implements error
|
||||
func (e *ErrUnsupportedType) Error() string { return fmt.Sprintf("msgp: type %q not supported", e.T) }
|
||||
|
||||
// Resumable returns 'true' for ErrUnsupportedType
|
||||
func (e *ErrUnsupportedType) Resumable() bool { return true }
|
548
vendor/src/github.com/tinylib/msgp/msgp/extension.go
vendored
Normal file
548
vendor/src/github.com/tinylib/msgp/msgp/extension.go
vendored
Normal file
|
@ -0,0 +1,548 @@
|
|||
package msgp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
const (
|
||||
// Complex64Extension is the extension number used for complex64
|
||||
Complex64Extension = 3
|
||||
|
||||
// Complex128Extension is the extension number used for complex128
|
||||
Complex128Extension = 4
|
||||
|
||||
// TimeExtension is the extension number used for time.Time
|
||||
TimeExtension = 5
|
||||
)
|
||||
|
||||
// our extensions live here
|
||||
var extensionReg = make(map[int8]func() Extension)
|
||||
|
||||
// RegisterExtension registers extensions so that they
|
||||
// can be initialized and returned by methods that
|
||||
// decode `interface{}` values. This should only
|
||||
// be called during initialization. f() should return
|
||||
// a newly-initialized zero value of the extension. Keep in
|
||||
// mind that extensions 3, 4, and 5 are reserved for
|
||||
// complex64, complex128, and time.Time, respectively,
|
||||
// and that MessagePack reserves extension types from -127 to -1.
|
||||
//
|
||||
// For example, if you wanted to register a user-defined struct:
|
||||
//
|
||||
// msgp.RegisterExtension(10, func() msgp.Extension { &MyExtension{} })
|
||||
//
|
||||
// RegisterExtension will panic if you call it multiple times
|
||||
// with the same 'typ' argument, or if you use a reserved
|
||||
// type (3, 4, or 5).
|
||||
func RegisterExtension(typ int8, f func() Extension) {
|
||||
switch typ {
|
||||
case Complex64Extension, Complex128Extension, TimeExtension:
|
||||
panic(fmt.Sprint("msgp: forbidden extension type:", typ))
|
||||
}
|
||||
if _, ok := extensionReg[typ]; ok {
|
||||
panic(fmt.Sprint("msgp: RegisterExtension() called with typ", typ, "more than once"))
|
||||
}
|
||||
extensionReg[typ] = f
|
||||
}
|
||||
|
||||
// ExtensionTypeError is an error type returned
|
||||
// when there is a mis-match between an extension type
|
||||
// and the type encoded on the wire
|
||||
type ExtensionTypeError struct {
|
||||
Got int8
|
||||
Want int8
|
||||
}
|
||||
|
||||
// Error implements the error interface
|
||||
func (e ExtensionTypeError) Error() string {
|
||||
return fmt.Sprintf("msgp: error decoding extension: wanted type %d; got type %d", e.Want, e.Got)
|
||||
}
|
||||
|
||||
// Resumable returns 'true' for ExtensionTypeErrors
|
||||
func (e ExtensionTypeError) Resumable() bool { return true }
|
||||
|
||||
func errExt(got int8, wanted int8) error {
|
||||
return ExtensionTypeError{Got: got, Want: wanted}
|
||||
}
|
||||
|
||||
// Extension is the interface fulfilled
|
||||
// by types that want to define their
|
||||
// own binary encoding.
|
||||
type Extension interface {
|
||||
// ExtensionType should return
|
||||
// a int8 that identifies the concrete
|
||||
// type of the extension. (Types <0 are
|
||||
// officially reserved by the MessagePack
|
||||
// specifications.)
|
||||
ExtensionType() int8
|
||||
|
||||
// Len should return the length
|
||||
// of the data to be encoded
|
||||
Len() int
|
||||
|
||||
// MarshalBinaryTo should copy
|
||||
// the data into the supplied slice,
|
||||
// assuming that the slice has length Len()
|
||||
MarshalBinaryTo([]byte) error
|
||||
|
||||
UnmarshalBinary([]byte) error
|
||||
}
|
||||
|
||||
// RawExtension implements the Extension interface
|
||||
type RawExtension struct {
|
||||
Data []byte
|
||||
Type int8
|
||||
}
|
||||
|
||||
// ExtensionType implements Extension.ExtensionType, and returns r.Type
|
||||
func (r *RawExtension) ExtensionType() int8 { return r.Type }
|
||||
|
||||
// Len implements Extension.Len, and returns len(r.Data)
|
||||
func (r *RawExtension) Len() int { return len(r.Data) }
|
||||
|
||||
// MarshalBinaryTo implements Extension.MarshalBinaryTo,
|
||||
// and returns a copy of r.Data
|
||||
func (r *RawExtension) MarshalBinaryTo(d []byte) error {
|
||||
copy(d, r.Data)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalBinary implements Extension.UnmarshalBinary,
|
||||
// and sets r.Data to the contents of the provided slice
|
||||
func (r *RawExtension) UnmarshalBinary(b []byte) error {
|
||||
if cap(r.Data) >= len(b) {
|
||||
r.Data = r.Data[0:len(b)]
|
||||
} else {
|
||||
r.Data = make([]byte, len(b))
|
||||
}
|
||||
copy(r.Data, b)
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteExtension writes an extension type to the writer
|
||||
func (mw *Writer) WriteExtension(e Extension) error {
|
||||
l := e.Len()
|
||||
var err error
|
||||
switch l {
|
||||
case 0:
|
||||
o, err := mw.require(3)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mw.buf[o] = mext8
|
||||
mw.buf[o+1] = 0
|
||||
mw.buf[o+2] = byte(e.ExtensionType())
|
||||
case 1:
|
||||
o, err := mw.require(2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mw.buf[o] = mfixext1
|
||||
mw.buf[o+1] = byte(e.ExtensionType())
|
||||
case 2:
|
||||
o, err := mw.require(2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mw.buf[o] = mfixext2
|
||||
mw.buf[o+1] = byte(e.ExtensionType())
|
||||
case 4:
|
||||
o, err := mw.require(2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mw.buf[o] = mfixext4
|
||||
mw.buf[o+1] = byte(e.ExtensionType())
|
||||
case 8:
|
||||
o, err := mw.require(2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mw.buf[o] = mfixext8
|
||||
mw.buf[o+1] = byte(e.ExtensionType())
|
||||
case 16:
|
||||
o, err := mw.require(2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mw.buf[o] = mfixext16
|
||||
mw.buf[o+1] = byte(e.ExtensionType())
|
||||
default:
|
||||
switch {
|
||||
case l < math.MaxUint8:
|
||||
o, err := mw.require(3)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mw.buf[o] = mext8
|
||||
mw.buf[o+1] = byte(uint8(l))
|
||||
mw.buf[o+2] = byte(e.ExtensionType())
|
||||
case l < math.MaxUint16:
|
||||
o, err := mw.require(4)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mw.buf[o] = mext16
|
||||
big.PutUint16(mw.buf[o+1:], uint16(l))
|
||||
mw.buf[o+3] = byte(e.ExtensionType())
|
||||
default:
|
||||
o, err := mw.require(6)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mw.buf[o] = mext32
|
||||
big.PutUint32(mw.buf[o+1:], uint32(l))
|
||||
mw.buf[o+5] = byte(e.ExtensionType())
|
||||
}
|
||||
}
|
||||
// we can only write directly to the
|
||||
// buffer if we're sure that it
|
||||
// fits the object
|
||||
if l <= mw.bufsize() {
|
||||
o, err := mw.require(l)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return e.MarshalBinaryTo(mw.buf[o:])
|
||||
}
|
||||
// here we create a new buffer
|
||||
// just large enough for the body
|
||||
// and save it as the write buffer
|
||||
err = mw.flush()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buf := make([]byte, l)
|
||||
err = e.MarshalBinaryTo(buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mw.buf = buf
|
||||
mw.wloc = l
|
||||
return nil
|
||||
}
|
||||
|
||||
// peek at the extension type, assuming the next
|
||||
// kind to be read is Extension
|
||||
func (m *Reader) peekExtensionType() (int8, error) {
|
||||
p, err := m.r.Peek(2)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
spec := sizes[p[0]]
|
||||
if spec.typ != ExtensionType {
|
||||
return 0, badPrefix(ExtensionType, p[0])
|
||||
}
|
||||
if spec.extra == constsize {
|
||||
return int8(p[1]), nil
|
||||
}
|
||||
size := spec.size
|
||||
p, err = m.r.Peek(int(size))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int8(p[size-1]), nil
|
||||
}
|
||||
|
||||
// peekExtension peeks at the extension encoding type
|
||||
// (must guarantee at least 1 byte in 'b')
|
||||
func peekExtension(b []byte) (int8, error) {
|
||||
spec := sizes[b[0]]
|
||||
size := spec.size
|
||||
if spec.typ != ExtensionType {
|
||||
return 0, badPrefix(ExtensionType, b[0])
|
||||
}
|
||||
if len(b) < int(size) {
|
||||
return 0, ErrShortBytes
|
||||
}
|
||||
// for fixed extensions,
|
||||
// the type information is in
|
||||
// the second byte
|
||||
if spec.extra == constsize {
|
||||
return int8(b[1]), nil
|
||||
}
|
||||
// otherwise, it's in the last
|
||||
// part of the prefix
|
||||
return int8(b[size-1]), nil
|
||||
}
|
||||
|
||||
// ReadExtension reads the next object from the reader
|
||||
// as an extension. ReadExtension will fail if the next
|
||||
// object in the stream is not an extension, or if
|
||||
// e.Type() is not the same as the wire type.
|
||||
func (m *Reader) ReadExtension(e Extension) (err error) {
|
||||
var p []byte
|
||||
p, err = m.r.Peek(2)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
lead := p[0]
|
||||
var read int
|
||||
var off int
|
||||
switch lead {
|
||||
case mfixext1:
|
||||
if int8(p[1]) != e.ExtensionType() {
|
||||
err = errExt(int8(p[1]), e.ExtensionType())
|
||||
return
|
||||
}
|
||||
p, err = m.r.Peek(3)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = e.UnmarshalBinary(p[2:])
|
||||
if err == nil {
|
||||
_, err = m.r.Skip(3)
|
||||
}
|
||||
return
|
||||
|
||||
case mfixext2:
|
||||
if int8(p[1]) != e.ExtensionType() {
|
||||
err = errExt(int8(p[1]), e.ExtensionType())
|
||||
return
|
||||
}
|
||||
p, err = m.r.Peek(4)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = e.UnmarshalBinary(p[2:])
|
||||
if err == nil {
|
||||
_, err = m.r.Skip(4)
|
||||
}
|
||||
return
|
||||
|
||||
case mfixext4:
|
||||
if int8(p[1]) != e.ExtensionType() {
|
||||
err = errExt(int8(p[1]), e.ExtensionType())
|
||||
return
|
||||
}
|
||||
p, err = m.r.Peek(6)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = e.UnmarshalBinary(p[2:])
|
||||
if err == nil {
|
||||
_, err = m.r.Skip(6)
|
||||
}
|
||||
return
|
||||
|
||||
case mfixext8:
|
||||
if int8(p[1]) != e.ExtensionType() {
|
||||
err = errExt(int8(p[1]), e.ExtensionType())
|
||||
return
|
||||
}
|
||||
p, err = m.r.Peek(10)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = e.UnmarshalBinary(p[2:])
|
||||
if err == nil {
|
||||
_, err = m.r.Skip(10)
|
||||
}
|
||||
return
|
||||
|
||||
case mfixext16:
|
||||
if int8(p[1]) != e.ExtensionType() {
|
||||
err = errExt(int8(p[1]), e.ExtensionType())
|
||||
return
|
||||
}
|
||||
p, err = m.r.Peek(18)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = e.UnmarshalBinary(p[2:])
|
||||
if err == nil {
|
||||
_, err = m.r.Skip(18)
|
||||
}
|
||||
return
|
||||
|
||||
case mext8:
|
||||
p, err = m.r.Peek(3)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if int8(p[2]) != e.ExtensionType() {
|
||||
err = errExt(int8(p[2]), e.ExtensionType())
|
||||
return
|
||||
}
|
||||
read = int(uint8(p[1]))
|
||||
off = 3
|
||||
|
||||
case mext16:
|
||||
p, err = m.r.Peek(4)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if int8(p[3]) != e.ExtensionType() {
|
||||
err = errExt(int8(p[3]), e.ExtensionType())
|
||||
return
|
||||
}
|
||||
read = int(big.Uint16(p[1:]))
|
||||
off = 4
|
||||
|
||||
case mext32:
|
||||
p, err = m.r.Peek(6)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if int8(p[5]) != e.ExtensionType() {
|
||||
err = errExt(int8(p[5]), e.ExtensionType())
|
||||
return
|
||||
}
|
||||
read = int(big.Uint32(p[1:]))
|
||||
off = 6
|
||||
|
||||
default:
|
||||
err = badPrefix(ExtensionType, lead)
|
||||
return
|
||||
}
|
||||
|
||||
p, err = m.r.Peek(read + off)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = e.UnmarshalBinary(p[off:])
|
||||
if err == nil {
|
||||
_, err = m.r.Skip(read + off)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// AppendExtension appends a MessagePack extension to the provided slice
|
||||
func AppendExtension(b []byte, e Extension) ([]byte, error) {
|
||||
l := e.Len()
|
||||
var o []byte
|
||||
var n int
|
||||
switch l {
|
||||
case 0:
|
||||
o, n = ensure(b, 3)
|
||||
o[n] = mext8
|
||||
o[n+1] = 0
|
||||
o[n+2] = byte(e.ExtensionType())
|
||||
return o[:n+3], nil
|
||||
case 1:
|
||||
o, n = ensure(b, 3)
|
||||
o[n] = mfixext1
|
||||
o[n+1] = byte(e.ExtensionType())
|
||||
n += 2
|
||||
case 2:
|
||||
o, n = ensure(b, 4)
|
||||
o[n] = mfixext2
|
||||
o[n+1] = byte(e.ExtensionType())
|
||||
n += 2
|
||||
case 4:
|
||||
o, n = ensure(b, 6)
|
||||
o[n] = mfixext4
|
||||
o[n+1] = byte(e.ExtensionType())
|
||||
n += 2
|
||||
case 8:
|
||||
o, n = ensure(b, 10)
|
||||
o[n] = mfixext8
|
||||
o[n+1] = byte(e.ExtensionType())
|
||||
n += 2
|
||||
case 16:
|
||||
o, n = ensure(b, 18)
|
||||
o[n] = mfixext16
|
||||
o[n+1] = byte(e.ExtensionType())
|
||||
n += 2
|
||||
}
|
||||
switch {
|
||||
case l < math.MaxUint8:
|
||||
o, n = ensure(b, l+3)
|
||||
o[n] = mext8
|
||||
o[n+1] = byte(uint8(l))
|
||||
o[n+2] = byte(e.ExtensionType())
|
||||
n += 3
|
||||
case l < math.MaxUint16:
|
||||
o, n = ensure(b, l+4)
|
||||
o[n] = mext16
|
||||
big.PutUint16(o[n+1:], uint16(l))
|
||||
o[n+3] = byte(e.ExtensionType())
|
||||
n += 4
|
||||
default:
|
||||
o, n = ensure(b, l+6)
|
||||
o[n] = mext32
|
||||
big.PutUint32(o[n+1:], uint32(l))
|
||||
o[n+5] = byte(e.ExtensionType())
|
||||
n += 6
|
||||
}
|
||||
return o, e.MarshalBinaryTo(o[n:])
|
||||
}
|
||||
|
||||
// ReadExtensionBytes reads an extension from 'b' into 'e'
|
||||
// and returns any remaining bytes.
|
||||
// Possible errors:
|
||||
// - ErrShortBytes ('b' not long enough)
|
||||
// - ExtensionTypeErorr{} (wire type not the same as e.Type())
|
||||
// - TypeErorr{} (next object not an extension)
|
||||
// - InvalidPrefixError
|
||||
// - An umarshal error returned from e.UnmarshalBinary
|
||||
func ReadExtensionBytes(b []byte, e Extension) ([]byte, error) {
|
||||
l := len(b)
|
||||
if l < 3 {
|
||||
return b, ErrShortBytes
|
||||
}
|
||||
lead := b[0]
|
||||
var (
|
||||
sz int // size of 'data'
|
||||
off int // offset of 'data'
|
||||
typ int8
|
||||
)
|
||||
switch lead {
|
||||
case mfixext1:
|
||||
typ = int8(b[1])
|
||||
sz = 1
|
||||
off = 2
|
||||
case mfixext2:
|
||||
typ = int8(b[1])
|
||||
sz = 2
|
||||
off = 2
|
||||
case mfixext4:
|
||||
typ = int8(b[1])
|
||||
sz = 4
|
||||
off = 2
|
||||
case mfixext8:
|
||||
typ = int8(b[1])
|
||||
sz = 8
|
||||
off = 2
|
||||
case mfixext16:
|
||||
typ = int8(b[1])
|
||||
sz = 16
|
||||
off = 2
|
||||
case mext8:
|
||||
sz = int(uint8(b[1]))
|
||||
typ = int8(b[2])
|
||||
off = 3
|
||||
if sz == 0 {
|
||||
return b[3:], e.UnmarshalBinary(b[3:3])
|
||||
}
|
||||
case mext16:
|
||||
if l < 4 {
|
||||
return b, ErrShortBytes
|
||||
}
|
||||
sz = int(big.Uint16(b[1:]))
|
||||
typ = int8(b[3])
|
||||
off = 4
|
||||
case mext32:
|
||||
if l < 6 {
|
||||
return b, ErrShortBytes
|
||||
}
|
||||
sz = int(big.Uint32(b[1:]))
|
||||
typ = int8(b[5])
|
||||
off = 6
|
||||
default:
|
||||
return b, badPrefix(ExtensionType, lead)
|
||||
}
|
||||
|
||||
if typ != e.ExtensionType() {
|
||||
return b, errExt(typ, e.ExtensionType())
|
||||
}
|
||||
|
||||
// the data of the extension starts
|
||||
// at 'off' and is 'sz' bytes long
|
||||
if len(b[off:]) < sz {
|
||||
return b, ErrShortBytes
|
||||
}
|
||||
tot := off + sz
|
||||
return b[tot:], e.UnmarshalBinary(b[off:tot])
|
||||
}
|
174
vendor/src/github.com/tinylib/msgp/msgp/integers.go
vendored
Normal file
174
vendor/src/github.com/tinylib/msgp/msgp/integers.go
vendored
Normal file
|
@ -0,0 +1,174 @@
|
|||
package msgp
|
||||
|
||||
/* ----------------------------------
|
||||
integer encoding utilities
|
||||
(inline-able)
|
||||
|
||||
TODO(tinylib): there are faster,
|
||||
albeit non-portable solutions
|
||||
to the code below. implement
|
||||
byteswap?
|
||||
---------------------------------- */
|
||||
|
||||
func putMint64(b []byte, i int64) {
|
||||
b[0] = mint64
|
||||
b[1] = byte(i >> 56)
|
||||
b[2] = byte(i >> 48)
|
||||
b[3] = byte(i >> 40)
|
||||
b[4] = byte(i >> 32)
|
||||
b[5] = byte(i >> 24)
|
||||
b[6] = byte(i >> 16)
|
||||
b[7] = byte(i >> 8)
|
||||
b[8] = byte(i)
|
||||
}
|
||||
|
||||
func getMint64(b []byte) int64 {
|
||||
return (int64(b[1]) << 56) | (int64(b[2]) << 48) |
|
||||
(int64(b[3]) << 40) | (int64(b[4]) << 32) |
|
||||
(int64(b[5]) << 24) | (int64(b[6]) << 16) |
|
||||
(int64(b[7]) << 8) | (int64(b[8]))
|
||||
}
|
||||
|
||||
func putMint32(b []byte, i int32) {
|
||||
b[0] = mint32
|
||||
b[1] = byte(i >> 24)
|
||||
b[2] = byte(i >> 16)
|
||||
b[3] = byte(i >> 8)
|
||||
b[4] = byte(i)
|
||||
}
|
||||
|
||||
func getMint32(b []byte) int32 {
|
||||
return (int32(b[1]) << 24) | (int32(b[2]) << 16) | (int32(b[3]) << 8) | (int32(b[4]))
|
||||
}
|
||||
|
||||
func putMint16(b []byte, i int16) {
|
||||
b[0] = mint16
|
||||
b[1] = byte(i >> 8)
|
||||
b[2] = byte(i)
|
||||
}
|
||||
|
||||
func getMint16(b []byte) (i int16) {
|
||||
return (int16(b[1]) << 8) | int16(b[2])
|
||||
}
|
||||
|
||||
func putMint8(b []byte, i int8) {
|
||||
b[0] = mint8
|
||||
b[1] = byte(i)
|
||||
}
|
||||
|
||||
func getMint8(b []byte) (i int8) {
|
||||
return int8(b[1])
|
||||
}
|
||||
|
||||
func putMuint64(b []byte, u uint64) {
|
||||
b[0] = muint64
|
||||
b[1] = byte(u >> 56)
|
||||
b[2] = byte(u >> 48)
|
||||
b[3] = byte(u >> 40)
|
||||
b[4] = byte(u >> 32)
|
||||
b[5] = byte(u >> 24)
|
||||
b[6] = byte(u >> 16)
|
||||
b[7] = byte(u >> 8)
|
||||
b[8] = byte(u)
|
||||
}
|
||||
|
||||
func getMuint64(b []byte) uint64 {
|
||||
return (uint64(b[1]) << 56) | (uint64(b[2]) << 48) |
|
||||
(uint64(b[3]) << 40) | (uint64(b[4]) << 32) |
|
||||
(uint64(b[5]) << 24) | (uint64(b[6]) << 16) |
|
||||
(uint64(b[7]) << 8) | (uint64(b[8]))
|
||||
}
|
||||
|
||||
func putMuint32(b []byte, u uint32) {
|
||||
b[0] = muint32
|
||||
b[1] = byte(u >> 24)
|
||||
b[2] = byte(u >> 16)
|
||||
b[3] = byte(u >> 8)
|
||||
b[4] = byte(u)
|
||||
}
|
||||
|
||||
func getMuint32(b []byte) uint32 {
|
||||
return (uint32(b[1]) << 24) | (uint32(b[2]) << 16) | (uint32(b[3]) << 8) | (uint32(b[4]))
|
||||
}
|
||||
|
||||
func putMuint16(b []byte, u uint16) {
|
||||
b[0] = muint16
|
||||
b[1] = byte(u >> 8)
|
||||
b[2] = byte(u)
|
||||
}
|
||||
|
||||
func getMuint16(b []byte) uint16 {
|
||||
return (uint16(b[1]) << 8) | uint16(b[2])
|
||||
}
|
||||
|
||||
func putMuint8(b []byte, u uint8) {
|
||||
b[0] = muint8
|
||||
b[1] = byte(u)
|
||||
}
|
||||
|
||||
func getMuint8(b []byte) uint8 {
|
||||
return uint8(b[1])
|
||||
}
|
||||
|
||||
func getUnix(b []byte) (sec int64, nsec int32) {
|
||||
sec = (int64(b[0]) << 56) | (int64(b[1]) << 48) |
|
||||
(int64(b[2]) << 40) | (int64(b[3]) << 32) |
|
||||
(int64(b[4]) << 24) | (int64(b[5]) << 16) |
|
||||
(int64(b[6]) << 8) | (int64(b[7]))
|
||||
|
||||
nsec = (int32(b[8]) << 24) | (int32(b[9]) << 16) | (int32(b[10]) << 8) | (int32(b[11]))
|
||||
return
|
||||
}
|
||||
|
||||
func putUnix(b []byte, sec int64, nsec int32) {
|
||||
b[0] = byte(sec >> 56)
|
||||
b[1] = byte(sec >> 48)
|
||||
b[2] = byte(sec >> 40)
|
||||
b[3] = byte(sec >> 32)
|
||||
b[4] = byte(sec >> 24)
|
||||
b[5] = byte(sec >> 16)
|
||||
b[6] = byte(sec >> 8)
|
||||
b[7] = byte(sec)
|
||||
b[8] = byte(nsec >> 24)
|
||||
b[9] = byte(nsec >> 16)
|
||||
b[10] = byte(nsec >> 8)
|
||||
b[11] = byte(nsec)
|
||||
}
|
||||
|
||||
/* -----------------------------
|
||||
prefix utilities
|
||||
----------------------------- */
|
||||
|
||||
// write prefix and uint8
|
||||
func prefixu8(b []byte, pre byte, sz uint8) {
|
||||
b[0] = pre
|
||||
b[1] = byte(sz)
|
||||
}
|
||||
|
||||
// write prefix and big-endian uint16
|
||||
func prefixu16(b []byte, pre byte, sz uint16) {
|
||||
b[0] = pre
|
||||
b[1] = byte(sz >> 8)
|
||||
b[2] = byte(sz)
|
||||
}
|
||||
|
||||
// write prefix and big-endian uint32
|
||||
func prefixu32(b []byte, pre byte, sz uint32) {
|
||||
b[0] = pre
|
||||
b[1] = byte(sz >> 24)
|
||||
b[2] = byte(sz >> 16)
|
||||
b[3] = byte(sz >> 8)
|
||||
b[4] = byte(sz)
|
||||
}
|
||||
|
||||
func prefixu64(b []byte, pre byte, sz uint64) {
|
||||
b[0] = pre
|
||||
b[1] = byte(sz >> 56)
|
||||
b[2] = byte(sz >> 48)
|
||||
b[3] = byte(sz >> 40)
|
||||
b[4] = byte(sz >> 32)
|
||||
b[5] = byte(sz >> 24)
|
||||
b[6] = byte(sz >> 16)
|
||||
b[7] = byte(sz >> 8)
|
||||
b[8] = byte(sz)
|
||||
}
|
542
vendor/src/github.com/tinylib/msgp/msgp/json.go
vendored
Normal file
542
vendor/src/github.com/tinylib/msgp/msgp/json.go
vendored
Normal file
|
@ -0,0 +1,542 @@
|
|||
package msgp
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"strconv"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
var (
|
||||
null = []byte("null")
|
||||
hex = []byte("0123456789abcdef")
|
||||
)
|
||||
|
||||
var defuns [_maxtype]func(jsWriter, *Reader) (int, error)
|
||||
|
||||
// note: there is an initialization loop if
|
||||
// this isn't set up during init()
|
||||
func init() {
|
||||
// since none of these functions are inline-able,
|
||||
// there is not much of a penalty to the indirect
|
||||
// call. however, this is best expressed as a jump-table...
|
||||
defuns = [_maxtype]func(jsWriter, *Reader) (int, error){
|
||||
StrType: rwString,
|
||||
BinType: rwBytes,
|
||||
MapType: rwMap,
|
||||
ArrayType: rwArray,
|
||||
Float64Type: rwFloat64,
|
||||
Float32Type: rwFloat32,
|
||||
BoolType: rwBool,
|
||||
IntType: rwInt,
|
||||
UintType: rwUint,
|
||||
NilType: rwNil,
|
||||
ExtensionType: rwExtension,
|
||||
Complex64Type: rwExtension,
|
||||
Complex128Type: rwExtension,
|
||||
TimeType: rwTime,
|
||||
}
|
||||
}
|
||||
|
||||
// this is the interface
|
||||
// used to write json
|
||||
type jsWriter interface {
|
||||
io.Writer
|
||||
io.ByteWriter
|
||||
WriteString(string) (int, error)
|
||||
}
|
||||
|
||||
// CopyToJSON reads MessagePack from 'src' and copies it
|
||||
// as JSON to 'dst' until EOF.
|
||||
func CopyToJSON(dst io.Writer, src io.Reader) (n int64, err error) {
|
||||
r := NewReader(src)
|
||||
n, err = r.WriteToJSON(dst)
|
||||
freeR(r)
|
||||
return
|
||||
}
|
||||
|
||||
// WriteToJSON translates MessagePack from 'r' and writes it as
|
||||
// JSON to 'w' until the underlying reader returns io.EOF. It returns
|
||||
// the number of bytes written, and an error if it stopped before EOF.
|
||||
func (r *Reader) WriteToJSON(w io.Writer) (n int64, err error) {
|
||||
var j jsWriter
|
||||
var bf *bufio.Writer
|
||||
if jsw, ok := w.(jsWriter); ok {
|
||||
j = jsw
|
||||
} else {
|
||||
bf = bufio.NewWriterSize(w, 512)
|
||||
j = bf
|
||||
}
|
||||
var nn int
|
||||
for err == nil {
|
||||
nn, err = rwNext(j, r)
|
||||
n += int64(nn)
|
||||
}
|
||||
if err != io.EOF {
|
||||
if bf != nil {
|
||||
bf.Flush()
|
||||
}
|
||||
return
|
||||
}
|
||||
err = nil
|
||||
if bf != nil {
|
||||
err = bf.Flush()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func rwNext(w jsWriter, src *Reader) (int, error) {
|
||||
t, err := src.NextType()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return defuns[t](w, src)
|
||||
}
|
||||
|
||||
func rwMap(dst jsWriter, src *Reader) (n int, err error) {
|
||||
var comma bool
|
||||
var sz uint32
|
||||
var field []byte
|
||||
|
||||
sz, err = src.ReadMapHeader()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if sz == 0 {
|
||||
return dst.WriteString("{}")
|
||||
}
|
||||
|
||||
err = dst.WriteByte('{')
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n++
|
||||
var nn int
|
||||
for i := uint32(0); i < sz; i++ {
|
||||
if comma {
|
||||
err = dst.WriteByte(',')
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n++
|
||||
}
|
||||
|
||||
field, err = src.ReadMapKeyPtr()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
nn, err = rwquoted(dst, field)
|
||||
n += nn
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = dst.WriteByte(':')
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n++
|
||||
nn, err = rwNext(dst, src)
|
||||
n += nn
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if !comma {
|
||||
comma = true
|
||||
}
|
||||
}
|
||||
|
||||
err = dst.WriteByte('}')
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n++
|
||||
return
|
||||
}
|
||||
|
||||
func rwArray(dst jsWriter, src *Reader) (n int, err error) {
|
||||
err = dst.WriteByte('[')
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var sz uint32
|
||||
var nn int
|
||||
sz, err = src.ReadArrayHeader()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
comma := false
|
||||
for i := uint32(0); i < sz; i++ {
|
||||
if comma {
|
||||
err = dst.WriteByte(',')
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n++
|
||||
}
|
||||
nn, err = rwNext(dst, src)
|
||||
n += nn
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
comma = true
|
||||
}
|
||||
|
||||
err = dst.WriteByte(']')
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n++
|
||||
return
|
||||
}
|
||||
|
||||
func rwNil(dst jsWriter, src *Reader) (int, error) {
|
||||
err := src.ReadNil()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return dst.Write(null)
|
||||
}
|
||||
|
||||
func rwFloat32(dst jsWriter, src *Reader) (int, error) {
|
||||
f, err := src.ReadFloat32()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
src.scratch = strconv.AppendFloat(src.scratch[:0], float64(f), 'f', -1, 64)
|
||||
return dst.Write(src.scratch)
|
||||
}
|
||||
|
||||
func rwFloat64(dst jsWriter, src *Reader) (int, error) {
|
||||
f, err := src.ReadFloat64()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
src.scratch = strconv.AppendFloat(src.scratch[:0], f, 'f', -1, 32)
|
||||
return dst.Write(src.scratch)
|
||||
}
|
||||
|
||||
func rwInt(dst jsWriter, src *Reader) (int, error) {
|
||||
i, err := src.ReadInt64()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
src.scratch = strconv.AppendInt(src.scratch[:0], i, 10)
|
||||
return dst.Write(src.scratch)
|
||||
}
|
||||
|
||||
func rwUint(dst jsWriter, src *Reader) (int, error) {
|
||||
u, err := src.ReadUint64()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
src.scratch = strconv.AppendUint(src.scratch[:0], u, 10)
|
||||
return dst.Write(src.scratch)
|
||||
}
|
||||
|
||||
func rwBool(dst jsWriter, src *Reader) (int, error) {
|
||||
b, err := src.ReadBool()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if b {
|
||||
return dst.WriteString("true")
|
||||
}
|
||||
return dst.WriteString("false")
|
||||
}
|
||||
|
||||
func rwTime(dst jsWriter, src *Reader) (int, error) {
|
||||
t, err := src.ReadTime()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
bts, err := t.MarshalJSON()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return dst.Write(bts)
|
||||
}
|
||||
|
||||
func rwExtension(dst jsWriter, src *Reader) (n int, err error) {
|
||||
et, err := src.peekExtensionType()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// registered extensions can override
|
||||
// the JSON encoding
|
||||
if j, ok := extensionReg[et]; ok {
|
||||
var bts []byte
|
||||
e := j()
|
||||
err = src.ReadExtension(e)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
bts, err = json.Marshal(e)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return dst.Write(bts)
|
||||
}
|
||||
|
||||
e := RawExtension{}
|
||||
e.Type = et
|
||||
err = src.ReadExtension(&e)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var nn int
|
||||
err = dst.WriteByte('{')
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n++
|
||||
|
||||
nn, err = dst.WriteString(`"type:"`)
|
||||
n += nn
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
src.scratch = strconv.AppendInt(src.scratch[0:0], int64(e.Type), 10)
|
||||
nn, err = dst.Write(src.scratch)
|
||||
n += nn
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
nn, err = dst.WriteString(`,"data":"`)
|
||||
n += nn
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
enc := base64.NewEncoder(base64.StdEncoding, dst)
|
||||
|
||||
nn, err = enc.Write(e.Data)
|
||||
n += nn
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = enc.Close()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
nn, err = dst.WriteString(`"}`)
|
||||
n += nn
|
||||
return
|
||||
}
|
||||
|
||||
func rwString(dst jsWriter, src *Reader) (n int, err error) {
|
||||
var p []byte
|
||||
p, err = src.r.Peek(1)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
lead := p[0]
|
||||
var read int
|
||||
|
||||
if isfixstr(lead) {
|
||||
read = int(rfixstr(lead))
|
||||
src.r.Skip(1)
|
||||
goto write
|
||||
}
|
||||
|
||||
switch lead {
|
||||
case mstr8:
|
||||
p, err = src.r.Next(2)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
read = int(uint8(p[1]))
|
||||
case mstr16:
|
||||
p, err = src.r.Next(3)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
read = int(big.Uint16(p[1:]))
|
||||
case mstr32:
|
||||
p, err = src.r.Next(5)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
read = int(big.Uint32(p[1:]))
|
||||
default:
|
||||
err = badPrefix(StrType, lead)
|
||||
return
|
||||
}
|
||||
write:
|
||||
p, err = src.r.Next(read)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n, err = rwquoted(dst, p)
|
||||
return
|
||||
}
|
||||
|
||||
func rwBytes(dst jsWriter, src *Reader) (n int, err error) {
|
||||
var nn int
|
||||
err = dst.WriteByte('"')
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n++
|
||||
src.scratch, err = src.ReadBytes(src.scratch[:0])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
enc := base64.NewEncoder(base64.StdEncoding, dst)
|
||||
nn, err = enc.Write(src.scratch)
|
||||
n += nn
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = enc.Close()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = dst.WriteByte('"')
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n++
|
||||
return
|
||||
}
|
||||
|
||||
// Below (c) The Go Authors, 2009-2014
|
||||
// Subject to the BSD-style license found at http://golang.org
|
||||
//
|
||||
// see: encoding/json/encode.go:(*encodeState).stringbytes()
|
||||
func rwquoted(dst jsWriter, s []byte) (n int, err error) {
|
||||
var nn int
|
||||
err = dst.WriteByte('"')
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n++
|
||||
start := 0
|
||||
for i := 0; i < len(s); {
|
||||
if b := s[i]; b < utf8.RuneSelf {
|
||||
if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' && b != '&' {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
if start < i {
|
||||
nn, err = dst.Write(s[start:i])
|
||||
n += nn
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
switch b {
|
||||
case '\\', '"':
|
||||
err = dst.WriteByte('\\')
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n++
|
||||
err = dst.WriteByte(b)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n++
|
||||
case '\n':
|
||||
err = dst.WriteByte('\\')
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n++
|
||||
err = dst.WriteByte('n')
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n++
|
||||
case '\r':
|
||||
err = dst.WriteByte('\\')
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n++
|
||||
err = dst.WriteByte('r')
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n++
|
||||
default:
|
||||
nn, err = dst.WriteString(`\u00`)
|
||||
n += nn
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = dst.WriteByte(hex[b>>4])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n++
|
||||
err = dst.WriteByte(hex[b&0xF])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n++
|
||||
}
|
||||
i++
|
||||
start = i
|
||||
continue
|
||||
}
|
||||
c, size := utf8.DecodeRune(s[i:])
|
||||
if c == utf8.RuneError && size == 1 {
|
||||
if start < i {
|
||||
nn, err = dst.Write(s[start:i])
|
||||
n += nn
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
nn, err = dst.WriteString(`\ufffd`)
|
||||
n += nn
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
i += size
|
||||
start = i
|
||||
continue
|
||||
}
|
||||
}
|
||||
if c == '\u2028' || c == '\u2029' {
|
||||
if start < i {
|
||||
nn, err = dst.Write(s[start:i])
|
||||
n += nn
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
nn, err = dst.WriteString(`\u202`)
|
||||
n += nn
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = dst.WriteByte(hex[c&0xF])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n++
|
||||
}
|
||||
}
|
||||
i += size
|
||||
}
|
||||
if start < len(s) {
|
||||
nn, err = dst.Write(s[start:])
|
||||
n += nn
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
err = dst.WriteByte('"')
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n++
|
||||
return
|
||||
}
|
363
vendor/src/github.com/tinylib/msgp/msgp/json_bytes.go
vendored
Normal file
363
vendor/src/github.com/tinylib/msgp/msgp/json_bytes.go
vendored
Normal file
|
@ -0,0 +1,363 @@
|
|||
package msgp
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
var unfuns [_maxtype]func(jsWriter, []byte, []byte) ([]byte, []byte, error)
|
||||
|
||||
func init() {
|
||||
|
||||
// NOTE(pmh): this is best expressed as a jump table,
|
||||
// but gc doesn't do that yet. revisit post-go1.5.
|
||||
unfuns = [_maxtype]func(jsWriter, []byte, []byte) ([]byte, []byte, error){
|
||||
StrType: rwStringBytes,
|
||||
BinType: rwBytesBytes,
|
||||
MapType: rwMapBytes,
|
||||
ArrayType: rwArrayBytes,
|
||||
Float64Type: rwFloat64Bytes,
|
||||
Float32Type: rwFloat32Bytes,
|
||||
BoolType: rwBoolBytes,
|
||||
IntType: rwIntBytes,
|
||||
UintType: rwUintBytes,
|
||||
NilType: rwNullBytes,
|
||||
ExtensionType: rwExtensionBytes,
|
||||
Complex64Type: rwExtensionBytes,
|
||||
Complex128Type: rwExtensionBytes,
|
||||
TimeType: rwTimeBytes,
|
||||
}
|
||||
}
|
||||
|
||||
// UnmarshalAsJSON takes raw messagepack and writes
|
||||
// it as JSON to 'w'. If an error is returned, the
|
||||
// bytes not translated will also be returned. If
|
||||
// no errors are encountered, the length of the returned
|
||||
// slice will be zero.
|
||||
func UnmarshalAsJSON(w io.Writer, msg []byte) ([]byte, error) {
|
||||
var (
|
||||
scratch []byte
|
||||
cast bool
|
||||
dst jsWriter
|
||||
err error
|
||||
)
|
||||
if jsw, ok := w.(jsWriter); ok {
|
||||
dst = jsw
|
||||
cast = true
|
||||
} else {
|
||||
dst = bufio.NewWriterSize(w, 512)
|
||||
}
|
||||
for len(msg) > 0 && err == nil {
|
||||
msg, scratch, err = writeNext(dst, msg, scratch)
|
||||
}
|
||||
if !cast && err == nil {
|
||||
err = dst.(*bufio.Writer).Flush()
|
||||
}
|
||||
return msg, err
|
||||
}
|
||||
|
||||
func writeNext(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
|
||||
if len(msg) < 1 {
|
||||
return msg, scratch, ErrShortBytes
|
||||
}
|
||||
t := getType(msg[0])
|
||||
if t == InvalidType {
|
||||
return msg, scratch, InvalidPrefixError(msg[0])
|
||||
}
|
||||
if t == ExtensionType {
|
||||
et, err := peekExtension(msg)
|
||||
if err != nil {
|
||||
return nil, scratch, err
|
||||
}
|
||||
if et == TimeExtension {
|
||||
t = TimeType
|
||||
}
|
||||
}
|
||||
return unfuns[t](w, msg, scratch)
|
||||
}
|
||||
|
||||
func rwArrayBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
|
||||
sz, msg, err := ReadArrayHeaderBytes(msg)
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
err = w.WriteByte('[')
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
for i := uint32(0); i < sz; i++ {
|
||||
if i != 0 {
|
||||
err = w.WriteByte(',')
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
}
|
||||
msg, scratch, err = writeNext(w, msg, scratch)
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
}
|
||||
err = w.WriteByte(']')
|
||||
return msg, scratch, err
|
||||
}
|
||||
|
||||
func rwMapBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
|
||||
sz, msg, err := ReadMapHeaderBytes(msg)
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
err = w.WriteByte('{')
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
for i := uint32(0); i < sz; i++ {
|
||||
if i != 0 {
|
||||
err = w.WriteByte(',')
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
}
|
||||
msg, scratch, err = rwMapKeyBytes(w, msg, scratch)
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
err = w.WriteByte(':')
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
msg, scratch, err = writeNext(w, msg, scratch)
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
}
|
||||
err = w.WriteByte('}')
|
||||
return msg, scratch, err
|
||||
}
|
||||
|
||||
func rwMapKeyBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
|
||||
msg, scratch, err := rwStringBytes(w, msg, scratch)
|
||||
if err != nil {
|
||||
if tperr, ok := err.(TypeError); ok && tperr.Encoded == BinType {
|
||||
return rwBytesBytes(w, msg, scratch)
|
||||
}
|
||||
}
|
||||
return msg, scratch, err
|
||||
}
|
||||
|
||||
func rwStringBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
|
||||
str, msg, err := ReadStringZC(msg)
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
_, err = rwquoted(w, str)
|
||||
return msg, scratch, err
|
||||
}
|
||||
|
||||
func rwBytesBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
|
||||
bts, msg, err := ReadBytesZC(msg)
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
l := base64.StdEncoding.EncodedLen(len(bts))
|
||||
if cap(scratch) >= l {
|
||||
scratch = scratch[0:l]
|
||||
} else {
|
||||
scratch = make([]byte, l)
|
||||
}
|
||||
base64.StdEncoding.Encode(scratch, bts)
|
||||
err = w.WriteByte('"')
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
_, err = w.Write(scratch)
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
err = w.WriteByte('"')
|
||||
return msg, scratch, err
|
||||
}
|
||||
|
||||
func rwNullBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
|
||||
msg, err := ReadNilBytes(msg)
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
_, err = w.Write(null)
|
||||
return msg, scratch, err
|
||||
}
|
||||
|
||||
func rwBoolBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
|
||||
b, msg, err := ReadBoolBytes(msg)
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
if b {
|
||||
_, err = w.WriteString("true")
|
||||
return msg, scratch, err
|
||||
}
|
||||
_, err = w.WriteString("false")
|
||||
return msg, scratch, err
|
||||
}
|
||||
|
||||
func rwIntBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
|
||||
i, msg, err := ReadInt64Bytes(msg)
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
scratch = strconv.AppendInt(scratch[0:0], i, 10)
|
||||
_, err = w.Write(scratch)
|
||||
return msg, scratch, err
|
||||
}
|
||||
|
||||
func rwUintBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
|
||||
u, msg, err := ReadUint64Bytes(msg)
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
scratch = strconv.AppendUint(scratch[0:0], u, 10)
|
||||
_, err = w.Write(scratch)
|
||||
return msg, scratch, err
|
||||
}
|
||||
|
||||
func rwFloatBytes(w jsWriter, msg []byte, f64 bool, scratch []byte) ([]byte, []byte, error) {
|
||||
var f float64
|
||||
var err error
|
||||
var sz int
|
||||
if f64 {
|
||||
sz = 64
|
||||
f, msg, err = ReadFloat64Bytes(msg)
|
||||
} else {
|
||||
sz = 32
|
||||
var v float32
|
||||
v, msg, err = ReadFloat32Bytes(msg)
|
||||
f = float64(v)
|
||||
}
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
scratch = strconv.AppendFloat(scratch, f, 'f', -1, sz)
|
||||
_, err = w.Write(scratch)
|
||||
return msg, scratch, err
|
||||
}
|
||||
|
||||
func rwFloat32Bytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
|
||||
var f float32
|
||||
var err error
|
||||
f, msg, err = ReadFloat32Bytes(msg)
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
scratch = strconv.AppendFloat(scratch[:0], float64(f), 'f', -1, 32)
|
||||
_, err = w.Write(scratch)
|
||||
return msg, scratch, err
|
||||
}
|
||||
|
||||
func rwFloat64Bytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
|
||||
var f float64
|
||||
var err error
|
||||
f, msg, err = ReadFloat64Bytes(msg)
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
scratch = strconv.AppendFloat(scratch[:0], f, 'f', -1, 64)
|
||||
_, err = w.Write(scratch)
|
||||
return msg, scratch, err
|
||||
}
|
||||
|
||||
func rwTimeBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
|
||||
var t time.Time
|
||||
var err error
|
||||
t, msg, err = ReadTimeBytes(msg)
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
bts, err := t.MarshalJSON()
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
_, err = w.Write(bts)
|
||||
return msg, scratch, err
|
||||
}
|
||||
|
||||
func rwExtensionBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
|
||||
var err error
|
||||
var et int8
|
||||
et, err = peekExtension(msg)
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
|
||||
// if it's time.Time
|
||||
if et == TimeExtension {
|
||||
var tm time.Time
|
||||
tm, msg, err = ReadTimeBytes(msg)
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
bts, err := tm.MarshalJSON()
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
_, err = w.Write(bts)
|
||||
return msg, scratch, err
|
||||
}
|
||||
|
||||
// if the extension is registered,
|
||||
// use its canonical JSON form
|
||||
if f, ok := extensionReg[et]; ok {
|
||||
e := f()
|
||||
msg, err = ReadExtensionBytes(msg, e)
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
bts, err := json.Marshal(e)
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
_, err = w.Write(bts)
|
||||
return msg, scratch, err
|
||||
}
|
||||
|
||||
// otherwise, write `{"type": <num>, "data": "<base64data>"}`
|
||||
r := RawExtension{}
|
||||
r.Type = et
|
||||
msg, err = ReadExtensionBytes(msg, &r)
|
||||
if err != nil {
|
||||
return msg, scratch, err
|
||||
}
|
||||
scratch, err = writeExt(w, r, scratch)
|
||||
return msg, scratch, err
|
||||
}
|
||||
|
||||
func writeExt(w jsWriter, r RawExtension, scratch []byte) ([]byte, error) {
|
||||
_, err := w.WriteString(`{"type":`)
|
||||
if err != nil {
|
||||
return scratch, err
|
||||
}
|
||||
scratch = strconv.AppendInt(scratch[0:0], int64(r.Type), 10)
|
||||
_, err = w.Write(scratch)
|
||||
if err != nil {
|
||||
return scratch, err
|
||||
}
|
||||
_, err = w.WriteString(`,"data":"`)
|
||||
if err != nil {
|
||||
return scratch, err
|
||||
}
|
||||
l := base64.StdEncoding.EncodedLen(len(r.Data))
|
||||
if cap(scratch) >= l {
|
||||
scratch = scratch[0:l]
|
||||
} else {
|
||||
scratch = make([]byte, l)
|
||||
}
|
||||
base64.StdEncoding.Encode(scratch, r.Data)
|
||||
_, err = w.Write(scratch)
|
||||
if err != nil {
|
||||
return scratch, err
|
||||
}
|
||||
_, err = w.WriteString(`"}`)
|
||||
return scratch, err
|
||||
}
|
140
vendor/src/github.com/tinylib/msgp/msgp/number.go
vendored
Normal file
140
vendor/src/github.com/tinylib/msgp/msgp/number.go
vendored
Normal file
|
@ -0,0 +1,140 @@
|
|||
package msgp
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// The portable parts of the Number implementation
|
||||
|
||||
// DecodeMsg implements msgp.Decodable
|
||||
func (n *Number) DecodeMsg(r *Reader) error {
|
||||
typ, err := r.NextType()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch typ {
|
||||
case Float32Type:
|
||||
f, err := r.ReadFloat32()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n.AsFloat32(f)
|
||||
return nil
|
||||
case Float64Type:
|
||||
f, err := r.ReadFloat64()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n.AsFloat64(f)
|
||||
return nil
|
||||
case IntType:
|
||||
i, err := r.ReadInt64()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n.AsInt(i)
|
||||
return nil
|
||||
case UintType:
|
||||
u, err := r.ReadUint64()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n.AsUint(u)
|
||||
return nil
|
||||
default:
|
||||
return TypeError{Encoded: typ, Method: IntType}
|
||||
}
|
||||
}
|
||||
|
||||
// UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (n *Number) UnmarshalMsg(b []byte) ([]byte, error) {
|
||||
typ := NextType(b)
|
||||
switch typ {
|
||||
case IntType:
|
||||
i, o, err := ReadInt64Bytes(b)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
n.AsInt(i)
|
||||
return o, nil
|
||||
case UintType:
|
||||
u, o, err := ReadUint64Bytes(b)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
n.AsUint(u)
|
||||
return o, nil
|
||||
case Float64Type:
|
||||
f, o, err := ReadFloat64Bytes(b)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
n.AsFloat64(f)
|
||||
return o, nil
|
||||
case Float32Type:
|
||||
f, o, err := ReadFloat32Bytes(b)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
n.AsFloat32(f)
|
||||
return o, nil
|
||||
default:
|
||||
return b, TypeError{Method: IntType, Encoded: typ}
|
||||
}
|
||||
}
|
||||
|
||||
// Msgsize implements msgp.Sizer
|
||||
func (n *Number) Msgsize() int {
|
||||
switch n.typ {
|
||||
case Float32Type:
|
||||
return Float32Size
|
||||
case Float64Type:
|
||||
return Float64Size
|
||||
case IntType:
|
||||
return Int64Size
|
||||
case UintType:
|
||||
return Uint64Size
|
||||
default:
|
||||
return 1 // fixint(0)
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalJSON implements json.Marshaler
|
||||
func (n *Number) MarshalJSON() ([]byte, error) {
|
||||
t := n.Type()
|
||||
if t == InvalidType {
|
||||
return []byte{'0'}, nil
|
||||
}
|
||||
out := make([]byte, 0, 32)
|
||||
switch t {
|
||||
case Float32Type, Float64Type:
|
||||
f, _ := n.Float()
|
||||
return strconv.AppendFloat(out, f, 'f', -1, 64), nil
|
||||
case IntType:
|
||||
i, _ := n.Int()
|
||||
return strconv.AppendInt(out, i, 10), nil
|
||||
case UintType:
|
||||
u, _ := n.Uint()
|
||||
return strconv.AppendUint(out, u, 10), nil
|
||||
default:
|
||||
panic("(*Number).typ is invalid")
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Number) String() string {
|
||||
switch n.typ {
|
||||
case InvalidType:
|
||||
return "0"
|
||||
case Float32Type, Float64Type:
|
||||
f, _ := n.Float()
|
||||
return strconv.FormatFloat(f, 'f', -1, 64)
|
||||
case IntType:
|
||||
i, _ := n.Int()
|
||||
return strconv.FormatInt(i, 10)
|
||||
case UintType:
|
||||
u, _ := n.Uint()
|
||||
return strconv.FormatUint(u, 10)
|
||||
default:
|
||||
panic("(*Number).typ is invalid")
|
||||
}
|
||||
}
|
101
vendor/src/github.com/tinylib/msgp/msgp/number_appengine.go
vendored
Normal file
101
vendor/src/github.com/tinylib/msgp/msgp/number_appengine.go
vendored
Normal file
|
@ -0,0 +1,101 @@
|
|||
// +build appengine
|
||||
|
||||
package msgp
|
||||
|
||||
// let's just assume appengine
|
||||
// uses 64-bit hardware...
|
||||
const smallint = false
|
||||
|
||||
func UnsafeString(b []byte) string {
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func UnsafeBytes(s string) []byte {
|
||||
return []byte(s)
|
||||
}
|
||||
|
||||
type Number struct {
|
||||
ibits uint64 // zero or bits
|
||||
fbits float64 // zero or bits
|
||||
typ Type // zero or type
|
||||
}
|
||||
|
||||
func (n *Number) AsFloat64(f float64) {
|
||||
n.typ = Float64Type
|
||||
n.fbits = f
|
||||
n.ibits = 0
|
||||
}
|
||||
|
||||
func (n *Number) AsFloat32(f float32) {
|
||||
n.typ = Float32Type
|
||||
n.fbits = float64(f)
|
||||
n.ibits = 0
|
||||
}
|
||||
|
||||
func (n *Number) AsInt(i int64) {
|
||||
n.fbits = 0
|
||||
if i == 0 {
|
||||
n.typ = InvalidType
|
||||
n.ibits = 0
|
||||
return
|
||||
}
|
||||
n.ibits = uint64(i)
|
||||
n.typ = IntType
|
||||
}
|
||||
|
||||
func (n *Number) AsUint(u uint64) {
|
||||
n.ibits = u
|
||||
n.fbits = 0
|
||||
n.typ = UintType
|
||||
}
|
||||
|
||||
func (n *Number) Float() (float64, bool) {
|
||||
return n.fbits, n.typ == Float64Type || n.typ == Float32Type
|
||||
}
|
||||
|
||||
func (n *Number) Int() (int64, bool) {
|
||||
return int64(n.ibits), n.typ == IntType
|
||||
}
|
||||
|
||||
func (n *Number) Uint() (uint64, bool) {
|
||||
return n.ibits, n.typ == UintType
|
||||
}
|
||||
|
||||
func (n *Number) Type() Type {
|
||||
if n.typ == InvalidType {
|
||||
return IntType
|
||||
}
|
||||
return n.typ
|
||||
}
|
||||
|
||||
func (n *Number) MarshalMsg(o []byte) ([]byte, error) {
|
||||
switch n.typ {
|
||||
case InvalidType:
|
||||
return AppendInt64(o, 0), nil
|
||||
case IntType:
|
||||
return AppendInt64(o, int64(n.ibits)), nil
|
||||
case UintType:
|
||||
return AppendUint64(o, n.ibits), nil
|
||||
case Float32Type:
|
||||
return AppendFloat32(o, float32(n.fbits)), nil
|
||||
case Float64Type:
|
||||
return AppendFloat64(o, n.fbits), nil
|
||||
}
|
||||
panic("unreachable code!")
|
||||
}
|
||||
|
||||
func (n *Number) EncodeMsg(w *Writer) error {
|
||||
switch n.typ {
|
||||
case InvalidType:
|
||||
return w.WriteInt64(0)
|
||||
case IntType:
|
||||
return w.WriteInt64(int64(n.ibits))
|
||||
case UintType:
|
||||
return w.WriteUint64(n.ibits)
|
||||
case Float32Type:
|
||||
return w.WriteFloat32(float32(n.fbits))
|
||||
case Float64Type:
|
||||
return w.WriteFloat64(n.fbits)
|
||||
}
|
||||
panic("unreachable code!")
|
||||
}
|
159
vendor/src/github.com/tinylib/msgp/msgp/number_unsafe.go
vendored
Normal file
159
vendor/src/github.com/tinylib/msgp/msgp/number_unsafe.go
vendored
Normal file
|
@ -0,0 +1,159 @@
|
|||
// +build !appengine
|
||||
|
||||
package msgp
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
// spec says int and uint are always
|
||||
// the same size, but that int/uint
|
||||
// size may not be machine word size
|
||||
smallint = unsafe.Sizeof(int(0)) == 4
|
||||
)
|
||||
|
||||
// UnsafeString returns the byte slice as a volatile string
|
||||
// THIS SHOULD ONLY BE USED BY THE CODE GENERATOR.
|
||||
// THIS IS EVIL CODE.
|
||||
// YOU HAVE BEEN WARNED.
|
||||
func UnsafeString(b []byte) string {
|
||||
return *(*string)(unsafe.Pointer(&reflect.StringHeader{Data: uintptr(unsafe.Pointer(&b[0])), Len: len(b)}))
|
||||
}
|
||||
|
||||
// UnsafeBytes returns the string as a byte slice
|
||||
// THIS SHOULD ONLY BE USED BY THE CODE GENERATOR.
|
||||
// THIS IS EVIL CODE.
|
||||
// YOU HAVE BEEN WARNED.
|
||||
func UnsafeBytes(s string) []byte {
|
||||
return *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
|
||||
Len: len(s),
|
||||
Cap: len(s),
|
||||
Data: (*(*reflect.StringHeader)(unsafe.Pointer(&s))).Data,
|
||||
}))
|
||||
}
|
||||
|
||||
// Number can be
|
||||
// an int64, uint64, float32,
|
||||
// or float64 internally.
|
||||
// It can decode itself
|
||||
// from any of the native
|
||||
// messagepack number types.
|
||||
// The zero-value of Number
|
||||
// is Int(0). Using the equality
|
||||
// operator with Number compares
|
||||
// both the type and the value
|
||||
// of the number.
|
||||
type Number struct {
|
||||
// internally, this
|
||||
// is just a tagged union.
|
||||
// the raw bits of the number
|
||||
// are stored the same way regardless.
|
||||
bits uint64
|
||||
typ Type
|
||||
}
|
||||
|
||||
// AsFloat64 sets the number to
|
||||
// a float64.
|
||||
func (n *Number) AsFloat64(f float64) {
|
||||
n.typ = Float64Type
|
||||
n.bits = *(*uint64)(unsafe.Pointer(&f))
|
||||
}
|
||||
|
||||
// AsInt sets the number to an int64.
|
||||
func (n *Number) AsInt(i int64) {
|
||||
|
||||
// we always store int(0)
|
||||
// as {0, InvalidType} in
|
||||
// order to preserve
|
||||
// the behavior of the == operator
|
||||
if i == 0 {
|
||||
n.typ = InvalidType
|
||||
n.bits = 0
|
||||
return
|
||||
}
|
||||
|
||||
n.typ = IntType
|
||||
n.bits = uint64(i)
|
||||
}
|
||||
|
||||
// AsUint sets the number to a uint64.
|
||||
func (n *Number) AsUint(u uint64) {
|
||||
n.typ = UintType
|
||||
n.bits = u
|
||||
}
|
||||
|
||||
// AsFloat32 sets the number to a float32.
|
||||
func (n *Number) AsFloat32(f float32) {
|
||||
n.typ = Float32Type
|
||||
g := float64(f)
|
||||
n.bits = *(*uint64)(unsafe.Pointer(&g))
|
||||
}
|
||||
|
||||
// Type will return one of:
|
||||
// Float64Type, Float32Type, UintType, or IntType.
|
||||
func (n *Number) Type() Type {
|
||||
if n.typ == InvalidType {
|
||||
return IntType
|
||||
}
|
||||
return n.typ
|
||||
}
|
||||
|
||||
// Float casts the number of the float,
|
||||
// and returns whether or not that was
|
||||
// the underlying type. (This is legal
|
||||
// for both float32 and float64 types.)
|
||||
func (n *Number) Float() (float64, bool) {
|
||||
return *(*float64)(unsafe.Pointer(&n.bits)), n.typ == Float64Type || n.typ == Float32Type
|
||||
}
|
||||
|
||||
// Int casts the number as an int64, and
|
||||
// returns whether or not that was the
|
||||
// underlying type.
|
||||
func (n *Number) Int() (int64, bool) {
|
||||
return int64(n.bits), n.typ == IntType || n.typ == InvalidType
|
||||
}
|
||||
|
||||
// Uint casts the number as a uint64, and returns
|
||||
// whether or not that was the underlying type.
|
||||
func (n *Number) Uint() (uint64, bool) {
|
||||
return n.bits, n.typ == UintType
|
||||
}
|
||||
|
||||
// EncodeMsg implements msgp.Encodable
|
||||
func (n *Number) EncodeMsg(w *Writer) error {
|
||||
switch n.typ {
|
||||
case InvalidType:
|
||||
return w.WriteInt(0)
|
||||
case IntType:
|
||||
return w.WriteInt64(int64(n.bits))
|
||||
case UintType:
|
||||
return w.WriteUint64(n.bits)
|
||||
case Float64Type:
|
||||
return w.WriteFloat64(*(*float64)(unsafe.Pointer(&n.bits)))
|
||||
case Float32Type:
|
||||
return w.WriteFloat32(float32(*(*float64)(unsafe.Pointer(&n.bits))))
|
||||
default:
|
||||
// this should never ever happen
|
||||
panic("(*Number).typ is invalid")
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalMsg implements msgp.Marshaler
|
||||
func (n *Number) MarshalMsg(b []byte) ([]byte, error) {
|
||||
switch n.typ {
|
||||
case InvalidType:
|
||||
return AppendInt(b, 0), nil
|
||||
case IntType:
|
||||
return AppendInt64(b, int64(n.bits)), nil
|
||||
case UintType:
|
||||
return AppendUint64(b, n.bits), nil
|
||||
case Float64Type:
|
||||
return AppendFloat64(b, *(*float64)(unsafe.Pointer(&n.bits))), nil
|
||||
case Float32Type:
|
||||
return AppendFloat32(b, float32(*(*float64)(unsafe.Pointer(&n.bits)))), nil
|
||||
default:
|
||||
panic("(*Number).typ is invalid")
|
||||
}
|
||||
}
|
1118
vendor/src/github.com/tinylib/msgp/msgp/read.go
vendored
Normal file
1118
vendor/src/github.com/tinylib/msgp/msgp/read.go
vendored
Normal file
File diff suppressed because it is too large
Load diff
1073
vendor/src/github.com/tinylib/msgp/msgp/read_bytes.go
vendored
Normal file
1073
vendor/src/github.com/tinylib/msgp/msgp/read_bytes.go
vendored
Normal file
File diff suppressed because it is too large
Load diff
38
vendor/src/github.com/tinylib/msgp/msgp/size.go
vendored
Normal file
38
vendor/src/github.com/tinylib/msgp/msgp/size.go
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
package msgp
|
||||
|
||||
// The sizes provided
|
||||
// are the worst-case
|
||||
// encoded sizes for
|
||||
// each type. For variable-
|
||||
// length types ([]byte, string),
|
||||
// the total encoded size is
|
||||
// the prefix size plus the
|
||||
// length of the object.
|
||||
const (
|
||||
Int64Size = 9
|
||||
IntSize = Int64Size
|
||||
UintSize = Int64Size
|
||||
Int8Size = 2
|
||||
Int16Size = 3
|
||||
Int32Size = 5
|
||||
Uint8Size = 2
|
||||
ByteSize = Uint8Size
|
||||
Uint16Size = 3
|
||||
Uint32Size = 5
|
||||
Uint64Size = Int64Size
|
||||
Float64Size = 9
|
||||
Float32Size = 5
|
||||
Complex64Size = 10
|
||||
Complex128Size = 18
|
||||
|
||||
TimeSize = 15
|
||||
BoolSize = 1
|
||||
NilSize = 1
|
||||
|
||||
MapHeaderSize = 5
|
||||
ArrayHeaderSize = 5
|
||||
|
||||
BytesPrefixSize = 5
|
||||
StringPrefixSize = 5
|
||||
ExtensionPrefixSize = 6
|
||||
)
|
768
vendor/src/github.com/tinylib/msgp/msgp/write.go
vendored
Normal file
768
vendor/src/github.com/tinylib/msgp/msgp/write.go
vendored
Normal file
|
@ -0,0 +1,768 @@
|
|||
package msgp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
func abs(i int64) int64 {
|
||||
if i < 0 {
|
||||
return -i
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
// Sizer is an interface implemented
|
||||
// by types that can estimate their
|
||||
// size when MessagePack encoded.
|
||||
// This interface is optional, but
|
||||
// encoding/marshaling implementations
|
||||
// may use this as a way to pre-allocate
|
||||
// memory for serialization.
|
||||
type Sizer interface {
|
||||
Msgsize() int
|
||||
}
|
||||
|
||||
var (
|
||||
// Nowhere is an io.Writer to nowhere
|
||||
Nowhere io.Writer = nwhere{}
|
||||
|
||||
btsType = reflect.TypeOf(([]byte)(nil))
|
||||
writerPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &Writer{buf: make([]byte, 2048)}
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func popWriter(w io.Writer) *Writer {
|
||||
wr := writerPool.Get().(*Writer)
|
||||
wr.Reset(w)
|
||||
return wr
|
||||
}
|
||||
|
||||
func pushWriter(wr *Writer) {
|
||||
wr.w = nil
|
||||
wr.wloc = 0
|
||||
writerPool.Put(wr)
|
||||
}
|
||||
|
||||
// freeW frees a writer for use
|
||||
// by other processes. It is not necessary
|
||||
// to call freeW on a writer. However, maintaining
|
||||
// a reference to a *Writer after calling freeW on
|
||||
// it will cause undefined behavior.
|
||||
func freeW(w *Writer) { pushWriter(w) }
|
||||
|
||||
// Require ensures that cap(old)-len(old) >= extra
|
||||
func Require(old []byte, extra int) []byte {
|
||||
if cap(old)-len(old) >= extra {
|
||||
return old
|
||||
}
|
||||
if len(old) == 0 {
|
||||
return make([]byte, 0, extra)
|
||||
}
|
||||
n := make([]byte, len(old), cap(old)-len(old)+extra)
|
||||
copy(n, old)
|
||||
return n
|
||||
}
|
||||
|
||||
// nowhere writer
|
||||
type nwhere struct{}
|
||||
|
||||
func (n nwhere) Write(p []byte) (int, error) { return len(p), nil }
|
||||
|
||||
// Marshaler is the interface implemented
|
||||
// by types that know how to marshal themselves
|
||||
// as MessagePack. MarshalMsg appends the marshalled
|
||||
// form of the object to the provided
|
||||
// byte slice, returning the extended
|
||||
// slice and any errors encountered.
|
||||
type Marshaler interface {
|
||||
MarshalMsg([]byte) ([]byte, error)
|
||||
}
|
||||
|
||||
// Encodable is the interface implemented
|
||||
// by types that know how to write themselves
|
||||
// as MessagePack using a *msgp.Writer.
|
||||
type Encodable interface {
|
||||
EncodeMsg(*Writer) error
|
||||
}
|
||||
|
||||
// Writer is a buffered writer
|
||||
// that can be used to write
|
||||
// MessagePack objects to an io.Writer.
|
||||
// You must call *Writer.Flush() in order
|
||||
// to flush all of the buffered data
|
||||
// to the underlying writer.
|
||||
type Writer struct {
|
||||
w io.Writer
|
||||
buf []byte
|
||||
wloc int
|
||||
}
|
||||
|
||||
// NewWriter returns a new *Writer.
|
||||
func NewWriter(w io.Writer) *Writer {
|
||||
if wr, ok := w.(*Writer); ok {
|
||||
return wr
|
||||
}
|
||||
return popWriter(w)
|
||||
}
|
||||
|
||||
// NewWriterSize returns a writer with a custom buffer size.
|
||||
func NewWriterSize(w io.Writer, sz int) *Writer {
|
||||
// we must be able to require() 18
|
||||
// contiguous bytes, so that is the
|
||||
// practical minimum buffer size
|
||||
if sz < 18 {
|
||||
sz = 18
|
||||
}
|
||||
|
||||
return &Writer{
|
||||
w: w,
|
||||
buf: make([]byte, sz),
|
||||
}
|
||||
}
|
||||
|
||||
// Encode encodes an Encodable to an io.Writer.
|
||||
func Encode(w io.Writer, e Encodable) error {
|
||||
wr := NewWriter(w)
|
||||
err := e.EncodeMsg(wr)
|
||||
if err == nil {
|
||||
err = wr.Flush()
|
||||
}
|
||||
freeW(wr)
|
||||
return err
|
||||
}
|
||||
|
||||
func (mw *Writer) flush() error {
|
||||
if mw.wloc == 0 {
|
||||
return nil
|
||||
}
|
||||
n, err := mw.w.Write(mw.buf[:mw.wloc])
|
||||
if err != nil {
|
||||
if n > 0 {
|
||||
mw.wloc = copy(mw.buf, mw.buf[n:mw.wloc])
|
||||
}
|
||||
return err
|
||||
}
|
||||
mw.wloc = 0
|
||||
return nil
|
||||
}
|
||||
|
||||
// Flush flushes all of the buffered
|
||||
// data to the underlying writer.
|
||||
func (mw *Writer) Flush() error { return mw.flush() }
|
||||
|
||||
// Buffered returns the number bytes in the write buffer
|
||||
func (mw *Writer) Buffered() int { return len(mw.buf) - mw.wloc }
|
||||
|
||||
func (mw *Writer) avail() int { return len(mw.buf) - mw.wloc }
|
||||
|
||||
func (mw *Writer) bufsize() int { return len(mw.buf) }
|
||||
|
||||
// NOTE: this should only be called with
|
||||
// a number that is guaranteed to be less than
|
||||
// len(mw.buf). typically, it is called with a constant.
|
||||
//
|
||||
// NOTE: this is a hot code path
|
||||
func (mw *Writer) require(n int) (int, error) {
|
||||
c := len(mw.buf)
|
||||
wl := mw.wloc
|
||||
if c-wl < n {
|
||||
if err := mw.flush(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
wl = mw.wloc
|
||||
}
|
||||
mw.wloc += n
|
||||
return wl, nil
|
||||
}
|
||||
|
||||
// push one byte onto the buffer
|
||||
//
|
||||
// NOTE: this is a hot code path
|
||||
func (mw *Writer) push(b byte) error {
|
||||
if mw.wloc == len(mw.buf) {
|
||||
if err := mw.flush(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
mw.buf[mw.wloc] = b
|
||||
mw.wloc++
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mw *Writer) prefix8(b byte, u uint8) error {
|
||||
const need = 2
|
||||
if len(mw.buf)-mw.wloc < need {
|
||||
if err := mw.flush(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
prefixu8(mw.buf[mw.wloc:], b, u)
|
||||
mw.wloc += need
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mw *Writer) prefix16(b byte, u uint16) error {
|
||||
const need = 3
|
||||
if len(mw.buf)-mw.wloc < need {
|
||||
if err := mw.flush(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
prefixu16(mw.buf[mw.wloc:], b, u)
|
||||
mw.wloc += need
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mw *Writer) prefix32(b byte, u uint32) error {
|
||||
const need = 5
|
||||
if len(mw.buf)-mw.wloc < need {
|
||||
if err := mw.flush(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
prefixu32(mw.buf[mw.wloc:], b, u)
|
||||
mw.wloc += need
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mw *Writer) prefix64(b byte, u uint64) error {
|
||||
const need = 9
|
||||
if len(mw.buf)-mw.wloc < need {
|
||||
if err := mw.flush(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
prefixu64(mw.buf[mw.wloc:], b, u)
|
||||
mw.wloc += need
|
||||
return nil
|
||||
}
|
||||
|
||||
// Write implements io.Writer, and writes
|
||||
// data directly to the buffer.
|
||||
func (mw *Writer) Write(p []byte) (int, error) {
|
||||
l := len(p)
|
||||
if mw.avail() < l {
|
||||
if err := mw.flush(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if l > len(mw.buf) {
|
||||
return mw.w.Write(p)
|
||||
}
|
||||
}
|
||||
mw.wloc += copy(mw.buf[mw.wloc:], p)
|
||||
return l, nil
|
||||
}
|
||||
|
||||
// implements io.WriteString
|
||||
func (mw *Writer) writeString(s string) error {
|
||||
l := len(s)
|
||||
if mw.avail() < l {
|
||||
if err := mw.flush(); err != nil {
|
||||
return err
|
||||
}
|
||||
if l > len(mw.buf) {
|
||||
_, err := io.WriteString(mw.w, s)
|
||||
return err
|
||||
}
|
||||
}
|
||||
mw.wloc += copy(mw.buf[mw.wloc:], s)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Reset changes the underlying writer used by the Writer
|
||||
func (mw *Writer) Reset(w io.Writer) {
|
||||
mw.buf = mw.buf[:cap(mw.buf)]
|
||||
mw.w = w
|
||||
mw.wloc = 0
|
||||
}
|
||||
|
||||
// WriteMapHeader writes a map header of the given
|
||||
// size to the writer
|
||||
func (mw *Writer) WriteMapHeader(sz uint32) error {
|
||||
switch {
|
||||
case sz < 16:
|
||||
return mw.push(wfixmap(uint8(sz)))
|
||||
case sz < math.MaxUint16:
|
||||
return mw.prefix16(mmap16, uint16(sz))
|
||||
default:
|
||||
return mw.prefix32(mmap32, sz)
|
||||
}
|
||||
}
|
||||
|
||||
// WriteArrayHeader writes an array header of the
|
||||
// given size to the writer
|
||||
func (mw *Writer) WriteArrayHeader(sz uint32) error {
|
||||
switch {
|
||||
case sz < 16:
|
||||
return mw.push(wfixarray(uint8(sz)))
|
||||
case sz < math.MaxUint16:
|
||||
return mw.prefix16(marray16, uint16(sz))
|
||||
default:
|
||||
return mw.prefix32(marray32, sz)
|
||||
}
|
||||
}
|
||||
|
||||
// WriteNil writes a nil byte to the buffer
|
||||
func (mw *Writer) WriteNil() error {
|
||||
return mw.push(mnil)
|
||||
}
|
||||
|
||||
// WriteFloat64 writes a float64 to the writer
|
||||
func (mw *Writer) WriteFloat64(f float64) error {
|
||||
return mw.prefix64(mfloat64, math.Float64bits(f))
|
||||
}
|
||||
|
||||
// WriteFloat32 writes a float32 to the writer
|
||||
func (mw *Writer) WriteFloat32(f float32) error {
|
||||
return mw.prefix32(mfloat32, math.Float32bits(f))
|
||||
}
|
||||
|
||||
// WriteInt64 writes an int64 to the writer
|
||||
func (mw *Writer) WriteInt64(i int64) error {
|
||||
a := abs(i)
|
||||
switch {
|
||||
case i < 0 && i > -32:
|
||||
return mw.push(wnfixint(int8(i)))
|
||||
case i >= 0 && i < 128:
|
||||
return mw.push(wfixint(uint8(i)))
|
||||
case a < math.MaxInt8:
|
||||
return mw.prefix8(mint8, uint8(i))
|
||||
case a < math.MaxInt16:
|
||||
return mw.prefix16(mint16, uint16(i))
|
||||
case a < math.MaxInt32:
|
||||
return mw.prefix32(mint32, uint32(i))
|
||||
default:
|
||||
return mw.prefix64(mint64, uint64(i))
|
||||
}
|
||||
}
|
||||
|
||||
// WriteInt8 writes an int8 to the writer
|
||||
func (mw *Writer) WriteInt8(i int8) error { return mw.WriteInt64(int64(i)) }
|
||||
|
||||
// WriteInt16 writes an int16 to the writer
|
||||
func (mw *Writer) WriteInt16(i int16) error { return mw.WriteInt64(int64(i)) }
|
||||
|
||||
// WriteInt32 writes an int32 to the writer
|
||||
func (mw *Writer) WriteInt32(i int32) error { return mw.WriteInt64(int64(i)) }
|
||||
|
||||
// WriteInt writes an int to the writer
|
||||
func (mw *Writer) WriteInt(i int) error { return mw.WriteInt64(int64(i)) }
|
||||
|
||||
// WriteUint64 writes a uint64 to the writer
|
||||
func (mw *Writer) WriteUint64(u uint64) error {
|
||||
switch {
|
||||
case u < (1 << 7):
|
||||
return mw.push(wfixint(uint8(u)))
|
||||
case u < math.MaxUint8:
|
||||
return mw.prefix8(muint8, uint8(u))
|
||||
case u < math.MaxUint16:
|
||||
return mw.prefix16(muint16, uint16(u))
|
||||
case u < math.MaxUint32:
|
||||
return mw.prefix32(muint32, uint32(u))
|
||||
default:
|
||||
return mw.prefix64(muint64, u)
|
||||
}
|
||||
}
|
||||
|
||||
// WriteByte is analagous to WriteUint8
|
||||
func (mw *Writer) WriteByte(u byte) error { return mw.WriteUint8(uint8(u)) }
|
||||
|
||||
// WriteUint8 writes a uint8 to the writer
|
||||
func (mw *Writer) WriteUint8(u uint8) error { return mw.WriteUint64(uint64(u)) }
|
||||
|
||||
// WriteUint16 writes a uint16 to the writer
|
||||
func (mw *Writer) WriteUint16(u uint16) error { return mw.WriteUint64(uint64(u)) }
|
||||
|
||||
// WriteUint32 writes a uint32 to the writer
|
||||
func (mw *Writer) WriteUint32(u uint32) error { return mw.WriteUint64(uint64(u)) }
|
||||
|
||||
// WriteUint writes a uint to the writer
|
||||
func (mw *Writer) WriteUint(u uint) error { return mw.WriteUint64(uint64(u)) }
|
||||
|
||||
// WriteBytes writes binary as 'bin' to the writer
|
||||
func (mw *Writer) WriteBytes(b []byte) error {
|
||||
sz := uint32(len(b))
|
||||
var err error
|
||||
switch {
|
||||
case sz < math.MaxUint8:
|
||||
err = mw.prefix8(mbin8, uint8(sz))
|
||||
case sz < math.MaxUint16:
|
||||
err = mw.prefix16(mbin16, uint16(sz))
|
||||
default:
|
||||
err = mw.prefix32(mbin32, sz)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = mw.Write(b)
|
||||
return err
|
||||
}
|
||||
|
||||
// WriteBool writes a bool to the writer
|
||||
func (mw *Writer) WriteBool(b bool) error {
|
||||
if b {
|
||||
return mw.push(mtrue)
|
||||
}
|
||||
return mw.push(mfalse)
|
||||
}
|
||||
|
||||
// WriteString writes a messagepack string to the writer.
|
||||
// (This is NOT an implementation of io.StringWriter)
|
||||
func (mw *Writer) WriteString(s string) error {
|
||||
sz := uint32(len(s))
|
||||
var err error
|
||||
switch {
|
||||
case sz < 32:
|
||||
err = mw.push(wfixstr(uint8(sz)))
|
||||
case sz < math.MaxUint8:
|
||||
err = mw.prefix8(mstr8, uint8(sz))
|
||||
case sz < math.MaxUint16:
|
||||
err = mw.prefix16(mstr16, uint16(sz))
|
||||
default:
|
||||
err = mw.prefix32(mstr32, sz)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return mw.writeString(s)
|
||||
}
|
||||
|
||||
// WriteComplex64 writes a complex64 to the writer
|
||||
func (mw *Writer) WriteComplex64(f complex64) error {
|
||||
o, err := mw.require(10)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mw.buf[o] = mfixext8
|
||||
mw.buf[o+1] = Complex64Extension
|
||||
big.PutUint32(mw.buf[o+2:], math.Float32bits(real(f)))
|
||||
big.PutUint32(mw.buf[o+6:], math.Float32bits(imag(f)))
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteComplex128 writes a complex128 to the writer
|
||||
func (mw *Writer) WriteComplex128(f complex128) error {
|
||||
o, err := mw.require(18)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mw.buf[o] = mfixext16
|
||||
mw.buf[o+1] = Complex128Extension
|
||||
big.PutUint64(mw.buf[o+2:], math.Float64bits(real(f)))
|
||||
big.PutUint64(mw.buf[o+10:], math.Float64bits(imag(f)))
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteMapStrStr writes a map[string]string to the writer
|
||||
func (mw *Writer) WriteMapStrStr(mp map[string]string) (err error) {
|
||||
err = mw.WriteMapHeader(uint32(len(mp)))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for key, val := range mp {
|
||||
err = mw.WriteString(key)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = mw.WriteString(val)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteMapStrIntf writes a map[string]interface to the writer
|
||||
func (mw *Writer) WriteMapStrIntf(mp map[string]interface{}) (err error) {
|
||||
err = mw.WriteMapHeader(uint32(len(mp)))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for key, val := range mp {
|
||||
err = mw.WriteString(key)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = mw.WriteIntf(val)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// WriteTime writes a time.Time object to the wire.
|
||||
//
|
||||
// Time is encoded as Unix time, which means that
|
||||
// location (time zone) data is removed from the object.
|
||||
// The encoded object itself is 12 bytes: 8 bytes for
|
||||
// a big-endian 64-bit integer denoting seconds
|
||||
// elapsed since "zero" Unix time, followed by 4 bytes
|
||||
// for a big-endian 32-bit signed integer denoting
|
||||
// the nanosecond offset of the time. This encoding
|
||||
// is intended to ease portability accross languages.
|
||||
// (Note that this is *not* the standard time.Time
|
||||
// binary encoding, because its implementation relies
|
||||
// heavily on the internal representation used by the
|
||||
// time package.)
|
||||
func (mw *Writer) WriteTime(t time.Time) error {
|
||||
t = t.UTC()
|
||||
o, err := mw.require(15)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mw.buf[o] = mext8
|
||||
mw.buf[o+1] = 12
|
||||
mw.buf[o+2] = TimeExtension
|
||||
putUnix(mw.buf[o+3:], t.Unix(), int32(t.Nanosecond()))
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteIntf writes the concrete type of 'v'.
|
||||
// WriteIntf will error if 'v' is not one of the following:
|
||||
// - A bool, float, string, []byte, int, uint, or complex
|
||||
// - A map of supported types (with string keys)
|
||||
// - An array or slice of supported types
|
||||
// - A pointer to a supported type
|
||||
// - A type that satisfies the msgp.Encodable interface
|
||||
// - A type that satisfies the msgp.Extension interface
|
||||
func (mw *Writer) WriteIntf(v interface{}) error {
|
||||
if v == nil {
|
||||
return mw.WriteNil()
|
||||
}
|
||||
switch v := v.(type) {
|
||||
|
||||
// preferred interfaces
|
||||
|
||||
case Encodable:
|
||||
return v.EncodeMsg(mw)
|
||||
case Extension:
|
||||
return mw.WriteExtension(v)
|
||||
|
||||
// concrete types
|
||||
|
||||
case bool:
|
||||
return mw.WriteBool(v)
|
||||
case float32:
|
||||
return mw.WriteFloat32(v)
|
||||
case float64:
|
||||
return mw.WriteFloat64(v)
|
||||
case complex64:
|
||||
return mw.WriteComplex64(v)
|
||||
case complex128:
|
||||
return mw.WriteComplex128(v)
|
||||
case uint8:
|
||||
return mw.WriteUint8(v)
|
||||
case uint16:
|
||||
return mw.WriteUint16(v)
|
||||
case uint32:
|
||||
return mw.WriteUint32(v)
|
||||
case uint64:
|
||||
return mw.WriteUint64(v)
|
||||
case uint:
|
||||
return mw.WriteUint(v)
|
||||
case int8:
|
||||
return mw.WriteInt8(v)
|
||||
case int16:
|
||||
return mw.WriteInt16(v)
|
||||
case int32:
|
||||
return mw.WriteInt32(v)
|
||||
case int64:
|
||||
return mw.WriteInt64(v)
|
||||
case int:
|
||||
return mw.WriteInt(v)
|
||||
case string:
|
||||
return mw.WriteString(v)
|
||||
case []byte:
|
||||
return mw.WriteBytes(v)
|
||||
case map[string]string:
|
||||
return mw.WriteMapStrStr(v)
|
||||
case map[string]interface{}:
|
||||
return mw.WriteMapStrIntf(v)
|
||||
case time.Time:
|
||||
return mw.WriteTime(v)
|
||||
}
|
||||
|
||||
val := reflect.ValueOf(v)
|
||||
if !isSupported(val.Kind()) || !val.IsValid() {
|
||||
return fmt.Errorf("msgp: type %s not supported", val)
|
||||
}
|
||||
|
||||
switch val.Kind() {
|
||||
case reflect.Ptr:
|
||||
if val.IsNil() {
|
||||
return mw.WriteNil()
|
||||
}
|
||||
return mw.WriteIntf(val.Elem().Interface())
|
||||
case reflect.Slice:
|
||||
return mw.writeSlice(val)
|
||||
case reflect.Map:
|
||||
return mw.writeMap(val)
|
||||
}
|
||||
return &ErrUnsupportedType{val.Type()}
|
||||
}
|
||||
|
||||
func (mw *Writer) writeMap(v reflect.Value) (err error) {
|
||||
if v.Elem().Kind() != reflect.String {
|
||||
return errors.New("msgp: map keys must be strings")
|
||||
}
|
||||
ks := v.MapKeys()
|
||||
err = mw.WriteMapHeader(uint32(len(ks)))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, key := range ks {
|
||||
val := v.MapIndex(key)
|
||||
err = mw.WriteString(key.String())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = mw.WriteIntf(val.Interface())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (mw *Writer) writeSlice(v reflect.Value) (err error) {
|
||||
// is []byte
|
||||
if v.Type().ConvertibleTo(btsType) {
|
||||
return mw.WriteBytes(v.Bytes())
|
||||
}
|
||||
|
||||
sz := uint32(v.Len())
|
||||
err = mw.WriteArrayHeader(sz)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for i := uint32(0); i < sz; i++ {
|
||||
err = mw.WriteIntf(v.Index(int(i)).Interface())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (mw *Writer) writeStruct(v reflect.Value) error {
|
||||
if enc, ok := v.Interface().(Encodable); ok {
|
||||
return enc.EncodeMsg(mw)
|
||||
}
|
||||
return fmt.Errorf("msgp: unsupported type: %s", v.Type())
|
||||
}
|
||||
|
||||
func (mw *Writer) writeVal(v reflect.Value) error {
|
||||
if !isSupported(v.Kind()) {
|
||||
return fmt.Errorf("msgp: msgp/enc: type %q not supported", v.Type())
|
||||
}
|
||||
|
||||
// shortcut for nil values
|
||||
if v.IsNil() {
|
||||
return mw.WriteNil()
|
||||
}
|
||||
switch v.Kind() {
|
||||
case reflect.Bool:
|
||||
return mw.WriteBool(v.Bool())
|
||||
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return mw.WriteFloat64(v.Float())
|
||||
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
return mw.WriteComplex128(v.Complex())
|
||||
|
||||
case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int8:
|
||||
return mw.WriteInt64(v.Int())
|
||||
|
||||
case reflect.Interface, reflect.Ptr:
|
||||
if v.IsNil() {
|
||||
mw.WriteNil()
|
||||
}
|
||||
return mw.writeVal(v.Elem())
|
||||
|
||||
case reflect.Map:
|
||||
return mw.writeMap(v)
|
||||
|
||||
case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint8:
|
||||
return mw.WriteUint64(v.Uint())
|
||||
|
||||
case reflect.String:
|
||||
return mw.WriteString(v.String())
|
||||
|
||||
case reflect.Slice, reflect.Array:
|
||||
return mw.writeSlice(v)
|
||||
|
||||
case reflect.Struct:
|
||||
return mw.writeStruct(v)
|
||||
|
||||
}
|
||||
return fmt.Errorf("msgp: msgp/enc: type %q not supported", v.Type())
|
||||
}
|
||||
|
||||
// is the reflect.Kind encodable?
|
||||
func isSupported(k reflect.Kind) bool {
|
||||
switch k {
|
||||
case reflect.Func, reflect.Chan, reflect.Invalid, reflect.UnsafePointer:
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// GuessSize guesses the size of the underlying
|
||||
// value of 'i'. If the underlying value is not
|
||||
// a simple builtin (or []byte), GuessSize defaults
|
||||
// to 512.
|
||||
func GuessSize(i interface{}) int {
|
||||
if i == nil {
|
||||
return NilSize
|
||||
}
|
||||
|
||||
switch i := i.(type) {
|
||||
case Sizer:
|
||||
return i.Msgsize()
|
||||
case Extension:
|
||||
return ExtensionPrefixSize + i.Len()
|
||||
case float64:
|
||||
return Float64Size
|
||||
case float32:
|
||||
return Float32Size
|
||||
case uint8, uint16, uint32, uint64, uint:
|
||||
return UintSize
|
||||
case int8, int16, int32, int64, int:
|
||||
return IntSize
|
||||
case []byte:
|
||||
return BytesPrefixSize + len(i)
|
||||
case string:
|
||||
return StringPrefixSize + len(i)
|
||||
case complex64:
|
||||
return Complex64Size
|
||||
case complex128:
|
||||
return Complex128Size
|
||||
case bool:
|
||||
return BoolSize
|
||||
case map[string]interface{}:
|
||||
s := MapHeaderSize
|
||||
for key, val := range i {
|
||||
s += StringPrefixSize + len(key) + GuessSize(val)
|
||||
}
|
||||
return s
|
||||
case map[string]string:
|
||||
s := MapHeaderSize
|
||||
for key, val := range i {
|
||||
s += 2*StringPrefixSize + len(key) + len(val)
|
||||
}
|
||||
return s
|
||||
default:
|
||||
return 512
|
||||
}
|
||||
}
|
369
vendor/src/github.com/tinylib/msgp/msgp/write_bytes.go
vendored
Normal file
369
vendor/src/github.com/tinylib/msgp/msgp/write_bytes.go
vendored
Normal file
|
@ -0,0 +1,369 @@
|
|||
package msgp
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ensure 'sz' extra bytes in 'b' btw len(b) and cap(b)
|
||||
func ensure(b []byte, sz int) ([]byte, int) {
|
||||
l := len(b)
|
||||
c := cap(b)
|
||||
if c-l < sz {
|
||||
o := make([]byte, (2*c)+sz) // exponential growth
|
||||
n := copy(o, b)
|
||||
return o[:n+sz], n
|
||||
}
|
||||
return b[:l+sz], l
|
||||
}
|
||||
|
||||
// AppendMapHeader appends a map header with the
|
||||
// given size to the slice
|
||||
func AppendMapHeader(b []byte, sz uint32) []byte {
|
||||
switch {
|
||||
case sz < 16:
|
||||
return append(b, wfixmap(uint8(sz)))
|
||||
|
||||
case sz < math.MaxUint16:
|
||||
o, n := ensure(b, 3)
|
||||
prefixu16(o[n:], mmap16, uint16(sz))
|
||||
return o
|
||||
|
||||
default:
|
||||
o, n := ensure(b, 5)
|
||||
prefixu32(o[n:], mmap32, sz)
|
||||
return o
|
||||
}
|
||||
}
|
||||
|
||||
// AppendArrayHeader appends an array header with
|
||||
// the given size to the slice
|
||||
func AppendArrayHeader(b []byte, sz uint32) []byte {
|
||||
switch {
|
||||
case sz < 16:
|
||||
return append(b, wfixarray(uint8(sz)))
|
||||
|
||||
case sz < math.MaxUint16:
|
||||
o, n := ensure(b, 3)
|
||||
prefixu16(o[n:], marray16, uint16(sz))
|
||||
return o
|
||||
|
||||
default:
|
||||
o, n := ensure(b, 5)
|
||||
prefixu32(o[n:], marray32, sz)
|
||||
return o
|
||||
}
|
||||
}
|
||||
|
||||
// AppendNil appends a 'nil' byte to the slice
|
||||
func AppendNil(b []byte) []byte { return append(b, mnil) }
|
||||
|
||||
// AppendFloat64 appends a float64 to the slice
|
||||
func AppendFloat64(b []byte, f float64) []byte {
|
||||
o, n := ensure(b, Float64Size)
|
||||
prefixu64(o[n:], mfloat64, math.Float64bits(f))
|
||||
return o
|
||||
}
|
||||
|
||||
// AppendFloat32 appends a float32 to the slice
|
||||
func AppendFloat32(b []byte, f float32) []byte {
|
||||
o, n := ensure(b, Float32Size)
|
||||
prefixu32(o[n:], mfloat32, math.Float32bits(f))
|
||||
return o
|
||||
}
|
||||
|
||||
// AppendInt64 appends an int64 to the slice
|
||||
func AppendInt64(b []byte, i int64) []byte {
|
||||
a := abs(i)
|
||||
switch {
|
||||
case i < 0 && i > -32:
|
||||
return append(b, wnfixint(int8(i)))
|
||||
|
||||
case i >= 0 && i < 128:
|
||||
return append(b, wfixint(uint8(i)))
|
||||
|
||||
case a < math.MaxInt8:
|
||||
o, n := ensure(b, 2)
|
||||
putMint8(o[n:], int8(i))
|
||||
return o
|
||||
|
||||
case a < math.MaxInt16:
|
||||
o, n := ensure(b, 3)
|
||||
putMint16(o[n:], int16(i))
|
||||
return o
|
||||
|
||||
case a < math.MaxInt32:
|
||||
o, n := ensure(b, 5)
|
||||
putMint32(o[n:], int32(i))
|
||||
return o
|
||||
|
||||
default:
|
||||
o, n := ensure(b, 9)
|
||||
putMint64(o[n:], i)
|
||||
return o
|
||||
}
|
||||
}
|
||||
|
||||
// AppendInt appends an int to the slice
|
||||
func AppendInt(b []byte, i int) []byte { return AppendInt64(b, int64(i)) }
|
||||
|
||||
// AppendInt8 appends an int8 to the slice
|
||||
func AppendInt8(b []byte, i int8) []byte { return AppendInt64(b, int64(i)) }
|
||||
|
||||
// AppendInt16 appends an int16 to the slice
|
||||
func AppendInt16(b []byte, i int16) []byte { return AppendInt64(b, int64(i)) }
|
||||
|
||||
// AppendInt32 appends an int32 to the slice
|
||||
func AppendInt32(b []byte, i int32) []byte { return AppendInt64(b, int64(i)) }
|
||||
|
||||
// AppendUint64 appends a uint64 to the slice
|
||||
func AppendUint64(b []byte, u uint64) []byte {
|
||||
switch {
|
||||
case u < (1 << 7):
|
||||
return append(b, wfixint(uint8(u)))
|
||||
|
||||
case u < math.MaxUint8:
|
||||
o, n := ensure(b, 2)
|
||||
putMuint8(o[n:], uint8(u))
|
||||
return o
|
||||
|
||||
case u < math.MaxUint16:
|
||||
o, n := ensure(b, 3)
|
||||
putMuint16(o[n:], uint16(u))
|
||||
return o
|
||||
|
||||
case u < math.MaxUint32:
|
||||
o, n := ensure(b, 5)
|
||||
putMuint32(o[n:], uint32(u))
|
||||
return o
|
||||
|
||||
default:
|
||||
o, n := ensure(b, 9)
|
||||
putMuint64(o[n:], u)
|
||||
return o
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// AppendUint appends a uint to the slice
|
||||
func AppendUint(b []byte, u uint) []byte { return AppendUint64(b, uint64(u)) }
|
||||
|
||||
// AppendUint8 appends a uint8 to the slice
|
||||
func AppendUint8(b []byte, u uint8) []byte { return AppendUint64(b, uint64(u)) }
|
||||
|
||||
// AppendByte is analagous to AppendUint8
|
||||
func AppendByte(b []byte, u byte) []byte { return AppendUint8(b, uint8(u)) }
|
||||
|
||||
// AppendUint16 appends a uint16 to the slice
|
||||
func AppendUint16(b []byte, u uint16) []byte { return AppendUint64(b, uint64(u)) }
|
||||
|
||||
// AppendUint32 appends a uint32 to the slice
|
||||
func AppendUint32(b []byte, u uint32) []byte { return AppendUint64(b, uint64(u)) }
|
||||
|
||||
// AppendBytes appends bytes to the slice as MessagePack 'bin' data
|
||||
func AppendBytes(b []byte, bts []byte) []byte {
|
||||
sz := len(bts)
|
||||
var o []byte
|
||||
var n int
|
||||
switch {
|
||||
case sz < math.MaxUint8:
|
||||
o, n = ensure(b, 2+sz)
|
||||
prefixu8(o[n:], mbin8, uint8(sz))
|
||||
n += 2
|
||||
case sz < math.MaxUint16:
|
||||
o, n = ensure(b, 3+sz)
|
||||
prefixu16(o[n:], mbin16, uint16(sz))
|
||||
n += 3
|
||||
default:
|
||||
o, n = ensure(b, 5+sz)
|
||||
prefixu32(o[n:], mbin32, uint32(sz))
|
||||
n += 5
|
||||
}
|
||||
return o[:n+copy(o[n:], bts)]
|
||||
}
|
||||
|
||||
// AppendBool appends a bool to the slice
|
||||
func AppendBool(b []byte, t bool) []byte {
|
||||
if t {
|
||||
return append(b, mtrue)
|
||||
}
|
||||
return append(b, mfalse)
|
||||
}
|
||||
|
||||
// AppendString appends a string as a MessagePack 'str' to the slice
|
||||
func AppendString(b []byte, s string) []byte {
|
||||
sz := len(s)
|
||||
var n int
|
||||
var o []byte
|
||||
switch {
|
||||
case sz < 32:
|
||||
o, n = ensure(b, 1+sz)
|
||||
o[n] = wfixstr(uint8(sz))
|
||||
n++
|
||||
case sz < math.MaxUint8:
|
||||
o, n = ensure(b, 2+sz)
|
||||
prefixu8(o[n:], mstr8, uint8(sz))
|
||||
n += 2
|
||||
case sz < math.MaxUint16:
|
||||
o, n = ensure(b, 3+sz)
|
||||
prefixu16(o[n:], mstr16, uint16(sz))
|
||||
n += 3
|
||||
default:
|
||||
o, n = ensure(b, 5+sz)
|
||||
prefixu32(o[n:], mstr32, uint32(sz))
|
||||
n += 5
|
||||
}
|
||||
return o[:n+copy(o[n:], s)]
|
||||
}
|
||||
|
||||
// AppendComplex64 appends a complex64 to the slice as a MessagePack extension
|
||||
func AppendComplex64(b []byte, c complex64) []byte {
|
||||
o, n := ensure(b, Complex64Size)
|
||||
o[n] = mfixext8
|
||||
o[n+1] = Complex64Extension
|
||||
big.PutUint32(o[n+2:], math.Float32bits(real(c)))
|
||||
big.PutUint32(o[n+6:], math.Float32bits(imag(c)))
|
||||
return o
|
||||
}
|
||||
|
||||
// AppendComplex128 appends a complex128 to the slice as a MessagePack extension
|
||||
func AppendComplex128(b []byte, c complex128) []byte {
|
||||
o, n := ensure(b, Complex128Size)
|
||||
o[n] = mfixext16
|
||||
o[n+1] = Complex128Extension
|
||||
big.PutUint64(o[n+2:], math.Float64bits(real(c)))
|
||||
big.PutUint64(o[n+10:], math.Float64bits(imag(c)))
|
||||
return o
|
||||
}
|
||||
|
||||
// AppendTime appends a time.Time to the slice as a MessagePack extension
|
||||
func AppendTime(b []byte, t time.Time) []byte {
|
||||
o, n := ensure(b, TimeSize)
|
||||
t = t.UTC()
|
||||
o[n] = mext8
|
||||
o[n+1] = 12
|
||||
o[n+2] = TimeExtension
|
||||
putUnix(o[n+3:], t.Unix(), int32(t.Nanosecond()))
|
||||
return o
|
||||
}
|
||||
|
||||
// AppendMapStrStr appends a map[string]string to the slice
|
||||
// as a MessagePack map with 'str'-type keys and values
|
||||
func AppendMapStrStr(b []byte, m map[string]string) []byte {
|
||||
sz := uint32(len(m))
|
||||
b = AppendMapHeader(b, sz)
|
||||
for key, val := range m {
|
||||
b = AppendString(b, key)
|
||||
b = AppendString(b, val)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// AppendMapStrIntf appends a map[string]interface{} to the slice
|
||||
// as a MessagePack map with 'str'-type keys.
|
||||
func AppendMapStrIntf(b []byte, m map[string]interface{}) ([]byte, error) {
|
||||
sz := uint32(len(m))
|
||||
b = AppendMapHeader(b, sz)
|
||||
var err error
|
||||
for key, val := range m {
|
||||
b = AppendString(b, key)
|
||||
b, err = AppendIntf(b, val)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// AppendIntf appends the concrete type of 'i' to the
|
||||
// provided []byte. 'i' must be one of the following:
|
||||
// - 'nil'
|
||||
// - A bool, float, string, []byte, int, uint, or complex
|
||||
// - A map[string]interface{} or map[string]string
|
||||
// - A []T, where T is another supported type
|
||||
// - A *T, where T is another supported type
|
||||
// - A type that satisfieds the msgp.Marshaler interface
|
||||
// - A type that satisfies the msgp.Extension interface
|
||||
func AppendIntf(b []byte, i interface{}) ([]byte, error) {
|
||||
if i == nil {
|
||||
return AppendNil(b), nil
|
||||
}
|
||||
|
||||
// all the concrete types
|
||||
// for which we have methods
|
||||
switch i := i.(type) {
|
||||
case Marshaler:
|
||||
return i.MarshalMsg(b)
|
||||
case Extension:
|
||||
return AppendExtension(b, i)
|
||||
case bool:
|
||||
return AppendBool(b, i), nil
|
||||
case float32:
|
||||
return AppendFloat32(b, i), nil
|
||||
case float64:
|
||||
return AppendFloat64(b, i), nil
|
||||
case complex64:
|
||||
return AppendComplex64(b, i), nil
|
||||
case complex128:
|
||||
return AppendComplex128(b, i), nil
|
||||
case string:
|
||||
return AppendString(b, i), nil
|
||||
case []byte:
|
||||
return AppendBytes(b, i), nil
|
||||
case int8:
|
||||
return AppendInt8(b, i), nil
|
||||
case int16:
|
||||
return AppendInt16(b, i), nil
|
||||
case int32:
|
||||
return AppendInt32(b, i), nil
|
||||
case int64:
|
||||
return AppendInt64(b, i), nil
|
||||
case int:
|
||||
return AppendInt64(b, int64(i)), nil
|
||||
case uint:
|
||||
return AppendUint64(b, uint64(i)), nil
|
||||
case uint8:
|
||||
return AppendUint8(b, i), nil
|
||||
case uint16:
|
||||
return AppendUint16(b, i), nil
|
||||
case uint32:
|
||||
return AppendUint32(b, i), nil
|
||||
case uint64:
|
||||
return AppendUint64(b, i), nil
|
||||
case time.Time:
|
||||
return AppendTime(b, i), nil
|
||||
case map[string]interface{}:
|
||||
return AppendMapStrIntf(b, i)
|
||||
case map[string]string:
|
||||
return AppendMapStrStr(b, i), nil
|
||||
case []interface{}:
|
||||
b = AppendArrayHeader(b, uint32(len(i)))
|
||||
var err error
|
||||
for _, k := range i {
|
||||
b, err = AppendIntf(b, k)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
var err error
|
||||
v := reflect.ValueOf(i)
|
||||
switch v.Kind() {
|
||||
case reflect.Array, reflect.Slice:
|
||||
l := v.Len()
|
||||
b = AppendArrayHeader(b, uint32(l))
|
||||
for i := 0; i < l; i++ {
|
||||
b, err = AppendIntf(b, v.Index(i).Interface())
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
}
|
||||
return b, nil
|
||||
|
||||
default:
|
||||
return b, &ErrUnsupportedType{T: v.Type()}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue