v2 / vlib / encoding / cbor / errors.v
165 lines · 144 sloc · 4.07 KB · 468855eef1db0ff73c62be2d1bf176ffa0e1478e
Raw
1module cbor
2
3// Typed errors for CBOR decode failures. Pattern-match in callers:
4//
5// cbor.decode[User](bad) or {
6// if err is cbor.UnexpectedEofError { ... }
7// }
8
9// UnexpectedEofError fires when the decoder runs past the end of its input.
10// `need` is i64 so it can represent the full CBOR length range (which is
11// u64 on the wire); huge values are clamped to i64::max for reporting.
12pub struct UnexpectedEofError {
13 Error
14pub:
15 pos int // position at which the read began
16 need i64 // bytes the decoder was trying to read
17 remaining int // bytes actually available
18}
19
20// msg formats an UnexpectedEofError for `IError.msg()`.
21pub fn (e &UnexpectedEofError) msg() string {
22 if e.need == max_i64 {
23 return 'cbor: unexpected EOF at pos ${e.pos}: declared length exceeds available input (have ${e.remaining})'
24 }
25 return 'cbor: unexpected EOF at pos ${e.pos}: need ${e.need} bytes, have ${e.remaining}'
26}
27
28// MalformedError fires when the byte stream violates RFC 8949 well-formedness.
29pub struct MalformedError {
30 Error
31pub:
32 pos int
33 reason string
34}
35
36// msg formats a MalformedError for `IError.msg()`.
37pub fn (e &MalformedError) msg() string {
38 return 'cbor: malformed at pos ${e.pos}: ${e.reason}'
39}
40
41// TypeMismatchError fires when a typed read finds a different major type.
42pub struct TypeMismatchError {
43 Error
44pub:
45 pos int
46 expected string
47 got u8 // initial byte
48}
49
50// msg formats a TypeMismatchError for `IError.msg()`.
51pub fn (e &TypeMismatchError) msg() string {
52 return 'cbor: type mismatch at pos ${e.pos}: expected ${e.expected}, got initial byte 0x${e.got:02x}'
53}
54
55// MaxDepthError fires when nested arrays/maps exceed the configured cap.
56pub struct MaxDepthError {
57 Error
58pub:
59 pos int
60 max_depth int
61}
62
63// msg formats a MaxDepthError for `IError.msg()`.
64pub fn (e &MaxDepthError) msg() string {
65 return 'cbor: max nesting depth ${e.max_depth} exceeded at pos ${e.pos}'
66}
67
68// UnknownFieldError fires when a struct decoded with `deny_unknown_fields`
69// encounters an unmapped key.
70pub struct UnknownFieldError {
71 Error
72pub:
73 pos int
74 name string
75}
76
77// msg formats an UnknownFieldError for `IError.msg()`.
78pub fn (e &UnknownFieldError) msg() string {
79 return 'cbor: unknown field "${e.name}" at pos ${e.pos}'
80}
81
82// IntRangeError fires when a decoded integer doesn't fit the target type.
83pub struct IntRangeError {
84 Error
85pub:
86 pos int
87 target string
88 value string
89}
90
91// msg formats an IntRangeError for `IError.msg()`.
92pub fn (e &IntRangeError) msg() string {
93 return 'cbor: integer ${e.value} at pos ${e.pos} out of range for ${e.target}'
94}
95
96// InvalidUtf8Error fires when a text-string payload isn't valid UTF-8 and
97// the decoder is configured to validate strings.
98pub struct InvalidUtf8Error {
99 Error
100pub:
101 pos int
102}
103
104// msg formats an InvalidUtf8Error for `IError.msg()`.
105pub fn (e &InvalidUtf8Error) msg() string {
106 return 'cbor: invalid UTF-8 in text string at pos ${e.pos}'
107}
108
109@[cold; inline]
110fn eof_at(pos int) IError {
111 return UnexpectedEofError{
112 pos: pos
113 need: 1
114 remaining: 0
115 }
116}
117
118@[cold; inline]
119fn eof_needing(pos int, need i64, remaining int) IError {
120 return UnexpectedEofError{
121 pos: pos
122 need: need
123 remaining: remaining
124 }
125}
126
127// eof_oversized reports an EOF caused by a length argument larger than
128// the host can represent, clamped to i64::max so callers see a sensible
129// number rather than a negative wrap-around. Used by string/bytes
130// chunk readers where the wire length is u64.
131@[cold; inline]
132fn eof_oversized(pos int, want u64, remaining int) IError {
133 clamped := if want > u64(max_i64) { max_i64 } else { i64(want) }
134 return UnexpectedEofError{
135 pos: pos
136 need: clamped
137 remaining: remaining
138 }
139}
140
141@[cold; inline]
142fn malformed(pos int, reason string) IError {
143 return MalformedError{
144 pos: pos
145 reason: reason
146 }
147}
148
149@[cold; inline]
150fn type_mismatch(pos int, expected string, got u8) IError {
151 return TypeMismatchError{
152 pos: pos
153 expected: expected
154 got: got
155 }
156}
157
158@[cold; inline]
159fn int_range(pos int, target string, value string) IError {
160 return IntRangeError{
161 pos: pos
162 target: target
163 value: value
164 }
165}
166