v / vlib / builtin / chan_option_result.v
216 lines · 184 sloc · 5.26 KB · 7d4e37c8652fee1885ef0b805cc4688555efe619
Raw
1module builtin
2
3// ChanState describes the result of an attempted channel transaction.
4pub enum ChanState {
5 success
6 not_ready // push()/pop() would have to wait, but no_block was requested
7 closed
8}
9
10/*
11The following methods are only stubs.
12The real implementation is in `vlib/sync/channels.v`
13*/
14
15// close closes the channel for further push transactions.
16// closed channels cannot be pushed to, and after the buffer is drained
17// `<-ch or {}` and `<-ch?` use `err` or default to `channel closed`.
18pub fn (ch chan) close(err ...IError) {}
19
20// try_pop returns `ChanState.success` if an object is popped from the channel.
21// try_pop effectively pops from the channel without waiting for objects to become available.
22// Both the test and pop transaction is done atomically.
23// Pass the destination as `mut`: `ch.try_pop(mut value)`, not `ch.try_pop(&value)`.
24pub fn (ch chan) try_pop(obj voidptr) ChanState {
25 return .success
26}
27
28// try_push returns `ChanState.success` if the object is pushed to the channel.
29// try_push effectively both push and test if the transaction `ch <- a` succeeded.
30// Both the test and push transaction is done atomically.
31pub fn (ch chan) try_push(obj voidptr) ChanState {
32 return .success
33}
34
35// IError holds information about an error instance.
36pub interface IError {
37 msg() string
38 code() int
39}
40
41struct _result {
42 is_error bool
43 err IError = none__
44 // Data is trailing after err
45 // and is not included in here but in the
46 // derived Result_xxx types
47}
48
49fn _result_ok(data voidptr, mut res _result, size int) {
50 unsafe {
51 *res = _result{}
52 // use err to get the end of ResultBase and then memcpy into it
53 vmemcpy(&u8(&res.err) + sizeof(IError), data, size)
54 }
55}
56
57fn _result_clone(current &_result, mut res _result, size int) {
58 unsafe {
59 *res = _result{
60 is_error: current.is_error
61 err: current.err
62 }
63 // use err to get the end of ResultBase and then memcpy into it
64 vmemcpy(&u8(&res.err) + sizeof(IError), &u8(¤t.err) + sizeof(IError), size)
65 }
66}
67
68// str returns the message of IError.
69pub fn (err IError) str() string {
70 if err is None__ {
71 return 'none'
72 }
73 c := err.code()
74 if c > 0 {
75 return err.msg() + '; code: ' + c.str()
76 }
77 return err.msg()
78}
79
80// Error is the empty default implementation of `IError`.
81pub struct Error {}
82
83pub fn (err Error) msg() string {
84 return ''
85}
86
87pub fn (err Error) code() int {
88 return 0
89}
90
91// MessageError is the default implementation of the `IError` interface that is returned by the `error()` function.
92struct MessageError {
93pub:
94 msg string
95 code int
96}
97
98// str returns both the .msg and .code of MessageError, when .code is != 0 .
99pub fn (err MessageError) str() string {
100 if err.code > 0 {
101 return '${err.msg}; code: ${err.code}'
102 }
103 return err.msg
104}
105
106// msg returns only the message of MessageError.
107pub fn (err MessageError) msg() string {
108 return err.msg
109}
110
111// code returns only the code of MessageError.
112pub fn (err MessageError) code() int {
113 return err.code
114}
115
116@[unsafe]
117pub fn (err &MessageError) free() {
118 unsafe { err.msg.free() }
119}
120
121@[if trace_error ?]
122fn trace_error(x string) {
123 eprintln('> ${@FN} | ${x}')
124}
125
126// error returns a default error instance containing the error given in `message`.
127// Example: f := fn (ouch bool) ! { if ouch { return error('an error occurred') } }; f(false)!
128@[inline]
129pub fn error(message string) IError {
130 trace_error(message)
131 return &MessageError{
132 msg: message
133 }
134}
135
136// error_with_code returns a default error instance containing the given `message` and error `code`.
137// Example: f := fn (ouch bool) ! { if ouch { return error_with_code('an error occurred', 1) } }; f(false)!
138@[inline]
139pub fn error_with_code(message string, code int) IError {
140 trace_error('${message} | code: ${code}')
141 return &MessageError{
142 msg: message
143 code: code
144 }
145}
146
147// Option is the base of V's internal option return system.
148struct Option {
149 state u8 // 0 - ok; 2 - none; 1 - ?
150 err IError = none__
151 // Data is trailing after err
152 // and is not included in here but in the
153 // derived Option_xxx types
154}
155
156// option is the base of V's internal option return system.
157struct _option {
158 state u8
159 err IError = none__
160 // Data is trailing after err
161 // and is not included in here but in the
162 // derived _option_xxx types
163}
164
165fn _option_none(data voidptr, mut option _option, size int) {
166 unsafe {
167 *option = _option{
168 state: 2
169 }
170 // use err to get the end of OptionBase and then memcpy into it
171 vmemcpy(&u8(&option.err) + sizeof(IError), data, size)
172 }
173}
174
175fn _option_ok(data voidptr, mut option _option, size int) {
176 unsafe {
177 *option = _option{}
178 // use err to get the end of OptionBase and then memcpy into it
179 vmemcpy(&u8(&option.err) + sizeof(IError), data, size)
180 }
181}
182
183fn _option_clone(current &_option, mut option _option, size int) {
184 unsafe {
185 *option = _option{
186 state: current.state
187 err: current.err
188 }
189 // use err to get the end of OptionBase and then memcpy into it
190 vmemcpy(&u8(&option.err) + sizeof(IError), &u8(¤t.err) + sizeof(IError), size)
191 }
192}
193
194@[markused]
195fn _result_ok_markused() {
196 mut res := _result{}
197 // Keep _result_ok emitted for code that constructs Result directly.
198 _result_ok(unsafe { nil }, mut res, 0)
199}
200
201//
202
203const none__ = IError(&None__{})
204
205struct None__ {
206 Error
207}
208
209fn (_ None__) str() string {
210 return 'none'
211}
212
213// str for none, returns 'none'
214pub fn (_ none) str() string {
215 return 'none'
216}
217