Update mattermost library (#2152)

* Update mattermost library

* Fix linting
This commit is contained in:
Wim
2024-05-24 23:08:09 +02:00
committed by GitHub
parent 65d78e38af
commit d16645c952
1003 changed files with 89451 additions and 114025 deletions

View File

@@ -1,4 +1,5 @@
// +build linux,!appengine
//go:build linux && !appengine && !tinygo
// +build linux,!appengine,!tinygo
package msgp

View File

@@ -1,4 +1,5 @@
// +build !linux appengine
//go:build (!linux && !tinygo && !windows) || appengine
// +build !linux,!tinygo,!windows appengine
package msgp

View File

@@ -5,16 +5,19 @@
// 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.
// - 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)
//
// msgp.Encode(io.Writer, msgp.Encodable)
//
// and
// msgp.Decode(io.Reader, msgp.Decodable)
//
// msgp.Decode(io.Reader, msgp.Decodable)
//
// There are also methods for converting MessagePack to JSON without
// an explicit de-serialization step.
@@ -23,11 +26,13 @@
// 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
const (
last4 = 0x0f
first4 = 0xf0
last5 = 0x1f
first3 = 0xe0
last7 = 0x7f
)
func isfixint(b byte) bool {
return b>>7 == 0

View File

@@ -1,72 +1,105 @@
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 calcBytespec(v byte) bytespec {
// single byte values
switch v {
func init() {
// set up fixed fields
case mnil:
return bytespec{size: 1, extra: constsize, typ: NilType}
case mfalse:
return bytespec{size: 1, extra: constsize, typ: BoolType}
case mtrue:
return bytespec{size: 1, extra: constsize, typ: BoolType}
case mbin8:
return bytespec{size: 2, extra: extra8, typ: BinType}
case mbin16:
return bytespec{size: 3, extra: extra16, typ: BinType}
case mbin32:
return bytespec{size: 5, extra: extra32, typ: BinType}
case mext8:
return bytespec{size: 3, extra: extra8, typ: ExtensionType}
case mext16:
return bytespec{size: 4, extra: extra16, typ: ExtensionType}
case mext32:
return bytespec{size: 6, extra: extra32, typ: ExtensionType}
case mfloat32:
return bytespec{size: 5, extra: constsize, typ: Float32Type}
case mfloat64:
return bytespec{size: 9, extra: constsize, typ: Float64Type}
case muint8:
return bytespec{size: 2, extra: constsize, typ: UintType}
case muint16:
return bytespec{size: 3, extra: constsize, typ: UintType}
case muint32:
return bytespec{size: 5, extra: constsize, typ: UintType}
case muint64:
return bytespec{size: 9, extra: constsize, typ: UintType}
case mint8:
return bytespec{size: 2, extra: constsize, typ: IntType}
case mint16:
return bytespec{size: 3, extra: constsize, typ: IntType}
case mint32:
return bytespec{size: 5, extra: constsize, typ: IntType}
case mint64:
return bytespec{size: 9, extra: constsize, typ: IntType}
case mfixext1:
return bytespec{size: 3, extra: constsize, typ: ExtensionType}
case mfixext2:
return bytespec{size: 4, extra: constsize, typ: ExtensionType}
case mfixext4:
return bytespec{size: 6, extra: constsize, typ: ExtensionType}
case mfixext8:
return bytespec{size: 10, extra: constsize, typ: ExtensionType}
case mfixext16:
return bytespec{size: 18, extra: constsize, typ: ExtensionType}
case mstr8:
return bytespec{size: 2, extra: extra8, typ: StrType}
case mstr16:
return bytespec{size: 3, extra: extra16, typ: StrType}
case mstr32:
return bytespec{size: 5, extra: extra32, typ: StrType}
case marray16:
return bytespec{size: 3, extra: array16v, typ: ArrayType}
case marray32:
return bytespec{size: 5, extra: array32v, typ: ArrayType}
case mmap16:
return bytespec{size: 3, extra: map16v, typ: MapType}
case mmap32:
return bytespec{size: 5, extra: map32v, typ: MapType}
}
switch {
// fixint
for i := mfixint; i < 0x80; i++ {
sizes[i] = bytespec{size: 1, extra: constsize, typ: IntType}
}
case v >= mfixint && v < 0x80:
return 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}
}
// fixstr gets constsize, since the prefix yields the size
case v >= mfixstr && v < 0xc0:
return bytespec{size: 1 + rfixstr(v), extra: constsize, typ: StrType}
// fixmap
for i := mfixmap; i < 0x90; i++ {
sizes[i] = bytespec{size: 1, extra: varmode(2 * rfixmap(i)), typ: MapType}
}
case v >= mfixmap && v < 0x90:
return bytespec{size: 1, extra: varmode(2 * rfixmap(v)), typ: MapType}
// fixarray
for i := mfixarray; i < 0xa0; i++ {
sizes[i] = bytespec{size: 1, extra: varmode(rfixarray(i)), typ: ArrayType}
case v >= mfixarray && v < 0xa0:
return bytespec{size: 1, extra: varmode(rfixarray(v)), typ: ArrayType}
// nfixint
case v >= mnfixint && uint16(v) < 0x100:
return bytespec{size: 1, extra: constsize, typ: IntType}
}
// 0xC1 is unused per the spec and falls through to here,
// everything else is covered above
return bytespec{}
}
func getType(v byte) Type {
return getBytespec(v).typ
}
// a valid bytespsec has
@@ -85,15 +118,11 @@ 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
extra8 varmode = -1 // has uint8(p[1]) extra bytes
extra16 varmode = -2 // has be16(p[1:]) extra bytes
extra32 varmode = -3 // has be32(p[1:]) extra bytes
map16v varmode = -4 // use map16
map32v varmode = -5 // use map32
array16v varmode = -6 // use array16
array32v varmode = -7 // use array32
)
func getType(v byte) Type {
return sizes[v].typ
}

21
vendor/github.com/tinylib/msgp/msgp/elsize_default.go generated vendored Normal file
View File

@@ -0,0 +1,21 @@
//go:build !tinygo
// +build !tinygo
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
func init() {
for i := 0; i < 256; i++ {
sizes[i] = calcBytespec(byte(i))
}
}
// getBytespec gets inlined to a simple array index
func getBytespec(v byte) bytespec {
return sizes[v]
}

13
vendor/github.com/tinylib/msgp/msgp/elsize_tinygo.go generated vendored Normal file
View File

@@ -0,0 +1,13 @@
//go:build tinygo
// +build tinygo
package msgp
// for tinygo, getBytespec just calls calcBytespec
// a simple/slow function with a switch statement -
// doesn't require any heap alloc, moves the space
// requirements into code instad of ram
func getBytespec(v byte) bytespec {
return calcBytespec(v)
}

View File

@@ -1,8 +1,8 @@
package msgp
import (
"fmt"
"reflect"
"strconv"
)
const resumableDefault = false
@@ -69,7 +69,6 @@ func Resumable(e error) bool {
//
// ErrShortBytes is not wrapped with any context due to backward compatibility
// issues with the public API.
//
func WrapError(err error, ctx ...interface{}) error {
switch e := err.(type) {
case errShort:
@@ -81,18 +80,6 @@ func WrapError(err error, ctx ...interface{}) error {
}
}
// ctxString converts the incoming interface{} slice into a single string.
func ctxString(ctx []interface{}) string {
out := ""
for idx, cv := range ctx {
if idx > 0 {
out += "/"
}
out += fmt.Sprintf("%v", cv)
}
return out
}
func addCtx(ctx, add string) string {
if ctx != "" {
return add + "/" + ctx
@@ -110,7 +97,7 @@ type errWrapped struct {
func (e errWrapped) Error() string {
if e.ctx != "" {
return fmt.Sprintf("%s at %s", e.cause, e.ctx)
return e.cause.Error() + " at " + e.ctx
} else {
return e.cause.Error()
}
@@ -158,7 +145,7 @@ type ArrayError struct {
// Error implements the error interface
func (a ArrayError) Error() string {
out := fmt.Sprintf("msgp: wanted array of size %d; got %d", a.Wanted, a.Got)
out := "msgp: wanted array of size " + strconv.Itoa(int(a.Wanted)) + "; got " + strconv.Itoa(int(a.Got))
if a.ctx != "" {
out += " at " + a.ctx
}
@@ -181,7 +168,7 @@ type IntOverflow struct {
// Error implements the error interface
func (i IntOverflow) Error() string {
str := fmt.Sprintf("msgp: %d overflows int%d", i.Value, i.FailedBitsize)
str := "msgp: " + strconv.FormatInt(i.Value, 10) + " overflows int" + strconv.Itoa(i.FailedBitsize)
if i.ctx != "" {
str += " at " + i.ctx
}
@@ -204,7 +191,7 @@ type UintOverflow struct {
// Error implements the error interface
func (u UintOverflow) Error() string {
str := fmt.Sprintf("msgp: %d overflows uint%d", u.Value, u.FailedBitsize)
str := "msgp: " + strconv.FormatUint(u.Value, 10) + " overflows uint" + strconv.Itoa(u.FailedBitsize)
if u.ctx != "" {
str += " at " + u.ctx
}
@@ -226,7 +213,7 @@ type UintBelowZero struct {
// Error implements the error interface
func (u UintBelowZero) Error() string {
str := fmt.Sprintf("msgp: attempted to cast int %d to unsigned", u.Value)
str := "msgp: attempted to cast int " + strconv.FormatInt(u.Value, 10) + " to unsigned"
if u.ctx != "" {
str += " at " + u.ctx
}
@@ -253,7 +240,7 @@ type TypeError struct {
// Error implements the error interface
func (t TypeError) Error() string {
out := fmt.Sprintf("msgp: attempted to decode type %q with method for %q", t.Encoded, t.Method)
out := "msgp: attempted to decode type " + quoteStr(t.Encoded.String()) + " with method for " + quoteStr(t.Method.String())
if t.ctx != "" {
out += " at " + t.ctx
}
@@ -269,7 +256,7 @@ func (t TypeError) withContext(ctx string) error { t.ctx = addCtx(t.ctx, ctx); r
// TypeError depending on whether or not
// the prefix is recognized
func badPrefix(want Type, lead byte) error {
t := sizes[lead].typ
t := getType(lead)
if t == InvalidType {
return InvalidPrefixError(lead)
}
@@ -283,7 +270,7 @@ type InvalidPrefixError byte
// Error implements the error interface
func (i InvalidPrefixError) Error() string {
return fmt.Sprintf("msgp: unrecognized type prefix 0x%x", byte(i))
return "msgp: unrecognized type prefix 0x" + strconv.FormatInt(int64(i), 16)
}
// Resumable returns 'false' for InvalidPrefixErrors
@@ -300,7 +287,7 @@ type ErrUnsupportedType struct {
// Error implements error
func (e *ErrUnsupportedType) Error() string {
out := fmt.Sprintf("msgp: type %q not supported", e.T)
out := "msgp: type " + quoteStr(e.T.String()) + " not supported"
if e.ctx != "" {
out += " at " + e.ctx
}
@@ -315,3 +302,58 @@ func (e *ErrUnsupportedType) withContext(ctx string) error {
o.ctx = addCtx(o.ctx, ctx)
return &o
}
// simpleQuoteStr is a simplified version of strconv.Quote for TinyGo,
// which takes up a lot less code space by escaping all non-ASCII
// (UTF-8) bytes with \x. Saves about 4k of code size
// (unicode tables, needed for IsPrint(), are big).
// It lives in errors.go just so we can test it in errors_test.go
func simpleQuoteStr(s string) string {
const (
lowerhex = "0123456789abcdef"
)
sb := make([]byte, 0, len(s)+2)
sb = append(sb, `"`...)
l: // loop through string bytes (not UTF-8 characters)
for i := 0; i < len(s); i++ {
b := s[i]
// specific escape chars
switch b {
case '\\':
sb = append(sb, `\\`...)
case '"':
sb = append(sb, `\"`...)
case '\a':
sb = append(sb, `\a`...)
case '\b':
sb = append(sb, `\b`...)
case '\f':
sb = append(sb, `\f`...)
case '\n':
sb = append(sb, `\n`...)
case '\r':
sb = append(sb, `\r`...)
case '\t':
sb = append(sb, `\t`...)
case '\v':
sb = append(sb, `\v`...)
default:
// no escaping needed (printable ASCII)
if b >= 0x20 && b <= 0x7E {
sb = append(sb, b)
continue l
}
// anything else is \x
sb = append(sb, `\x`...)
sb = append(sb, lowerhex[byte(b)>>4])
sb = append(sb, lowerhex[byte(b)&0xF])
continue l
}
}
sb = append(sb, `"`...)
return string(sb)
}

25
vendor/github.com/tinylib/msgp/msgp/errors_default.go generated vendored Normal file
View File

@@ -0,0 +1,25 @@
//go:build !tinygo
// +build !tinygo
package msgp
import (
"fmt"
"strconv"
)
// ctxString converts the incoming interface{} slice into a single string.
func ctxString(ctx []interface{}) string {
out := ""
for idx, cv := range ctx {
if idx > 0 {
out += "/"
}
out += fmt.Sprintf("%v", cv)
}
return out
}
func quoteStr(s string) string {
return strconv.Quote(s)
}

42
vendor/github.com/tinylib/msgp/msgp/errors_tinygo.go generated vendored Normal file
View File

@@ -0,0 +1,42 @@
//go:build tinygo
// +build tinygo
package msgp
import (
"reflect"
)
// ctxString converts the incoming interface{} slice into a single string,
// without using fmt under tinygo
func ctxString(ctx []interface{}) string {
out := ""
for idx, cv := range ctx {
if idx > 0 {
out += "/"
}
out += ifToStr(cv)
}
return out
}
type stringer interface {
String() string
}
func ifToStr(i interface{}) string {
switch v := i.(type) {
case stringer:
return v.String()
case error:
return v.Error()
case string:
return v
default:
return reflect.ValueOf(i).String()
}
}
func quoteStr(s string) string {
return simpleQuoteStr(s)
}

View File

@@ -1,8 +1,9 @@
package msgp
import (
"fmt"
"errors"
"math"
"strconv"
)
const (
@@ -30,7 +31,7 @@ var extensionReg = make(map[int8]func() Extension)
//
// For example, if you wanted to register a user-defined struct:
//
// msgp.RegisterExtension(10, func() msgp.Extension { &MyExtension{} })
// 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
@@ -38,10 +39,10 @@ var extensionReg = make(map[int8]func() Extension)
func RegisterExtension(typ int8, f func() Extension) {
switch typ {
case Complex64Extension, Complex128Extension, TimeExtension:
panic(fmt.Sprint("msgp: forbidden extension type:", typ))
panic(errors.New("msgp: forbidden extension type: " + strconv.Itoa(int(typ))))
}
if _, ok := extensionReg[typ]; ok {
panic(fmt.Sprint("msgp: RegisterExtension() called with typ", typ, "more than once"))
panic(errors.New("msgp: RegisterExtension() called with typ " + strconv.Itoa(int(typ)) + " more than once"))
}
extensionReg[typ] = f
}
@@ -56,7 +57,7 @@ type ExtensionTypeError struct {
// 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)
return "msgp: error decoding extension: wanted type " + strconv.Itoa(int(e.Want)) + "; got type " + strconv.Itoa(int(e.Got))
}
// Resumable returns 'true' for ExtensionTypeErrors
@@ -120,11 +121,8 @@ func (r *RawExtension) UnmarshalBinary(b []byte) error {
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 {
func (mw *Writer) writeExtensionHeader(length int, extType int8) error {
switch length {
case 0:
o, err := mw.require(3)
if err != nil {
@@ -132,75 +130,88 @@ func (mw *Writer) WriteExtension(e Extension) error {
}
mw.buf[o] = mext8
mw.buf[o+1] = 0
mw.buf[o+2] = byte(e.ExtensionType())
mw.buf[o+2] = byte(extType)
case 1:
o, err := mw.require(2)
if err != nil {
return err
}
mw.buf[o] = mfixext1
mw.buf[o+1] = byte(e.ExtensionType())
mw.buf[o+1] = byte(extType)
case 2:
o, err := mw.require(2)
if err != nil {
return err
}
mw.buf[o] = mfixext2
mw.buf[o+1] = byte(e.ExtensionType())
mw.buf[o+1] = byte(extType)
case 4:
o, err := mw.require(2)
if err != nil {
return err
}
mw.buf[o] = mfixext4
mw.buf[o+1] = byte(e.ExtensionType())
mw.buf[o+1] = byte(extType)
case 8:
o, err := mw.require(2)
if err != nil {
return err
}
mw.buf[o] = mfixext8
mw.buf[o+1] = byte(e.ExtensionType())
mw.buf[o+1] = byte(extType)
case 16:
o, err := mw.require(2)
if err != nil {
return err
}
mw.buf[o] = mfixext16
mw.buf[o+1] = byte(e.ExtensionType())
mw.buf[o+1] = byte(extType)
default:
switch {
case l < math.MaxUint8:
case length < 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:
mw.buf[o+1] = byte(uint8(length))
mw.buf[o+2] = byte(extType)
case length < 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())
big.PutUint16(mw.buf[o+1:], uint16(length))
mw.buf[o+3] = byte(extType)
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())
big.PutUint32(mw.buf[o+1:], uint32(length))
mw.buf[o+5] = byte(extType)
}
}
return nil
}
// WriteExtension writes an extension type to the writer
func (mw *Writer) WriteExtension(e Extension) error {
length := e.Len()
err := mw.writeExtensionHeader(length, e.ExtensionType())
if err != nil {
return err
}
// 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 length <= mw.bufsize() {
o, err := mw.require(length)
if err != nil {
return err
}
@@ -213,42 +224,56 @@ func (mw *Writer) WriteExtension(e Extension) error {
if err != nil {
return err
}
buf := make([]byte, l)
buf := make([]byte, length)
err = e.MarshalBinaryTo(buf)
if err != nil {
return err
}
mw.buf = buf
mw.wloc = l
mw.wloc = length
return nil
}
// WriteExtensionRaw writes an extension type to the writer
func (mw *Writer) WriteExtensionRaw(extType int8, payload []byte) error {
if err := mw.writeExtensionHeader(len(payload), extType); err != nil {
return err
}
// instead of using mw.Write(), we'll copy the data through the internal
// buffer, otherwise the payload would be moved to the heap
// (meaning we can use stack-allocated buffers with zero allocations)
for len(payload) > 0 {
chunkSize := mw.avail()
if chunkSize == 0 {
if err := mw.flush(); err != nil {
return err
}
chunkSize = mw.avail()
}
if chunkSize > len(payload) {
chunkSize = len(payload)
}
mw.wloc += copy(mw.buf[mw.wloc:], payload[:chunkSize])
payload = payload[chunkSize:]
}
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
_, _, extType, err := m.peekExtensionHeader()
return extType, err
}
// 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]]
spec := getBytespec(b[0])
size := spec.size
if spec.typ != ExtensionType {
return 0, badPrefix(ExtensionType, b[0])
@@ -267,93 +292,40 @@ func peekExtension(b []byte) (int8, error) {
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) {
func (m *Reader) peekExtensionHeader() (offset int, length int, extType int8, err error) {
var p []byte
p, err = m.R.Peek(2)
if err != nil {
return
}
offset = 2
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)
}
extType = int8(p[1])
length = 1
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)
}
extType = int8(p[1])
length = 2
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)
}
extType = int8(p[1])
length = 4
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)
}
extType = int8(p[1])
length = 8
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)
}
extType = int8(p[1])
length = 16
return
case mext8:
@@ -361,53 +333,79 @@ func (m *Reader) ReadExtension(e Extension) (err error) {
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
offset = 3
extType = int8(p[2])
length = int(uint8(p[1]))
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
offset = 4
extType = int8(p[3])
length = int(big.Uint16(p[1:]))
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
offset = 6
extType = int8(p[5])
length = int(big.Uint32(p[1:]))
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
}
// 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) error {
offset, length, extType, err := m.peekExtensionHeader()
if err != nil {
return err
}
if expectedType := e.ExtensionType(); extType != expectedType {
return errExt(extType, expectedType)
}
p, err := m.R.Peek(offset + length)
if err != nil {
return err
}
err = e.UnmarshalBinary(p[offset:])
if err == nil {
// consume the peeked bytes
_, err = m.R.Skip(offset + length)
}
return err
}
// ReadExtensionRaw reads the next object from the reader
// as an extension. The returned slice is only
// valid until the next *Reader method call.
func (m *Reader) ReadExtensionRaw() (int8, []byte, error) {
offset, length, extType, err := m.peekExtensionHeader()
if err != nil {
return 0, nil, err
}
payload, err := m.R.Next(offset + length)
if err != nil {
return 0, nil, err
}
return extType, payload[offset:], nil
}
// AppendExtension appends a MessagePack extension to the provided slice
func AppendExtension(b []byte, e Extension) ([]byte, error) {
l := e.Len()

View File

@@ -1,5 +1,7 @@
//go:build (linux || darwin || dragonfly || freebsd || netbsd || openbsd) && !appengine && !tinygo
// +build linux darwin dragonfly freebsd netbsd openbsd
// +build !appengine
// +build !tinygo
package msgp
@@ -20,7 +22,6 @@ import (
// is only efficient for large files; small
// files are best read and written using
// the ordinary streaming interfaces.
//
func ReadFile(dst Unmarshaler, file *os.File) error {
stat, err := file.Stat()
if err != nil {

View File

@@ -1,4 +1,5 @@
// +build windows appengine
//go:build windows || appengine || tinygo
// +build windows appengine tinygo
package msgp

View File

@@ -12,7 +12,6 @@ import (
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){
@@ -223,27 +222,6 @@ func rwUintBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error)
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

View File

@@ -29,7 +29,6 @@ type Number struct {
// 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

View File

@@ -1,3 +1,4 @@
//go:build purego || appengine
// +build purego appengine
package msgp

View File

@@ -36,6 +36,7 @@ const (
IntType
UintType
NilType
DurationType
ExtensionType
// pseudo-types provided
@@ -262,7 +263,7 @@ func getNextSize(r *fwd.Reader) (uintptr, uintptr, error) {
return 0, 0, err
}
lead := b[0]
spec := &sizes[lead]
spec := getBytespec(lead)
size, mode := spec.size, spec.extra
if size == 0 {
return 0, 0, InvalidPrefixError(lead)
@@ -394,7 +395,7 @@ func (m *Reader) ReadMapKey(scratch []byte) ([]byte, error) {
return out, nil
}
// MapKeyPtr returns a []byte pointing to the contents
// ReadMapKeyPtr returns a []byte pointing to the contents
// of a valid map key. The key cannot be empty, and it
// must be shorter than the total buffer size of the
// *Reader. Additionally, the returned slice is only
@@ -559,6 +560,12 @@ func (m *Reader) ReadBool() (b bool, err error) {
return
}
// ReadDuration reads a time.Duration from the reader
func (m *Reader) ReadDuration() (d time.Duration, err error) {
i, err := m.ReadInt64()
return time.Duration(i), err
}
// ReadInt64 reads an int64 from the reader
func (m *Reader) ReadInt64() (i int64, err error) {
var p []byte
@@ -1302,6 +1309,10 @@ func (m *Reader) ReadIntf() (i interface{}, err error) {
i, err = m.ReadTime()
return
case DurationType:
i, err = m.ReadDuration()
return
case ExtensionType:
var t int8
t, err = m.peekExtensionType()

View File

@@ -12,12 +12,12 @@ var big = binary.BigEndian
// NextType returns the type of the next
// object in the slice. If the length
// of the input is zero, it returns
// InvalidType.
// [InvalidType].
func NextType(b []byte) Type {
if len(b) == 0 {
return InvalidType
}
spec := sizes[b[0]]
spec := getBytespec(b[0])
t := spec.typ
if t == ExtensionType && len(b) > int(spec.size) {
var tp int8
@@ -55,7 +55,7 @@ func IsNil(b []byte) bool {
// data without interpreting its contents.
type Raw []byte
// MarshalMsg implements msgp.Marshaler.
// MarshalMsg implements [Marshaler].
// It appends the raw contents of 'raw'
// to the provided byte slice. If 'raw'
// is 0 bytes, 'nil' will be appended instead.
@@ -69,7 +69,7 @@ func (r Raw) MarshalMsg(b []byte) ([]byte, error) {
return o, nil
}
// UnmarshalMsg implements msgp.Unmarshaler.
// UnmarshalMsg implements [Unmarshaler].
// It sets the contents of *Raw to be the next
// object in the provided byte slice.
func (r *Raw) UnmarshalMsg(b []byte) ([]byte, error) {
@@ -91,7 +91,7 @@ func (r *Raw) UnmarshalMsg(b []byte) ([]byte, error) {
return out, nil
}
// EncodeMsg implements msgp.Encodable.
// EncodeMsg implements [Encodable].
// It writes the raw bytes to the writer.
// If r is empty, it writes 'nil' instead.
func (r Raw) EncodeMsg(w *Writer) error {
@@ -102,7 +102,7 @@ func (r Raw) EncodeMsg(w *Writer) error {
return err
}
// DecodeMsg implements msgp.Decodable.
// DecodeMsg implements [Decodable].
// It sets the value of *Raw to be the
// next object on the wire.
func (r *Raw) DecodeMsg(f *Reader) error {
@@ -114,7 +114,7 @@ func (r *Raw) DecodeMsg(f *Reader) error {
return err
}
// Msgsize implements msgp.Sizer
// Msgsize implements [Sizer].
func (r Raw) Msgsize() int {
l := len(r)
if l == 0 {
@@ -144,7 +144,7 @@ func appendNext(f *Reader, d *[]byte) error {
return nil
}
// MarshalJSON implements json.Marshaler
// MarshalJSON implements [json.Marshaler].
func (r *Raw) MarshalJSON() ([]byte, error) {
var buf bytes.Buffer
_, err := UnmarshalAsJSON(&buf, []byte(*r))
@@ -153,9 +153,11 @@ func (r *Raw) MarshalJSON() ([]byte, error) {
// ReadMapHeaderBytes reads a map header size
// from 'b' and returns the remaining bytes.
//
// Possible errors:
// - ErrShortBytes (too few bytes)
// - TypeError{} (not a map)
//
// - [ErrShortBytes] (too few bytes)
// - [TypeError] (not a map)
func ReadMapHeaderBytes(b []byte) (sz uint32, o []byte, err error) {
l := len(b)
if l < 1 {
@@ -197,9 +199,11 @@ func ReadMapHeaderBytes(b []byte) (sz uint32, o []byte, err error) {
// ReadMapKeyZC attempts to read a map key
// from 'b' and returns the key bytes and the remaining bytes
//
// Possible errors:
// - ErrShortBytes (too few bytes)
// - TypeError{} (not a str or bin)
//
// - [ErrShortBytes] (too few bytes)
// - [TypeError] (not a str or bin)
func ReadMapKeyZC(b []byte) ([]byte, []byte, error) {
o, x, err := ReadStringZC(b)
if err != nil {
@@ -214,9 +218,11 @@ func ReadMapKeyZC(b []byte) ([]byte, []byte, error) {
// ReadArrayHeaderBytes attempts to read
// the array header size off of 'b' and return
// the size and remaining bytes.
//
// Possible errors:
// - ErrShortBytes (too few bytes)
// - TypeError{} (not an array)
//
// - [ErrShortBytes] (too few bytes)
// - [TypeError] (not an array)
func ReadArrayHeaderBytes(b []byte) (sz uint32, o []byte, err error) {
if len(b) < 1 {
return 0, nil, ErrShortBytes
@@ -255,9 +261,11 @@ func ReadArrayHeaderBytes(b []byte) (sz uint32, o []byte, err error) {
// ReadBytesHeader reads the 'bin' header size
// off of 'b' and returns the size and remaining bytes.
//
// Possible errors:
// - ErrShortBytes (too few bytes)
// - TypeError{} (not a bin object)
//
// - [ErrShortBytes] (too few bytes)
// - [TypeError] (not a bin object)
func ReadBytesHeader(b []byte) (sz uint32, o []byte, err error) {
if len(b) < 1 {
return 0, nil, ErrShortBytes
@@ -295,10 +303,12 @@ func ReadBytesHeader(b []byte) (sz uint32, o []byte, err error) {
// ReadNilBytes tries to read a "nil" byte
// off of 'b' and return the remaining bytes.
//
// Possible errors:
// - ErrShortBytes (too few bytes)
// - TypeError{} (not a 'nil')
// - InvalidPrefixError
//
// - [ErrShortBytes] (too few bytes)
// - [TypeError] (not a 'nil')
// - [InvalidPrefixError]
func ReadNilBytes(b []byte) ([]byte, error) {
if len(b) < 1 {
return nil, ErrShortBytes
@@ -311,9 +321,11 @@ func ReadNilBytes(b []byte) ([]byte, error) {
// ReadFloat64Bytes tries to read a float64
// from 'b' and return the value and the remaining bytes.
//
// Possible errors:
// - ErrShortBytes (too few bytes)
// - TypeError{} (not a float64)
//
// - [ErrShortBytes] (too few bytes)
// - [TypeError] (not a float64)
func ReadFloat64Bytes(b []byte) (f float64, o []byte, err error) {
if len(b) < 9 {
if len(b) >= 5 && b[0] == mfloat32 {
@@ -344,9 +356,11 @@ func ReadFloat64Bytes(b []byte) (f float64, o []byte, err error) {
// ReadFloat32Bytes tries to read a float64
// from 'b' and return the value and the remaining bytes.
//
// Possible errors:
// - ErrShortBytes (too few bytes)
// - TypeError{} (not a float32)
//
// - [ErrShortBytes] (too few bytes)
// - [TypeError] (not a float32)
func ReadFloat32Bytes(b []byte) (f float32, o []byte, err error) {
if len(b) < 5 {
err = ErrShortBytes
@@ -365,9 +379,11 @@ func ReadFloat32Bytes(b []byte) (f float32, o []byte, err error) {
// ReadBoolBytes tries to read a float64
// from 'b' and return the value and the remaining bytes.
//
// Possible errors:
// - ErrShortBytes (too few bytes)
// - TypeError{} (not a bool)
//
// - [ErrShortBytes] (too few bytes)
// - [TypeError] (not a bool)
func ReadBoolBytes(b []byte) (bool, []byte, error) {
if len(b) < 1 {
return false, b, ErrShortBytes
@@ -382,11 +398,25 @@ func ReadBoolBytes(b []byte) (bool, []byte, error) {
}
}
// ReadDurationBytes tries to read a time.Duration
// from 'b' and return the value and the remaining bytes.
//
// Possible errors:
//
// - [ErrShortBytes] (too few bytes)
// - TypeError (not a int)
func ReadDurationBytes(b []byte) (d time.Duration, o []byte, err error) {
i, o, err := ReadInt64Bytes(b)
return time.Duration(i), o, err
}
// ReadInt64Bytes tries to read an int64
// from 'b' and return the value and the remaining bytes.
//
// Possible errors:
// - ErrShortBytes (too few bytes)
// - TypeError (not a int)
//
// - [ErrShortBytes] (too few bytes)
// - [TypeError] (not a int)
func ReadInt64Bytes(b []byte) (i int64, o []byte, err error) {
l := len(b)
if l < 1 {
@@ -491,10 +521,12 @@ func ReadInt64Bytes(b []byte) (i int64, o []byte, err error) {
// ReadInt32Bytes tries to read an int32
// from 'b' and return the value and the remaining bytes.
//
// Possible errors:
// - ErrShortBytes (too few bytes)
// - TypeError{} (not a int)
// - IntOverflow{} (value doesn't fit in int32)
//
// - [ErrShortBytes] (too few bytes)
// - [TypeError] (not a int)
// - [IntOverflow] (value doesn't fit in int32)
func ReadInt32Bytes(b []byte) (int32, []byte, error) {
i, o, err := ReadInt64Bytes(b)
if i > math.MaxInt32 || i < math.MinInt32 {
@@ -505,10 +537,12 @@ func ReadInt32Bytes(b []byte) (int32, []byte, error) {
// ReadInt16Bytes tries to read an int16
// from 'b' and return the value and the remaining bytes.
//
// Possible errors:
// - ErrShortBytes (too few bytes)
// - TypeError{} (not a int)
// - IntOverflow{} (value doesn't fit in int16)
//
// - [ErrShortBytes] (too few bytes)
// - [TypeError] (not a int)
// - [IntOverflow] (value doesn't fit in int16)
func ReadInt16Bytes(b []byte) (int16, []byte, error) {
i, o, err := ReadInt64Bytes(b)
if i > math.MaxInt16 || i < math.MinInt16 {
@@ -519,10 +553,12 @@ func ReadInt16Bytes(b []byte) (int16, []byte, error) {
// ReadInt8Bytes tries to read an int16
// from 'b' and return the value and the remaining bytes.
//
// Possible errors:
// - ErrShortBytes (too few bytes)
// - TypeError{} (not a int)
// - IntOverflow{} (value doesn't fit in int8)
//
// - [ErrShortBytes] (too few bytes)
// - [TypeError] (not a int)
// - [IntOverflow] (value doesn't fit in int8)
func ReadInt8Bytes(b []byte) (int8, []byte, error) {
i, o, err := ReadInt64Bytes(b)
if i > math.MaxInt8 || i < math.MinInt8 {
@@ -533,10 +569,12 @@ func ReadInt8Bytes(b []byte) (int8, []byte, error) {
// ReadIntBytes tries to read an int
// from 'b' and return the value and the remaining bytes.
//
// Possible errors:
// - ErrShortBytes (too few bytes)
// - TypeError{} (not a int)
// - IntOverflow{} (value doesn't fit in int; 32-bit platforms only)
//
// - [ErrShortBytes] (too few bytes)
// - [TypeError] (not a int)
// - [IntOverflow] (value doesn't fit in int; 32-bit platforms only)
func ReadIntBytes(b []byte) (int, []byte, error) {
if smallint {
i, b, err := ReadInt32Bytes(b)
@@ -548,9 +586,11 @@ func ReadIntBytes(b []byte) (int, []byte, error) {
// ReadUint64Bytes tries to read a uint64
// from 'b' and return the value and the remaining bytes.
//
// Possible errors:
// - ErrShortBytes (too few bytes)
// - TypeError{} (not a uint)
//
// - [ErrShortBytes] (too few bytes)
// - [TypeError] (not a uint)
func ReadUint64Bytes(b []byte) (u uint64, o []byte, err error) {
l := len(b)
if l < 1 {
@@ -669,10 +709,12 @@ func ReadUint64Bytes(b []byte) (u uint64, o []byte, err error) {
// ReadUint32Bytes tries to read a uint32
// from 'b' and return the value and the remaining bytes.
//
// Possible errors:
// - ErrShortBytes (too few bytes)
// - TypeError{} (not a uint)
// - UintOverflow{} (value too large for uint32)
//
// - [ErrShortBytes] (too few bytes)
// - [TypeError] (not a uint)
// - [UintOverflow] (value too large for uint32)
func ReadUint32Bytes(b []byte) (uint32, []byte, error) {
v, o, err := ReadUint64Bytes(b)
if v > math.MaxUint32 {
@@ -683,10 +725,12 @@ func ReadUint32Bytes(b []byte) (uint32, []byte, error) {
// ReadUint16Bytes tries to read a uint16
// from 'b' and return the value and the remaining bytes.
//
// Possible errors:
// - ErrShortBytes (too few bytes)
// - TypeError{} (not a uint)
// - UintOverflow{} (value too large for uint16)
//
// - [ErrShortBytes] (too few bytes)
// - [TypeError] (not a uint)
// - [UintOverflow] (value too large for uint16)
func ReadUint16Bytes(b []byte) (uint16, []byte, error) {
v, o, err := ReadUint64Bytes(b)
if v > math.MaxUint16 {
@@ -697,10 +741,12 @@ func ReadUint16Bytes(b []byte) (uint16, []byte, error) {
// ReadUint8Bytes tries to read a uint8
// from 'b' and return the value and the remaining bytes.
//
// Possible errors:
// - ErrShortBytes (too few bytes)
// - TypeError{} (not a uint)
// - UintOverflow{} (value too large for uint8)
//
// - [ErrShortBytes] (too few bytes)
// - [TypeError] (not a uint)
// - [UintOverflow] (value too large for uint8)
func ReadUint8Bytes(b []byte) (uint8, []byte, error) {
v, o, err := ReadUint64Bytes(b)
if v > math.MaxUint8 {
@@ -711,10 +757,12 @@ func ReadUint8Bytes(b []byte) (uint8, []byte, error) {
// ReadUintBytes tries to read a uint
// from 'b' and return the value and the remaining bytes.
//
// Possible errors:
// - ErrShortBytes (too few bytes)
// - TypeError{} (not a uint)
// - UintOverflow{} (value too large for uint; 32-bit platforms only)
//
// - [ErrShortBytes] (too few bytes)
// - [TypeError] (not a uint)
// - [UintOverflow] (value too large for uint; 32-bit platforms only)
func ReadUintBytes(b []byte) (uint, []byte, error) {
if smallint {
u, b, err := ReadUint32Bytes(b)
@@ -732,9 +780,11 @@ func ReadByteBytes(b []byte) (byte, []byte, error) {
// ReadBytesBytes reads a 'bin' object
// from 'b' and returns its vaue and
// the remaining bytes in 'b'.
//
// Possible errors:
// - ErrShortBytes (too few bytes)
// - TypeError{} (not a 'bin' object)
//
// - [ErrShortBytes] (too few bytes)
// - [TypeError] (not a 'bin' object)
func ReadBytesBytes(b []byte, scratch []byte) (v []byte, o []byte, err error) {
return readBytesBytes(b, scratch, false)
}
@@ -803,9 +853,11 @@ func readBytesBytes(b []byte, scratch []byte, zc bool) (v []byte, o []byte, err
// ReadBytesZC extracts the messagepack-encoded
// binary field without copying. The returned []byte
// points to the same memory as the input slice.
//
// Possible errors:
// - ErrShortBytes (b not long enough)
// - TypeError{} (object not 'bin')
//
// - [ErrShortBytes] (b not long enough)
// - [TypeError] (object not 'bin')
func ReadBytesZC(b []byte) (v []byte, o []byte, err error) {
return readBytesBytes(b, nil, true)
}
@@ -863,9 +915,11 @@ func ReadExactBytes(b []byte, into []byte) (o []byte, err error) {
// ReadStringZC reads a messagepack string field
// without copying. The returned []byte points
// to the same memory as the input slice.
//
// Possible errors:
// - ErrShortBytes (b not long enough)
// - TypeError{} (object not 'str')
//
// - [ErrShortBytes] (b not long enough)
// - [TypeError] (object not 'str')
func ReadStringZC(b []byte) (v []byte, o []byte, err error) {
l := len(b)
if l < 1 {
@@ -923,10 +977,12 @@ func ReadStringZC(b []byte) (v []byte, o []byte, err error) {
// ReadStringBytes reads a 'str' object
// from 'b' and returns its value and the
// remaining bytes in 'b'.
//
// Possible errors:
// - ErrShortBytes (b not long enough)
// - TypeError{} (not 'str' type)
// - InvalidPrefixError
//
// - [ErrShortBytes] (b not long enough)
// - [TypeError] (not 'str' type)
// - [InvalidPrefixError]
func ReadStringBytes(b []byte) (string, []byte, error) {
v, o, err := ReadStringZC(b)
return string(v), o, err
@@ -936,11 +992,13 @@ func ReadStringBytes(b []byte) (string, []byte, error) {
// into a slice of bytes. 'v' is the value of
// the 'str' object, which may reside in memory
// pointed to by 'scratch.' 'o' is the remaining bytes
// in 'b.''
// in 'b'.
//
// Possible errors:
// - ErrShortBytes (b not long enough)
// - TypeError{} (not 'str' type)
// - InvalidPrefixError (unknown type marker)
//
// - [ErrShortBytes] (b not long enough)
// - [TypeError] (not 'str' type)
// - [InvalidPrefixError] (unknown type marker)
func ReadStringAsBytes(b []byte, scratch []byte) (v []byte, o []byte, err error) {
var tmp []byte
tmp, o, err = ReadStringZC(b)
@@ -951,11 +1009,13 @@ func ReadStringAsBytes(b []byte, scratch []byte) (v []byte, o []byte, err error)
// ReadComplex128Bytes reads a complex128
// extension object from 'b' and returns the
// remaining bytes.
//
// Possible errors:
// - ErrShortBytes (not enough bytes in 'b')
// - TypeError{} (object not a complex128)
// - InvalidPrefixError
// - ExtensionTypeError{} (object an extension of the correct size, but not a complex128)
//
// - [ErrShortBytes] (not enough bytes in 'b')
// - [TypeError] (object not a complex128)
// - [InvalidPrefixError]
// - [ExtensionTypeError] (object an extension of the correct size, but not a complex128)
func ReadComplex128Bytes(b []byte) (c complex128, o []byte, err error) {
if len(b) < 18 {
err = ErrShortBytes
@@ -978,10 +1038,12 @@ func ReadComplex128Bytes(b []byte) (c complex128, o []byte, err error) {
// ReadComplex64Bytes reads a complex64
// extension object from 'b' and returns the
// remaining bytes.
//
// Possible errors:
// - ErrShortBytes (not enough bytes in 'b')
// - TypeError{} (object not a complex64)
// - ExtensionTypeError{} (object an extension of the correct size, but not a complex64)
//
// - [ErrShortBytes] (not enough bytes in 'b')
// - [TypeError] (object not a complex64)
// - [ExtensionTypeError] (object an extension of the correct size, but not a complex64)
func ReadComplex64Bytes(b []byte) (c complex64, o []byte, err error) {
if len(b) < 10 {
err = ErrShortBytes
@@ -1004,10 +1066,12 @@ func ReadComplex64Bytes(b []byte) (c complex64, o []byte, err error) {
// ReadTimeBytes reads a time.Time
// extension object from 'b' and returns the
// remaining bytes.
//
// Possible errors:
// - ErrShortBytes (not enough bytes in 'b')
// - TypeError{} (object not a complex64)
// - ExtensionTypeError{} (object an extension of the correct size, but not a time.Time)
//
// - [ErrShortBytes] (not enough bytes in 'b')
// - [TypeError] (object not a complex64)
// - [ExtensionTypeError] (object an extension of the correct size, but not a time.Time)
func ReadTimeBytes(b []byte) (t time.Time, o []byte, err error) {
if len(b) < 15 {
err = ErrShortBytes
@@ -1176,9 +1240,11 @@ func ReadIntfBytes(b []byte) (i interface{}, o []byte, err error) {
// returns the remaining bytes. If the object
// is a map or array, all of its elements
// will be skipped.
// Possible Errors:
// - ErrShortBytes (not enough bytes in b)
// - InvalidPrefixError (bad encoding)
//
// Possible errors:
//
// - [ErrShortBytes] (not enough bytes in b)
// - [InvalidPrefixError] (bad encoding)
func Skip(b []byte) ([]byte, error) {
sz, asz, err := getSize(b)
if err != nil {
@@ -1205,7 +1271,7 @@ func getSize(b []byte) (uintptr, uintptr, error) {
return 0, 0, ErrShortBytes
}
lead := b[0]
spec := &sizes[lead] // get type information
spec := getBytespec(lead) // get type information
size, mode := spec.size, spec.extra
if size == 0 {
return 0, 0, InvalidPrefixError(lead)

View File

@@ -25,9 +25,10 @@ const (
Complex64Size = 10
Complex128Size = 18
TimeSize = 15
BoolSize = 1
NilSize = 1
DurationSize = Int64Size
TimeSize = 15
BoolSize = 1
NilSize = 1
MapHeaderSize = 5
ArrayHeaderSize = 5

View File

@@ -1,3 +1,4 @@
//go:build !purego && !appengine
// +build !purego,!appengine
package msgp

View File

@@ -2,7 +2,6 @@ package msgp
import (
"errors"
"fmt"
"io"
"math"
"reflect"
@@ -357,6 +356,11 @@ func (mw *Writer) WriteFloat32(f float32) error {
return mw.prefix32(mfloat32, math.Float32bits(f))
}
// WriteDuration writes a time.Duration to the writer
func (mw *Writer) WriteDuration(d time.Duration) error {
return mw.WriteInt64(int64(d))
}
// WriteInt64 writes an int64 to the writer
func (mw *Writer) WriteInt64(i int64) error {
if i >= 0 {
@@ -622,12 +626,12 @@ func (mw *Writer) WriteTime(t time.Time) error {
// 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
// - 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()
@@ -683,11 +687,13 @@ func (mw *Writer) WriteIntf(v interface{}) error {
return mw.WriteMapStrIntf(v)
case time.Time:
return mw.WriteTime(v)
case time.Duration:
return mw.WriteDuration(v)
}
val := reflect.ValueOf(v)
if !isSupported(val.Kind()) || !val.IsValid() {
return fmt.Errorf("msgp: type %s not supported", val)
return errors.New("msgp: type " + val.String() + " not supported")
}
switch val.Kind() {
@@ -747,60 +753,6 @@ func (mw *Writer) writeSlice(v reflect.Value) (err error) {
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 {

View File

@@ -73,6 +73,11 @@ func AppendFloat32(b []byte, f float32) []byte {
return o
}
// AppendDuration appends a time.Duration to the slice
func AppendDuration(b []byte, d time.Duration) []byte {
return AppendInt64(b, int64(d))
}
// AppendInt64 appends an int64 to the slice
func AppendInt64(b []byte, i int64) []byte {
if i >= 0 {
@@ -335,13 +340,13 @@ func AppendMapStrIntf(b []byte, m map[string]interface{}) ([]byte, error) {
// 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
// - '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