v / vlib / builtin
Raw file | 164 loc (142 sloc) | 3.43 KB | Latest commit hash 90941b3b1
1// Copyright (c) 2019-2023 Alexander Medvednikov. All rights reserved.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4module builtin
5
6// IError holds information about an error instance
7pub interface IError {
8 // >> Hack to allow old style custom error implementations
9 // TODO: remove once deprecation period for `IError` methods has ended
10 msg string
11 code int // <<
12 msg() string
13 code() int
14}
15
16// str returns the message of IError
17pub fn (err IError) str() string {
18 return match err {
19 None__ {
20 'none'
21 }
22 Error {
23 err.msg()
24 }
25 MessageError {
26 err.msg()
27 }
28 else {
29 // >> Hack to allow old style custom error implementations
30 // TODO: remove once deprecation period for `IError` methods has ended
31 // old_error_style := unsafe { voidptr(&err.msg) != voidptr(&err.code) } // if fields are not defined (new style) they don't have an offset between
32 // <<
33 '${err.type_name()}: ${err.msg()}'
34 }
35 }
36}
37
38// Error is the empty default implementation of `IError`.
39pub struct Error {}
40
41pub fn (err Error) msg() string {
42 return ''
43}
44
45pub fn (err Error) code() int {
46 return 0
47}
48
49// MessageError is the default implementation of the `IError` interface that is returned by the `error()` function
50struct MessageError {
51pub:
52 msg string
53 code int
54}
55
56// msg returns the message of MessageError
57pub fn (err MessageError) msg() string {
58 if err.code > 0 {
59 return '${err.msg}; code: ${err.code}'
60 }
61 return err.msg
62}
63
64// code returns the code of MessageError
65pub fn (err MessageError) code() int {
66 return err.code
67}
68
69[unsafe]
70pub fn (err &MessageError) free() {
71 unsafe { err.msg.free() }
72}
73
74const none__ = IError(&None__{})
75
76struct None__ {
77 Error
78}
79
80fn (_ None__) str() string {
81 return 'none'
82}
83
84[if trace_error ?]
85fn trace_error(x string) {
86 eprintln('> ${@FN} | ${x}')
87}
88
89// error returns a default error instance containing the error given in `message`.
90// Example: if ouch { return error('an error occurred') }
91[inline]
92pub fn error(message string) IError {
93 trace_error(message)
94 return &MessageError{
95 msg: message
96 }
97}
98
99// error_with_code returns a default error instance containing the given `message` and error `code`.
100// Example: if ouch { return error_with_code('an error occurred', 1) }
101[inline]
102pub fn error_with_code(message string, code int) IError {
103 trace_error('${message} | code: ${code}')
104 return &MessageError{
105 msg: message
106 code: code
107 }
108}
109
110// Option is the base of V's internal option return system.
111struct Option {
112 state u8
113 err IError = none__
114 // Data is trailing after err
115 // and is not included in here but in the
116 // derived Option_xxx types
117}
118
119// option is the base of V's internal option return system.
120struct _option {
121 state u8
122 err IError = none__
123 // Data is trailing after err
124 // and is not included in here but in the
125 // derived _option_xxx types
126}
127
128fn _option_none(data voidptr, mut option _option, size int) {
129 unsafe {
130 *option = _option{
131 state: 2
132 }
133 // use err to get the end of OptionBase and then memcpy into it
134 vmemcpy(&u8(&option.err) + sizeof(IError), data, size)
135 }
136}
137
138fn _option_ok(data voidptr, mut option _option, size int) {
139 unsafe {
140 *option = _option{}
141 // use err to get the end of OptionBase and then memcpy into it
142 vmemcpy(&u8(&option.err) + sizeof(IError), data, size)
143 }
144}
145
146struct _result {
147 is_error bool
148 err IError = none__
149 // Data is trailing after err
150 // and is not included in here but in the
151 // derived Result_xxx types
152}
153
154fn _result_ok(data voidptr, mut res _result, size int) {
155 unsafe {
156 *res = _result{}
157 // use err to get the end of ResultBase and then memcpy into it
158 vmemcpy(&u8(&res.err) + sizeof(IError), data, size)
159 }
160}
161
162pub fn (_ none) str() string {
163 return 'none'
164}