errors.go 7.7 KB

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