errors.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. package msgp
  2. import (
  3. "fmt"
  4. "reflect"
  5. "strings"
  6. )
  7. const resumableDefault = false
  8. var (
  9. // ErrShortBytes is returned when the
  10. // slice being decoded is too short to
  11. // contain the contents of the message
  12. ErrShortBytes error = errShort{}
  13. // this error is only returned
  14. // if we reach code that should
  15. // be unreachable
  16. fatal error = errFatal{}
  17. )
  18. // Error is the interface satisfied
  19. // by all of the errors that originate
  20. // from this package.
  21. type Error interface {
  22. error
  23. // Resumable returns whether
  24. // or not the error means that
  25. // the stream of data is malformed
  26. // and the information is unrecoverable.
  27. Resumable() bool
  28. }
  29. // contextError allows msgp Error instances to be enhanced with additional
  30. // context about their origin.
  31. type contextError interface {
  32. Error
  33. // withContext must not modify the error instance - it must clone and
  34. // return a new error with the context added.
  35. withContext(ctx string) error
  36. }
  37. // Cause returns the underlying cause of an error that has been wrapped
  38. // with additional context.
  39. func Cause(e error) error {
  40. out := e
  41. if e, ok := e.(errWrapped); ok && e.cause != nil {
  42. out = e.cause
  43. }
  44. return out
  45. }
  46. // Resumable returns whether or not the error means that the stream of data is
  47. // malformed and the information is unrecoverable.
  48. func Resumable(e error) bool {
  49. if e, ok := e.(Error); ok {
  50. return e.Resumable()
  51. }
  52. return resumableDefault
  53. }
  54. // WrapError wraps an error with additional context that allows the part of the
  55. // serialized type that caused the problem to be identified. Underlying errors
  56. // can be retrieved using Cause()
  57. //
  58. // The input error is not modified - a new error should be returned.
  59. //
  60. // ErrShortBytes is not wrapped with any context due to backward compatibility
  61. // issues with the public API.
  62. func WrapError(err error, ctx ...interface{}) error {
  63. switch e := err.(type) {
  64. case errShort:
  65. return e
  66. case contextError:
  67. return e.withContext(ctxString(ctx))
  68. default:
  69. return errWrapped{cause: err, ctx: ctxString(ctx)}
  70. }
  71. }
  72. // ctxString converts the incoming interface{} slice into a single string.
  73. func ctxString(ctx []interface{}) string {
  74. out := ""
  75. for idx, cv := range ctx {
  76. if idx > 0 {
  77. out += "/"
  78. }
  79. out += fmt.Sprintf("%v", cv)
  80. }
  81. return out
  82. }
  83. func addCtx(ctx, add string) string {
  84. if ctx != "" {
  85. return add + "/" + ctx
  86. } else {
  87. return add
  88. }
  89. }
  90. // errWrapped allows arbitrary errors passed to WrapError to be enhanced with
  91. // context and unwrapped with Cause()
  92. type errWrapped struct {
  93. cause error
  94. ctx string
  95. }
  96. func (e errWrapped) Error() string {
  97. if e.ctx != "" {
  98. return strings.Join([]string{e.cause.Error(), "at", e.ctx}, " ")
  99. } else {
  100. return e.cause.Error()
  101. }
  102. }
  103. func (e errWrapped) Resumable() bool {
  104. if e, ok := e.cause.(Error); ok {
  105. return e.Resumable()
  106. }
  107. return resumableDefault
  108. }
  109. // Unwrap returns the cause.
  110. func (e errWrapped) Unwrap() error { return e.cause }
  111. type errShort struct{}
  112. func (e errShort) Error() string { return "msgp: too few bytes left to read object" }
  113. func (e errShort) Resumable() bool { return false }
  114. type errFatal struct {
  115. ctx string
  116. }
  117. func (f errFatal) Error() string {
  118. out := "msgp: fatal decoding error (unreachable code)"
  119. if f.ctx != "" {
  120. out += " at " + f.ctx
  121. }
  122. return out
  123. }
  124. func (f errFatal) Resumable() bool { return false }
  125. func (f errFatal) withContext(ctx string) error { f.ctx = addCtx(f.ctx, ctx); return f }
  126. // ArrayError is an error returned
  127. // when decoding a fix-sized array
  128. // of the wrong size
  129. type ArrayError struct {
  130. Wanted uint32
  131. Got uint32
  132. ctx string
  133. }
  134. // Error implements the error interface
  135. func (a ArrayError) Error() string {
  136. out := fmt.Sprintf("msgp: wanted array of size %d; got %d", a.Wanted, a.Got)
  137. if a.ctx != "" {
  138. out += " at " + a.ctx
  139. }
  140. return out
  141. }
  142. // Resumable is always 'true' for ArrayErrors
  143. func (a ArrayError) Resumable() bool { return true }
  144. func (a ArrayError) withContext(ctx string) error { a.ctx = addCtx(a.ctx, ctx); return a }
  145. // IntOverflow is returned when a call
  146. // would downcast an integer to a type
  147. // with too few bits to hold its value.
  148. type IntOverflow struct {
  149. Value int64 // the value of the integer
  150. FailedBitsize int // the bit size that the int64 could not fit into
  151. ctx string
  152. }
  153. // Error implements the error interface
  154. func (i IntOverflow) Error() string {
  155. str := fmt.Sprintf("msgp: %d overflows int%d", i.Value, i.FailedBitsize)
  156. if i.ctx != "" {
  157. str += " at " + i.ctx
  158. }
  159. return str
  160. }
  161. // Resumable is always 'true' for overflows
  162. func (i IntOverflow) Resumable() bool { return true }
  163. func (i IntOverflow) withContext(ctx string) error { i.ctx = addCtx(i.ctx, ctx); return i }
  164. // UintOverflow is returned when a call
  165. // would downcast an unsigned integer to a type
  166. // with too few bits to hold its value
  167. type UintOverflow struct {
  168. Value uint64 // value of the uint
  169. FailedBitsize int // the bit size that couldn't fit the value
  170. ctx string
  171. }
  172. // Error implements the error interface
  173. func (u UintOverflow) Error() string {
  174. str := fmt.Sprintf("msgp: %d overflows uint%d", u.Value, u.FailedBitsize)
  175. if u.ctx != "" {
  176. str += " at " + u.ctx
  177. }
  178. return str
  179. }
  180. // Resumable is always 'true' for overflows
  181. func (u UintOverflow) Resumable() bool { return true }
  182. func (u UintOverflow) withContext(ctx string) error { u.ctx = addCtx(u.ctx, ctx); return u }
  183. // UintBelowZero is returned when a call
  184. // would cast a signed integer below zero
  185. // to an unsigned integer.
  186. type UintBelowZero struct {
  187. Value int64 // value of the incoming int
  188. ctx string
  189. }
  190. // Error implements the error interface
  191. func (u UintBelowZero) Error() string {
  192. str := fmt.Sprintf("msgp: attempted to cast int %d to unsigned", u.Value)
  193. if u.ctx != "" {
  194. str += " at " + u.ctx
  195. }
  196. return str
  197. }
  198. // Resumable is always 'true' for overflows
  199. func (u UintBelowZero) Resumable() bool { return true }
  200. func (u UintBelowZero) withContext(ctx string) error {
  201. u.ctx = ctx
  202. return u
  203. }
  204. // A TypeError is returned when a particular
  205. // decoding method is unsuitable for decoding
  206. // a particular MessagePack value.
  207. type TypeError struct {
  208. Method Type // Type expected by method
  209. Encoded Type // Type actually encoded
  210. ctx string
  211. }
  212. // Error implements the error interface
  213. func (t TypeError) Error() string {
  214. out := fmt.Sprintf("msgp: attempted to decode type %q with method for %q", t.Encoded, t.Method)
  215. if t.ctx != "" {
  216. out += " at " + t.ctx
  217. }
  218. return out
  219. }
  220. // Resumable returns 'true' for TypeErrors
  221. func (t TypeError) Resumable() bool { return true }
  222. func (t TypeError) withContext(ctx string) error { t.ctx = addCtx(t.ctx, ctx); return t }
  223. // returns either InvalidPrefixError or
  224. // TypeError depending on whether or not
  225. // the prefix is recognized
  226. func badPrefix(want Type, lead byte) error {
  227. t := sizes[lead].typ
  228. if t == InvalidType {
  229. return InvalidPrefixError(lead)
  230. }
  231. return TypeError{Method: want, Encoded: t}
  232. }
  233. // InvalidPrefixError is returned when a bad encoding
  234. // uses a prefix that is not recognized in the MessagePack standard.
  235. // This kind of error is unrecoverable.
  236. type InvalidPrefixError byte
  237. // Error implements the error interface
  238. func (i InvalidPrefixError) Error() string {
  239. return fmt.Sprintf("msgp: unrecognized type prefix 0x%x", byte(i))
  240. }
  241. // Resumable returns 'false' for InvalidPrefixErrors
  242. func (i InvalidPrefixError) Resumable() bool { return false }
  243. // ErrUnsupportedType is returned
  244. // when a bad argument is supplied
  245. // to a function that takes `interface{}`.
  246. type ErrUnsupportedType struct {
  247. T reflect.Type
  248. ctx string
  249. }
  250. // Error implements error
  251. func (e *ErrUnsupportedType) Error() string {
  252. out := fmt.Sprintf("msgp: type %q not supported", e.T)
  253. if e.ctx != "" {
  254. out += " at " + e.ctx
  255. }
  256. return out
  257. }
  258. // Resumable returns 'true' for ErrUnsupportedType
  259. func (e *ErrUnsupportedType) Resumable() bool { return true }
  260. func (e *ErrUnsupportedType) withContext(ctx string) error {
  261. o := *e
  262. o.ctx = addCtx(o.ctx, ctx)
  263. return &o
  264. }