123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- package msgp
- import (
- "fmt"
- "reflect"
- )
- const resumableDefault = false
- 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
- }
- // contextError allows msgp Error instances to be enhanced with additional
- // context about their origin.
- type contextError interface {
- Error
- // withContext must not modify the error instance - it must clone and
- // return a new error with the context added.
- withContext(ctx string) error
- }
- // Cause returns the underlying cause of an error that has been wrapped
- // with additional context.
- func Cause(e error) error {
- out := e
- if e, ok := e.(errWrapped); ok && e.cause != nil {
- out = e.cause
- }
- return out
- }
- // Resumable returns whether or not the error means that the stream of data is
- // malformed and the information is unrecoverable.
- func Resumable(e error) bool {
- if e, ok := e.(Error); ok {
- return e.Resumable()
- }
- return resumableDefault
- }
- // WrapError wraps an error with additional context that allows the part of the
- // serialized type that caused the problem to be identified. Underlying errors
- // can be retrieved using Cause()
- //
- // The input error is not modified - a new error should be returned.
- //
- // 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:
- return e
- case contextError:
- return e.withContext(ctxString(ctx))
- default:
- return errWrapped{cause: err, ctx: ctxString(ctx)}
- }
- }
- // 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
- } else {
- return add
- }
- }
- // errWrapped allows arbitrary errors passed to WrapError to be enhanced with
- // context and unwrapped with Cause()
- type errWrapped struct {
- cause error
- ctx string
- }
- func (e errWrapped) Error() string {
- if e.ctx != "" {
- return fmt.Sprintf("%s at %s", e.cause, e.ctx)
- } else {
- return e.cause.Error()
- }
- }
- func (e errWrapped) Resumable() bool {
- if e, ok := e.cause.(Error); ok {
- return e.Resumable()
- }
- return resumableDefault
- }
- 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 {
- ctx string
- }
- func (f errFatal) Error() string {
- out := "msgp: fatal decoding error (unreachable code)"
- if f.ctx != "" {
- out += " at " + f.ctx
- }
- return out
- }
- func (f errFatal) Resumable() bool { return false }
- func (f errFatal) withContext(ctx string) error { f.ctx = addCtx(f.ctx, ctx); return f }
- // ArrayError is an error returned
- // when decoding a fix-sized array
- // of the wrong size
- type ArrayError struct {
- Wanted uint32
- Got uint32
- ctx string
- }
- // 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)
- if a.ctx != "" {
- out += " at " + a.ctx
- }
- return out
- }
- // Resumable is always 'true' for ArrayErrors
- func (a ArrayError) Resumable() bool { return true }
- func (a ArrayError) withContext(ctx string) error { a.ctx = addCtx(a.ctx, ctx); return a }
- // 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
- ctx string
- }
- // Error implements the error interface
- func (i IntOverflow) Error() string {
- str := fmt.Sprintf("msgp: %d overflows int%d", i.Value, i.FailedBitsize)
- if i.ctx != "" {
- str += " at " + i.ctx
- }
- return str
- }
- // Resumable is always 'true' for overflows
- func (i IntOverflow) Resumable() bool { return true }
- func (i IntOverflow) withContext(ctx string) error { i.ctx = addCtx(i.ctx, ctx); return i }
- // 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
- ctx string
- }
- // Error implements the error interface
- func (u UintOverflow) Error() string {
- str := fmt.Sprintf("msgp: %d overflows uint%d", u.Value, u.FailedBitsize)
- if u.ctx != "" {
- str += " at " + u.ctx
- }
- return str
- }
- // Resumable is always 'true' for overflows
- func (u UintOverflow) Resumable() bool { return true }
- func (u UintOverflow) withContext(ctx string) error { u.ctx = addCtx(u.ctx, ctx); return u }
- // UintBelowZero is returned when a call
- // would cast a signed integer below zero
- // to an unsigned integer.
- type UintBelowZero struct {
- Value int64 // value of the incoming int
- ctx string
- }
- // Error implements the error interface
- func (u UintBelowZero) Error() string {
- str := fmt.Sprintf("msgp: attempted to cast int %d to unsigned", u.Value)
- if u.ctx != "" {
- str += " at " + u.ctx
- }
- return str
- }
- // Resumable is always 'true' for overflows
- func (u UintBelowZero) Resumable() bool { return true }
- func (u UintBelowZero) withContext(ctx string) error {
- u.ctx = ctx
- return u
- }
- // 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
- ctx string
- }
- // 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)
- if t.ctx != "" {
- out += " at " + t.ctx
- }
- return out
- }
- // Resumable returns 'true' for TypeErrors
- func (t TypeError) Resumable() bool { return true }
- func (t TypeError) withContext(ctx string) error { t.ctx = addCtx(t.ctx, ctx); return t }
- // 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
- ctx string
- }
- // Error implements error
- func (e *ErrUnsupportedType) Error() string {
- out := fmt.Sprintf("msgp: type %q not supported", e.T)
- if e.ctx != "" {
- out += " at " + e.ctx
- }
- return out
- }
- // Resumable returns 'true' for ErrUnsupportedType
- func (e *ErrUnsupportedType) Resumable() bool { return true }
- func (e *ErrUnsupportedType) withContext(ctx string) error {
- o := *e
- o.ctx = addCtx(o.ctx, ctx)
- return &o
- }
|