mt-lang 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. checksums.yaml +4 -4
  2. data/docs/index.html +4 -3
  3. data/lib/milk_tea/base.rb +1 -1
  4. data/std/asset_pack.mt +267 -0
  5. data/std/async/libuv_runtime.mt +539 -0
  6. data/std/async/mailbox.mt +191 -0
  7. data/std/async/runtime.mt +87 -0
  8. data/std/async.mt +87 -0
  9. data/std/base64.mt +185 -0
  10. data/std/behavior_tree.mt +396 -0
  11. data/std/binary.mt +314 -0
  12. data/std/binary_heap.mt +157 -0
  13. data/std/bitset.mt +239 -0
  14. data/std/box2d.mt +535 -0
  15. data/std/bytes.mt +46 -0
  16. data/std/c/box2d.mt +1254 -0
  17. data/std/c/cgltf.mt +647 -0
  18. data/std/c/cjson.mt +106 -0
  19. data/std/c/crypto.mt +11 -0
  20. data/std/c/crypto_support.h +51 -0
  21. data/std/c/ctype.mt +19 -0
  22. data/std/c/ctype_bindgen.h +29 -0
  23. data/std/c/curl.mt +1223 -0
  24. data/std/c/enet.mt +473 -0
  25. data/std/c/errno.mt +41 -0
  26. data/std/c/errno_bindgen.h +53 -0
  27. data/std/c/flecs.mt +2945 -0
  28. data/std/c/fs.linux.mt +43 -0
  29. data/std/c/fs.windows.mt +43 -0
  30. data/std/c/fs_support.h +954 -0
  31. data/std/c/gl.mt +2065 -0
  32. data/std/c/gl_registry_helpers.h +10748 -0
  33. data/std/c/glfw.mt +499 -0
  34. data/std/c/libc.mt +167 -0
  35. data/std/c/libuv.mt +1491 -0
  36. data/std/c/math.mt +22 -0
  37. data/std/c/math_bindgen.h +31 -0
  38. data/std/c/miniaudio.mt +3420 -0
  39. data/std/c/pcre2.mt +735 -0
  40. data/std/c/process.mt +58 -0
  41. data/std/c/process_support.h +1147 -0
  42. data/std/c/raygui.mt +1602 -0
  43. data/std/c/raylib.mt +1245 -0
  44. data/std/c/raymath.mt +163 -0
  45. data/std/c/rlgl.mt +434 -0
  46. data/std/c/rpng.mt +60 -0
  47. data/std/c/rres.mt +187 -0
  48. data/std/c/sdl3.mt +4132 -0
  49. data/std/c/sqlite3.mt +951 -0
  50. data/std/c/stb_image.mt +52 -0
  51. data/std/c/stb_image_resize2.mt +128 -0
  52. data/std/c/stb_image_write.mt +19 -0
  53. data/std/c/stb_rect_pack.mt +38 -0
  54. data/std/c/stb_truetype.mt +175 -0
  55. data/std/c/stb_vorbis.mt +31 -0
  56. data/std/c/stdio.mt +90 -0
  57. data/std/c/steamworks.h +5769 -0
  58. data/std/c/steamworks.mt +4771 -0
  59. data/std/c/string.mt +16 -0
  60. data/std/c/string_bindgen.h +36 -0
  61. data/std/c/sync.mt +33 -0
  62. data/std/c/sync_support.h +219 -0
  63. data/std/c/terminal.mt +24 -0
  64. data/std/c/terminal_support.h +408 -0
  65. data/std/c/time.mt +26 -0
  66. data/std/c/tls.mt +24 -0
  67. data/std/c/tls_support.h +626 -0
  68. data/std/c/tracy.mt +53 -0
  69. data/std/c/zlib.mt +20 -0
  70. data/std/c/zlib_support.h +239 -0
  71. data/std/c/zstd.mt +231 -0
  72. data/std/cell.mt +60 -0
  73. data/std/cgltf.mt +115 -0
  74. data/std/cjson.mt +90 -0
  75. data/std/cli.mt +768 -0
  76. data/std/cookie.mt +198 -0
  77. data/std/counter.mt +160 -0
  78. data/std/crypto.mt +74 -0
  79. data/std/cstring.mt +13 -0
  80. data/std/ctype.mt +52 -0
  81. data/std/curl/runtime.mt +261 -0
  82. data/std/curl.mt +38 -0
  83. data/std/deque.mt +348 -0
  84. data/std/encoding.mt +93 -0
  85. data/std/enet.mt +133 -0
  86. data/std/env.mt +41 -0
  87. data/std/errno.mt +47 -0
  88. data/std/flecs.mt +978 -0
  89. data/std/fmt.mt +271 -0
  90. data/std/fs.linux.mt +696 -0
  91. data/std/fs.windows.mt +711 -0
  92. data/std/fsm.mt +267 -0
  93. data/std/gl.mt +2062 -0
  94. data/std/glfw.mt +471 -0
  95. data/std/goap.mt +342 -0
  96. data/std/graph.mt +521 -0
  97. data/std/gzip.mt +77 -0
  98. data/std/hash.mt +429 -0
  99. data/std/http/server.mt +810 -0
  100. data/std/http.mt +1227 -0
  101. data/std/intern.mt +53 -0
  102. data/std/jobs.mt +288 -0
  103. data/std/json.mt +627 -0
  104. data/std/libc.mt +34 -0
  105. data/std/libuv.mt +554 -0
  106. data/std/linear_algebra.mt +243 -0
  107. data/std/linked_map.mt +372 -0
  108. data/std/linked_map_view.mt +49 -0
  109. data/std/linked_set.mt +117 -0
  110. data/std/log.mt +69 -0
  111. data/std/map.mt +418 -0
  112. data/std/math.mt +24 -0
  113. data/std/mem/arena.mt +137 -0
  114. data/std/mem/endian.mt +51 -0
  115. data/std/mem/heap.mt +298 -0
  116. data/std/mem/pool.mt +164 -0
  117. data/std/mem/stack.mt +47 -0
  118. data/std/mem/tracking.mt +119 -0
  119. data/std/miniaudio.mt +1299 -0
  120. data/std/multiset.mt +191 -0
  121. data/std/net/channel.mt +727 -0
  122. data/std/net/clock.mt +237 -0
  123. data/std/net/discovery.mt +277 -0
  124. data/std/net/lobby.mt +813 -0
  125. data/std/net/manager.mt +539 -0
  126. data/std/net/mux.mt +839 -0
  127. data/std/net/nat.mt +122 -0
  128. data/std/net/packet.mt +219 -0
  129. data/std/net/punch.mt +162 -0
  130. data/std/net/rpc.mt +119 -0
  131. data/std/net/session.mt +1157 -0
  132. data/std/net/stun.mt +252 -0
  133. data/std/net/sync.mt +183 -0
  134. data/std/net/turn.mt +459 -0
  135. data/std/net.mt +2944 -0
  136. data/std/oauth2.mt +408 -0
  137. data/std/option.mt +51 -0
  138. data/std/ordered_map.mt +497 -0
  139. data/std/ordered_set.mt +348 -0
  140. data/std/path.mt +368 -0
  141. data/std/pcre2/runtime.mt +35 -0
  142. data/std/pcre2.mt +78 -0
  143. data/std/priority_queue.mt +55 -0
  144. data/std/process.mt +837 -0
  145. data/std/queue.mt +55 -0
  146. data/std/random.mt +146 -0
  147. data/std/raygui.mt +99 -0
  148. data/std/raylib/debug_console.mt +71 -0
  149. data/std/raylib/easing.mt +388 -0
  150. data/std/raylib/packed_assets.mt +255 -0
  151. data/std/raylib/runtime.mt +30 -0
  152. data/std/raylib/tracy_gpu.mt +37 -0
  153. data/std/raylib.mt +1510 -0
  154. data/std/raymath.mt +153 -0
  155. data/std/result.mt +89 -0
  156. data/std/rlgl.mt +268 -0
  157. data/std/rpng.mt +46 -0
  158. data/std/rres.mt +36 -0
  159. data/std/sdl3/runtime.mt +54 -0
  160. data/std/sdl3.mt +1731 -0
  161. data/std/serialize.mt +68 -0
  162. data/std/set.mt +124 -0
  163. data/std/spatial.mt +176 -0
  164. data/std/sqlite3.mt +151 -0
  165. data/std/stack.mt +55 -0
  166. data/std/stb_image.mt +47 -0
  167. data/std/stb_image_resize2.mt +41 -0
  168. data/std/stb_image_write.mt +17 -0
  169. data/std/stb_rect_pack.mt +15 -0
  170. data/std/stb_truetype.mt +77 -0
  171. data/std/stb_vorbis.mt +16 -0
  172. data/std/stdio.mt +88 -0
  173. data/std/steamworks.mt +1542 -0
  174. data/std/str.mt +293 -0
  175. data/std/string.mt +234 -0
  176. data/std/sync.mt +194 -0
  177. data/std/tar.mt +704 -0
  178. data/std/terminal.mt +1002 -0
  179. data/std/testing.mt +266 -0
  180. data/std/thread.mt +120 -0
  181. data/std/time.mt +105 -0
  182. data/std/tls.mt +616 -0
  183. data/std/toml.mt +1310 -0
  184. data/std/tracy.mt +42 -0
  185. data/std/uri.mt +118 -0
  186. data/std/url.mt +372 -0
  187. data/std/vec.mt +433 -0
  188. data/std/zstd.mt +94 -0
  189. metadata +187 -2
data/std/oauth2.mt ADDED
@@ -0,0 +1,408 @@
1
+ import std.base64 as base64
2
+ import std.bytes as bytes
3
+ import std.crypto as crypto
4
+ import std.http as http
5
+ import std.json as json
6
+ import std.str as text
7
+ import std.string as string
8
+ import std.url as url
9
+ import std.vec as vec
10
+
11
+ public struct Config:
12
+ client_id: string.String
13
+ client_secret: string.String
14
+ authorize_url: string.String
15
+ token_url: string.String
16
+ redirect_uri: string.String
17
+ scopes: vec.Vec[string.String]
18
+
19
+ public struct Tokens:
20
+ access_token: string.String
21
+ refresh_token: Option[string.String]
22
+ token_type: string.String
23
+ expires_in: Option[ptr_int]
24
+ id_token: Option[string.String]
25
+
26
+ public struct Error:
27
+ message: string.String
28
+
29
+
30
+ function oauth_error(message: str) -> Error:
31
+ return Error(message = string.String.from_str(message))
32
+
33
+
34
+ public function create_config(
35
+ client_id: str,
36
+ client_secret: str,
37
+ authorize_url: str,
38
+ token_url: str,
39
+ redirect_uri: str,
40
+ scopes: span[str]
41
+ ) -> Config:
42
+ var scope_vec = vec.Vec[string.String].create()
43
+ var index: ptr_uint = 0
44
+ while index < scopes.len:
45
+ scope_vec.push(string.String.from_str(unsafe: read(scopes.data + index)))
46
+ index += 1
47
+
48
+ return Config(
49
+ client_id = string.String.from_str(client_id),
50
+ client_secret = string.String.from_str(client_secret),
51
+ authorize_url = string.String.from_str(authorize_url),
52
+ token_url = string.String.from_str(token_url),
53
+ redirect_uri = string.String.from_str(redirect_uri),
54
+ scopes = scope_vec
55
+ )
56
+
57
+
58
+ public function generate_state() -> Result[string.String, Error]:
59
+ let random_result = crypto.random_bytes(32)
60
+ match random_result:
61
+ Result.failure:
62
+ return Result[string.String, Error].failure(error = oauth_error("failed to generate state"))
63
+ Result.success as ok_payload:
64
+ var random_data = ok_payload.value
65
+ let state = base64.encode_urlsafe(random_data.as_span())
66
+ random_data.release()
67
+ return Result[string.String, Error].success(value = state)
68
+
69
+
70
+ public function generate_pkce() -> Result[PkcePair, Error]:
71
+ let random_result = crypto.random_bytes(32)
72
+ match random_result:
73
+ Result.failure:
74
+ return Result[PkcePair, Error].failure(error = oauth_error("failed to generate PKCE verifier"))
75
+ Result.success as ok_payload:
76
+ var random_data = ok_payload.value
77
+ let verifier = base64.encode_urlsafe(random_data.as_span())
78
+ random_data.release()
79
+
80
+ var challenge = crypto.sha256(text.as_byte_span(verifier.as_str()))
81
+ defer challenge.release()
82
+
83
+ let challenge_b64 = base64.encode_urlsafe(challenge.as_span())
84
+
85
+ return Result[PkcePair, Error].success(
86
+ value = PkcePair(
87
+ verifier = verifier,
88
+ challenge = challenge_b64
89
+ )
90
+ )
91
+
92
+ public struct PkcePair:
93
+ verifier: string.String
94
+ challenge: string.String
95
+
96
+
97
+ public function build_authorization_url(
98
+ config: Config,
99
+ state: str,
100
+ pkce_challenge: Option[str]
101
+ ) -> string.String:
102
+ var result = string.String.from_str(config.authorize_url.as_str())
103
+
104
+ result.push_byte(63)
105
+
106
+ append_query_param(ref_of(result), "response_type", "code")
107
+ append_query_param(ref_of(result), "client_id", config.client_id.as_str())
108
+ append_query_param(ref_of(result), "redirect_uri", config.redirect_uri.as_str())
109
+ append_query_param(ref_of(result), "state", state)
110
+
111
+ if config.scopes.len() > 0:
112
+ var scope_str = string.String.create()
113
+ var index: ptr_uint = 0
114
+ while index < config.scopes.len():
115
+ if index > 0:
116
+ scope_str.push_byte(32)
117
+
118
+ let name_ptr = config.scopes.get(index) else:
119
+ break
120
+
121
+ scope_str.append(unsafe: read(name_ptr).as_str())
122
+ index += 1
123
+
124
+ append_query_param(ref_of(result), "scope", scope_str.as_str())
125
+ scope_str.release()
126
+
127
+ match pkce_challenge:
128
+ Option.none:
129
+ pass
130
+ Option.some as payload:
131
+ append_query_param(ref_of(result), "code_challenge", payload.value)
132
+ append_query_param(ref_of(result), "code_challenge_method", "S256")
133
+
134
+ return result
135
+
136
+
137
+ function append_query_param(target: ref[string.String], key: str, value: str) -> void:
138
+ if target.len() > 0:
139
+ let last_byte = target.as_str().byte_at(target.len() - 1)
140
+ if last_byte != 63 and last_byte != 38:
141
+ target.push_byte(38)
142
+
143
+ var encoded_key = url.percent_encode(key)
144
+ defer encoded_key.release()
145
+ var encoded_value = url.percent_encode(value)
146
+ defer encoded_value.release()
147
+
148
+ target.append(encoded_key.as_str())
149
+ target.push_byte(61)
150
+ target.append(encoded_value.as_str())
151
+
152
+
153
+ public async function exchange_code(
154
+ config: Config,
155
+ code: str,
156
+ pkce_verifier: Option[str]
157
+ ) -> Result[Tokens, Error]:
158
+ var body_params = vec.Vec[url.FormField].create()
159
+ defer release_form_fields(ref_of(body_params))
160
+
161
+ body_params.push(url.FormField(key = "grant_type", value = "authorization_code"))
162
+ body_params.push(url.FormField(key = "code", value = code))
163
+ body_params.push(url.FormField(key = "redirect_uri", value = config.redirect_uri.as_str()))
164
+ body_params.push(url.FormField(key = "client_id", value = config.client_id.as_str()))
165
+
166
+ match pkce_verifier:
167
+ Option.none:
168
+ pass
169
+ Option.some as payload:
170
+ body_params.push(url.FormField(key = "code_verifier", value = payload.value))
171
+
172
+ var form_body = url.encode_form(body_params.as_span())
173
+ defer form_body.release()
174
+
175
+ var auth_header = build_basic_auth_header(config.client_id.as_str(), config.client_secret.as_str())
176
+ defer auth_header.release()
177
+
178
+ var headers = array[http.RequestHeader, 2](
179
+ http.RequestHeader(name = "Content-Type", value = "application/x-www-form-urlencoded"),
180
+ http.RequestHeader(name = "Authorization", value = auth_header.as_str())
181
+ )
182
+
183
+ let header_span = span[http.RequestHeader](data = ptr_of(headers[0]), len = 2)
184
+ let body_span = text.as_byte_span(form_body.as_str())
185
+
186
+ let request_result = await http.request(
187
+ config.token_url.as_str(),
188
+ "POST",
189
+ header_span,
190
+ Option[span[ubyte]].some(value = body_span)
191
+ )
192
+ match request_result:
193
+ Result.failure as payload:
194
+ return Result[Tokens, Error].failure(error = http_error_to_oauth(payload.error))
195
+ Result.success as payload:
196
+ var response = payload.value
197
+ defer response.release()
198
+
199
+ let body_str = response.body_as_str() else:
200
+ return Result[Tokens, Error].failure(error = oauth_error("token response body is not valid UTF-8"))
201
+
202
+ return parse_token_response(body_str, response.status_code)
203
+
204
+
205
+ function build_basic_auth_header(client_id: str, client_secret: str) -> string.String:
206
+ var credentials = string.String.with_capacity(client_id.len + client_secret.len + 2)
207
+ credentials.append(client_id)
208
+ credentials.push_byte(58)
209
+ credentials.append(client_secret)
210
+
211
+ var encoded = base64.encode(text.as_byte_span(credentials.as_str()))
212
+ credentials.release()
213
+
214
+ var header = string.String.with_capacity(encoded.len() + 7)
215
+ header.append("Basic ")
216
+ header.append(encoded.as_str())
217
+
218
+ encoded.release()
219
+ return header
220
+
221
+
222
+ function parse_token_response(body_str: str, status_code: int) -> Result[Tokens, Error]:
223
+ let parsed_json = json.parse(body_str)
224
+ match parsed_json:
225
+ Result.failure:
226
+ return Result[Tokens, Error].failure(error = oauth_error("token response is not valid JSON"))
227
+ Result.success as json_payload:
228
+ let json_value = json_payload.value
229
+ defer json.release_value(json_value)
230
+
231
+ if status_code != 200:
232
+ let object_ptr = json_value.as_object() else:
233
+ return Result[Tokens, Error].failure(error = oauth_error("token error response is not an object"))
234
+
235
+ let error_desc = unsafe: read(object_ptr).get_string("error_description")
236
+ match error_desc:
237
+ Option.some as payload:
238
+ let msg = string.String.from_str(payload.value)
239
+ return Result[Tokens, Error].failure(error = Error(message = msg))
240
+ Option.none:
241
+ return Result[
242
+ Tokens,
243
+ Error
244
+ ].failure(error = oauth_error("token endpoint returned error status"))
245
+
246
+ let object_ptr = json_value.as_object() else:
247
+ return Result[Tokens, Error].failure(error = oauth_error("token response is not an object"))
248
+
249
+ unsafe:
250
+ let access_token_opt = read(object_ptr).get_string("access_token")
251
+ let access_token = access_token_opt else:
252
+ return Result[Tokens, Error].failure(error = oauth_error("token response missing access_token"))
253
+
254
+ let token_type = read_json_string(read(object_ptr), "token_type")
255
+ var token_type_str = string.String.from_str("Bearer")
256
+ match token_type:
257
+ Option.some as payload:
258
+ let owned = string.String.from_str(payload.value)
259
+ token_type_str = owned
260
+ Option.none:
261
+ pass
262
+
263
+ var refresh_token: Option[string.String] = Option[string.String].none
264
+ let refresh_opt = read_json_string(read(object_ptr), "refresh_token")
265
+ match refresh_opt:
266
+ Option.some as payload:
267
+ refresh_token = Option[string.String].some(value = string.String.from_str(payload.value))
268
+ Option.none:
269
+ pass
270
+
271
+ var expires_in: Option[ptr_int] = Option[ptr_int].none
272
+ let expires_opt = read_json_number(read(object_ptr), "expires_in")
273
+ match expires_opt:
274
+ Option.some as payload:
275
+ expires_in = Option[ptr_int].some(value = ptr_int<-payload.value)
276
+ Option.none:
277
+ pass
278
+
279
+ var id_token: Option[string.String] = Option[string.String].none
280
+ let id_opt = read_json_string(read(object_ptr), "id_token")
281
+ match id_opt:
282
+ Option.some as payload:
283
+ id_token = Option[string.String].some(value = string.String.from_str(payload.value))
284
+ Option.none:
285
+ pass
286
+
287
+ return Result[Tokens, Error].success(value = Tokens(
288
+ access_token = string.String.from_str(access_token),
289
+ refresh_token = refresh_token,
290
+ token_type = token_type_str,
291
+ expires_in = expires_in,
292
+ id_token = id_token
293
+ ))
294
+
295
+
296
+ function read_json_string(object_value: json.Object, key: str) -> Option[str]:
297
+ return object_value.get_string(key)
298
+
299
+
300
+ function read_json_number(object_value: json.Object, key: str) -> Option[double]:
301
+ return object_value.get_number(key)
302
+
303
+
304
+ public async function refresh_access_token(
305
+ config: Config,
306
+ refresh_token: str
307
+ ) -> Result[Tokens, Error]:
308
+ var body_params = vec.Vec[url.FormField].create()
309
+ defer release_form_fields(ref_of(body_params))
310
+
311
+ body_params.push(url.FormField(key = "grant_type", value = "refresh_token"))
312
+ body_params.push(url.FormField(key = "refresh_token", value = refresh_token))
313
+ body_params.push(url.FormField(key = "client_id", value = config.client_id.as_str()))
314
+
315
+ var form_body = url.encode_form(body_params.as_span())
316
+ defer form_body.release()
317
+
318
+ var auth_header = build_basic_auth_header(config.client_id.as_str(), config.client_secret.as_str())
319
+ defer auth_header.release()
320
+
321
+ var headers = array[http.RequestHeader, 2](
322
+ http.RequestHeader(name = "Content-Type", value = "application/x-www-form-urlencoded"),
323
+ http.RequestHeader(name = "Authorization", value = auth_header.as_str())
324
+ )
325
+
326
+ let header_span = span[http.RequestHeader](data = ptr_of(headers[0]), len = 2)
327
+ let body_span = text.as_byte_span(form_body.as_str())
328
+
329
+ let request_result = await http.request(
330
+ config.token_url.as_str(),
331
+ "POST",
332
+ header_span,
333
+ Option[span[ubyte]].some(value = body_span)
334
+ )
335
+ match request_result:
336
+ Result.failure as payload:
337
+ return Result[Tokens, Error].failure(error = http_error_to_oauth(payload.error))
338
+ Result.success as payload:
339
+ var response = payload.value
340
+ defer response.release()
341
+
342
+ let body_str = response.body_as_str() else:
343
+ return Result[Tokens, Error].failure(error = oauth_error("token response body is not valid UTF-8"))
344
+
345
+ return parse_token_response(body_str, response.status_code)
346
+
347
+
348
+ function http_error_to_oauth(http_error: http.Error) -> Error:
349
+ var owned_error = http_error
350
+ let message = string.String.from_str(owned_error.message.as_str())
351
+ owned_error.release()
352
+ return Error(message = message)
353
+
354
+
355
+ function release_form_fields(fields: ref[vec.Vec[url.FormField]]) -> void:
356
+ fields.release()
357
+
358
+
359
+ extending Config:
360
+ public editable function release() -> void:
361
+ this.client_id.release()
362
+ this.client_secret.release()
363
+ this.authorize_url.release()
364
+ this.token_url.release()
365
+ this.redirect_uri.release()
366
+
367
+ var index: ptr_uint = 0
368
+ while index < this.scopes.len():
369
+ let scope_ptr = this.scopes.get(index) else:
370
+ break
371
+
372
+ unsafe:
373
+ var scope = read(scope_ptr)
374
+ scope.release()
375
+
376
+ index += 1
377
+
378
+ this.scopes.release()
379
+
380
+
381
+ extending Tokens:
382
+ public editable function release() -> void:
383
+ this.access_token.release()
384
+
385
+ match this.refresh_token:
386
+ Option.some as payload:
387
+ payload.value.release()
388
+ Option.none:
389
+ pass
390
+
391
+ this.token_type.release()
392
+
393
+ match this.id_token:
394
+ Option.some as payload:
395
+ payload.value.release()
396
+ Option.none:
397
+ pass
398
+
399
+
400
+ extending PkcePair:
401
+ public editable function release() -> void:
402
+ this.verifier.release()
403
+ this.challenge.release()
404
+
405
+
406
+ extending Error:
407
+ public editable function release() -> void:
408
+ this.message.release()
data/std/option.mt ADDED
@@ -0,0 +1,51 @@
1
+ # Standard library: Option type
2
+ #
3
+ # Option[T] represents an optional value: either Some(T) or None.
4
+ # Imported automatically as part of the language prelude.
5
+
6
+ public variant Option[T]:
7
+ some(value: T)
8
+ none
9
+
10
+ extending Option[T]:
11
+ public function is_some() -> bool:
12
+ match this:
13
+ Option.some:
14
+ return true
15
+ Option.none:
16
+ return false
17
+
18
+ public function is_none() -> bool:
19
+ match this:
20
+ Option.some:
21
+ return false
22
+ Option.none:
23
+ return true
24
+
25
+ public function unwrap() -> T:
26
+ match this:
27
+ Option.some as payload:
28
+ return payload.value
29
+ Option.none:
30
+ fatal(c"called Option.unwrap on a none value")
31
+
32
+ public function expect(msg: str) -> T:
33
+ match this:
34
+ Option.some as payload:
35
+ return payload.value
36
+ Option.none:
37
+ fatal(msg)
38
+
39
+ public function unwrap_or(default: T) -> T:
40
+ match this:
41
+ Option.some as payload:
42
+ return payload.value
43
+ Option.none:
44
+ return default
45
+
46
+ public function unwrap_or_else(f: proc() -> T) -> T:
47
+ match this:
48
+ Option.some as payload:
49
+ return payload.value
50
+ Option.none:
51
+ return f()