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.
- checksums.yaml +4 -4
- data/docs/index.html +4 -3
- data/lib/milk_tea/base.rb +1 -1
- data/std/asset_pack.mt +267 -0
- data/std/async/libuv_runtime.mt +539 -0
- data/std/async/mailbox.mt +191 -0
- data/std/async/runtime.mt +87 -0
- data/std/async.mt +87 -0
- data/std/base64.mt +185 -0
- data/std/behavior_tree.mt +396 -0
- data/std/binary.mt +314 -0
- data/std/binary_heap.mt +157 -0
- data/std/bitset.mt +239 -0
- data/std/box2d.mt +535 -0
- data/std/bytes.mt +46 -0
- data/std/c/box2d.mt +1254 -0
- data/std/c/cgltf.mt +647 -0
- data/std/c/cjson.mt +106 -0
- data/std/c/crypto.mt +11 -0
- data/std/c/crypto_support.h +51 -0
- data/std/c/ctype.mt +19 -0
- data/std/c/ctype_bindgen.h +29 -0
- data/std/c/curl.mt +1223 -0
- data/std/c/enet.mt +473 -0
- data/std/c/errno.mt +41 -0
- data/std/c/errno_bindgen.h +53 -0
- data/std/c/flecs.mt +2945 -0
- data/std/c/fs.linux.mt +43 -0
- data/std/c/fs.windows.mt +43 -0
- data/std/c/fs_support.h +954 -0
- data/std/c/gl.mt +2065 -0
- data/std/c/gl_registry_helpers.h +10748 -0
- data/std/c/glfw.mt +499 -0
- data/std/c/libc.mt +167 -0
- data/std/c/libuv.mt +1491 -0
- data/std/c/math.mt +22 -0
- data/std/c/math_bindgen.h +31 -0
- data/std/c/miniaudio.mt +3420 -0
- data/std/c/pcre2.mt +735 -0
- data/std/c/process.mt +58 -0
- data/std/c/process_support.h +1147 -0
- data/std/c/raygui.mt +1602 -0
- data/std/c/raylib.mt +1245 -0
- data/std/c/raymath.mt +163 -0
- data/std/c/rlgl.mt +434 -0
- data/std/c/rpng.mt +60 -0
- data/std/c/rres.mt +187 -0
- data/std/c/sdl3.mt +4132 -0
- data/std/c/sqlite3.mt +951 -0
- data/std/c/stb_image.mt +52 -0
- data/std/c/stb_image_resize2.mt +128 -0
- data/std/c/stb_image_write.mt +19 -0
- data/std/c/stb_rect_pack.mt +38 -0
- data/std/c/stb_truetype.mt +175 -0
- data/std/c/stb_vorbis.mt +31 -0
- data/std/c/stdio.mt +90 -0
- data/std/c/steamworks.h +5769 -0
- data/std/c/steamworks.mt +4771 -0
- data/std/c/string.mt +16 -0
- data/std/c/string_bindgen.h +36 -0
- data/std/c/sync.mt +33 -0
- data/std/c/sync_support.h +219 -0
- data/std/c/terminal.mt +24 -0
- data/std/c/terminal_support.h +408 -0
- data/std/c/time.mt +26 -0
- data/std/c/tls.mt +24 -0
- data/std/c/tls_support.h +626 -0
- data/std/c/tracy.mt +53 -0
- data/std/c/zlib.mt +20 -0
- data/std/c/zlib_support.h +239 -0
- data/std/c/zstd.mt +231 -0
- data/std/cell.mt +60 -0
- data/std/cgltf.mt +115 -0
- data/std/cjson.mt +90 -0
- data/std/cli.mt +768 -0
- data/std/cookie.mt +198 -0
- data/std/counter.mt +160 -0
- data/std/crypto.mt +74 -0
- data/std/cstring.mt +13 -0
- data/std/ctype.mt +52 -0
- data/std/curl/runtime.mt +261 -0
- data/std/curl.mt +38 -0
- data/std/deque.mt +348 -0
- data/std/encoding.mt +93 -0
- data/std/enet.mt +133 -0
- data/std/env.mt +41 -0
- data/std/errno.mt +47 -0
- data/std/flecs.mt +978 -0
- data/std/fmt.mt +271 -0
- data/std/fs.linux.mt +696 -0
- data/std/fs.windows.mt +711 -0
- data/std/fsm.mt +267 -0
- data/std/gl.mt +2062 -0
- data/std/glfw.mt +471 -0
- data/std/goap.mt +342 -0
- data/std/graph.mt +521 -0
- data/std/gzip.mt +77 -0
- data/std/hash.mt +429 -0
- data/std/http/server.mt +810 -0
- data/std/http.mt +1227 -0
- data/std/intern.mt +53 -0
- data/std/jobs.mt +288 -0
- data/std/json.mt +627 -0
- data/std/libc.mt +34 -0
- data/std/libuv.mt +554 -0
- data/std/linear_algebra.mt +243 -0
- data/std/linked_map.mt +372 -0
- data/std/linked_map_view.mt +49 -0
- data/std/linked_set.mt +117 -0
- data/std/log.mt +69 -0
- data/std/map.mt +418 -0
- data/std/math.mt +24 -0
- data/std/mem/arena.mt +137 -0
- data/std/mem/endian.mt +51 -0
- data/std/mem/heap.mt +298 -0
- data/std/mem/pool.mt +164 -0
- data/std/mem/stack.mt +47 -0
- data/std/mem/tracking.mt +119 -0
- data/std/miniaudio.mt +1299 -0
- data/std/multiset.mt +191 -0
- data/std/net/channel.mt +727 -0
- data/std/net/clock.mt +237 -0
- data/std/net/discovery.mt +277 -0
- data/std/net/lobby.mt +813 -0
- data/std/net/manager.mt +539 -0
- data/std/net/mux.mt +839 -0
- data/std/net/nat.mt +122 -0
- data/std/net/packet.mt +219 -0
- data/std/net/punch.mt +162 -0
- data/std/net/rpc.mt +119 -0
- data/std/net/session.mt +1157 -0
- data/std/net/stun.mt +252 -0
- data/std/net/sync.mt +183 -0
- data/std/net/turn.mt +459 -0
- data/std/net.mt +2944 -0
- data/std/oauth2.mt +408 -0
- data/std/option.mt +51 -0
- data/std/ordered_map.mt +497 -0
- data/std/ordered_set.mt +348 -0
- data/std/path.mt +368 -0
- data/std/pcre2/runtime.mt +35 -0
- data/std/pcre2.mt +78 -0
- data/std/priority_queue.mt +55 -0
- data/std/process.mt +837 -0
- data/std/queue.mt +55 -0
- data/std/random.mt +146 -0
- data/std/raygui.mt +99 -0
- data/std/raylib/debug_console.mt +71 -0
- data/std/raylib/easing.mt +388 -0
- data/std/raylib/packed_assets.mt +255 -0
- data/std/raylib/runtime.mt +30 -0
- data/std/raylib/tracy_gpu.mt +37 -0
- data/std/raylib.mt +1510 -0
- data/std/raymath.mt +153 -0
- data/std/result.mt +89 -0
- data/std/rlgl.mt +268 -0
- data/std/rpng.mt +46 -0
- data/std/rres.mt +36 -0
- data/std/sdl3/runtime.mt +54 -0
- data/std/sdl3.mt +1731 -0
- data/std/serialize.mt +68 -0
- data/std/set.mt +124 -0
- data/std/spatial.mt +176 -0
- data/std/sqlite3.mt +151 -0
- data/std/stack.mt +55 -0
- data/std/stb_image.mt +47 -0
- data/std/stb_image_resize2.mt +41 -0
- data/std/stb_image_write.mt +17 -0
- data/std/stb_rect_pack.mt +15 -0
- data/std/stb_truetype.mt +77 -0
- data/std/stb_vorbis.mt +16 -0
- data/std/stdio.mt +88 -0
- data/std/steamworks.mt +1542 -0
- data/std/str.mt +293 -0
- data/std/string.mt +234 -0
- data/std/sync.mt +194 -0
- data/std/tar.mt +704 -0
- data/std/terminal.mt +1002 -0
- data/std/testing.mt +266 -0
- data/std/thread.mt +120 -0
- data/std/time.mt +105 -0
- data/std/tls.mt +616 -0
- data/std/toml.mt +1310 -0
- data/std/tracy.mt +42 -0
- data/std/uri.mt +118 -0
- data/std/url.mt +372 -0
- data/std/vec.mt +433 -0
- data/std/zstd.mt +94 -0
- metadata +187 -2
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import std.async as aio
|
|
2
|
+
import std.async.libuv_runtime as aio_backend
|
|
3
|
+
import std.deque as deque
|
|
4
|
+
import std.libuv as libuv
|
|
5
|
+
import std.mem.heap as heap
|
|
6
|
+
import std.str as text
|
|
7
|
+
import std.string as string
|
|
8
|
+
import std.sync as sync
|
|
9
|
+
import std.vec as vec
|
|
10
|
+
|
|
11
|
+
type NativeHandle = libuv.uv_handle_t
|
|
12
|
+
type NativeAsyncHandle = libuv.uv_async_t
|
|
13
|
+
|
|
14
|
+
public struct Error:
|
|
15
|
+
code: int
|
|
16
|
+
message: string.String
|
|
17
|
+
|
|
18
|
+
public struct Mailbox[T]:
|
|
19
|
+
state: ptr[MailboxState[T]]?
|
|
20
|
+
|
|
21
|
+
struct MailboxStateBase:
|
|
22
|
+
destroy: fn(state_frame: ptr[void]) -> void
|
|
23
|
+
|
|
24
|
+
struct MailboxState[T]:
|
|
25
|
+
destroy: fn(state_frame: ptr[void]) -> void
|
|
26
|
+
mutex: sync.Mutex
|
|
27
|
+
queue: deque.Deque[T]
|
|
28
|
+
handle: ptr[NativeAsyncHandle]?
|
|
29
|
+
closing: bool
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
function libuv_error(code: int) -> Error:
|
|
33
|
+
return Error(code = code, message = string.String.from_str(text.cstr_as_str(libuv.strerror(code))))
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
function mailbox_error(message: str) -> Error:
|
|
37
|
+
return Error(code = -1, message = string.String.from_str(message))
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
function async_as_handle(handle: ptr[NativeAsyncHandle]) -> ptr[NativeHandle]:
|
|
41
|
+
return unsafe: ptr[NativeHandle]<-handle
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
function handle_as_async(handle: ptr[NativeHandle]) -> ptr[NativeAsyncHandle]:
|
|
45
|
+
return unsafe: ptr[NativeAsyncHandle]<-handle
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
function mailbox_async_callback(handle: ptr[NativeAsyncHandle]) -> void:
|
|
49
|
+
unsafe: handle
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
function mailbox_destroy_state[T](state_frame: ptr[void]) -> void:
|
|
53
|
+
let state = unsafe: ptr[MailboxState[T]]<-state_frame
|
|
54
|
+
|
|
55
|
+
var mutex = unsafe: read(state).mutex
|
|
56
|
+
mutex.release()
|
|
57
|
+
|
|
58
|
+
var queue = unsafe: read(state).queue
|
|
59
|
+
queue.release()
|
|
60
|
+
|
|
61
|
+
heap.release(state)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
function mailbox_close_callback(handle: ptr[NativeHandle]) -> void:
|
|
65
|
+
let state_raw = libuv.handle_get_data(handle) else:
|
|
66
|
+
unsafe: heap.release_bytes(ptr[void]<-handle_as_async(handle))
|
|
67
|
+
return
|
|
68
|
+
|
|
69
|
+
unsafe:
|
|
70
|
+
heap.release_bytes(ptr[void]<-handle_as_async(handle))
|
|
71
|
+
|
|
72
|
+
let state_base = unsafe: ptr[MailboxStateBase]<-state_raw
|
|
73
|
+
unsafe: read(state_base).destroy(state_raw)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
function alloc_async_handle() -> ptr[NativeAsyncHandle]:
|
|
77
|
+
let handle_size = libuv.handle_size(libuv.uv_handle_type.UV_ASYNC)
|
|
78
|
+
return unsafe: ptr[NativeAsyncHandle]<-heap.must_alloc_zeroed_bytes(1, handle_size)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
public function create_on[T](runtime: aio.Runtime) -> Result[Mailbox[T], Error]:
|
|
82
|
+
let mutex_result = sync.create_mutex()
|
|
83
|
+
match mutex_result:
|
|
84
|
+
Result.failure as payload:
|
|
85
|
+
return Result[Mailbox[T], Error].failure(error = Error(
|
|
86
|
+
code = payload.error.code,
|
|
87
|
+
message = payload.error.message
|
|
88
|
+
))
|
|
89
|
+
Result.success as payload:
|
|
90
|
+
let loop = aio_backend.runtime_loop(runtime)
|
|
91
|
+
let handle = alloc_async_handle()
|
|
92
|
+
let state = heap.must_alloc_zeroed[MailboxState[T]](1)
|
|
93
|
+
unsafe:
|
|
94
|
+
state.destroy = mailbox_destroy_state[T]
|
|
95
|
+
state.mutex = payload.value
|
|
96
|
+
state.queue = deque.Deque[T].create()
|
|
97
|
+
state.handle = handle
|
|
98
|
+
state.closing = false
|
|
99
|
+
libuv.handle_set_data(async_as_handle(handle), ptr[void]<-state)
|
|
100
|
+
|
|
101
|
+
let status_code = libuv.async_init(loop, handle, mailbox_async_callback)
|
|
102
|
+
if status_code != 0:
|
|
103
|
+
payload.value.release()
|
|
104
|
+
unsafe: heap.release_bytes(ptr[void]<-handle)
|
|
105
|
+
heap.release(state)
|
|
106
|
+
return Result[Mailbox[T], Error].failure(error = libuv_error(status_code))
|
|
107
|
+
|
|
108
|
+
return Result[Mailbox[T], Error].success(value = Mailbox[T](state = state))
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
public function create[T]() -> Result[Mailbox[T], Error]:
|
|
112
|
+
return create_on[T](aio.current_runtime())
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
extending Error:
|
|
116
|
+
public editable function release() -> void:
|
|
117
|
+
this.message.release()
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
extending Mailbox[T]:
|
|
121
|
+
public editable function release() -> void:
|
|
122
|
+
let state = this.state else:
|
|
123
|
+
return
|
|
124
|
+
|
|
125
|
+
this.state = null
|
|
126
|
+
|
|
127
|
+
let handle = unsafe: read(state).handle else:
|
|
128
|
+
mailbox_destroy_state[T](unsafe: ptr[void]<-state)
|
|
129
|
+
return
|
|
130
|
+
|
|
131
|
+
unsafe: read(state).closing = true
|
|
132
|
+
libuv.close(async_as_handle(handle), mailbox_close_callback)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
public function send(value: T) -> Result[bool, Error]:
|
|
136
|
+
let state = this.state else:
|
|
137
|
+
return Result[bool, Error].failure(error = mailbox_error("mailbox is released"))
|
|
138
|
+
|
|
139
|
+
var mutex = unsafe: read(state).mutex
|
|
140
|
+
mutex.lock()
|
|
141
|
+
defer mutex.unlock()
|
|
142
|
+
|
|
143
|
+
let handle = unsafe: read(state).handle else:
|
|
144
|
+
return Result[bool, Error].failure(error = mailbox_error("mailbox is closed"))
|
|
145
|
+
|
|
146
|
+
if unsafe: read(state).closing:
|
|
147
|
+
return Result[bool, Error].failure(error = mailbox_error("mailbox is closed"))
|
|
148
|
+
|
|
149
|
+
unsafe: read(state).queue.push_back(value)
|
|
150
|
+
let status_code = libuv.async_send(handle)
|
|
151
|
+
if status_code != 0:
|
|
152
|
+
let _ = unsafe: read(state).queue.pop_back()
|
|
153
|
+
return Result[bool, Error].failure(error = libuv_error(status_code))
|
|
154
|
+
|
|
155
|
+
return Result[bool, Error].success(value = true)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
public function try_recv() -> Option[T]:
|
|
159
|
+
let state = this.state else:
|
|
160
|
+
return Option[T].none
|
|
161
|
+
|
|
162
|
+
var mutex = unsafe: read(state).mutex
|
|
163
|
+
mutex.lock()
|
|
164
|
+
defer mutex.unlock()
|
|
165
|
+
return unsafe: read(state).queue.pop_front()
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
public function drain() -> vec.Vec[T]:
|
|
169
|
+
let state = this.state else:
|
|
170
|
+
return vec.Vec[T].create()
|
|
171
|
+
|
|
172
|
+
var mutex = unsafe: read(state).mutex
|
|
173
|
+
mutex.lock()
|
|
174
|
+
defer mutex.unlock()
|
|
175
|
+
|
|
176
|
+
var drained = vec.Vec[T].with_capacity(unsafe: read(state).queue.len())
|
|
177
|
+
while true:
|
|
178
|
+
let message = unsafe: read(state).queue.pop_front()
|
|
179
|
+
if message.is_none():
|
|
180
|
+
return drained
|
|
181
|
+
drained.push(message.unwrap())
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
public function is_empty() -> bool:
|
|
185
|
+
let state = this.state else:
|
|
186
|
+
return true
|
|
187
|
+
|
|
188
|
+
var mutex = unsafe: read(state).mutex
|
|
189
|
+
mutex.lock()
|
|
190
|
+
defer mutex.unlock()
|
|
191
|
+
return unsafe: read(state).queue.is_empty()
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import std.async.libuv_runtime as backend
|
|
2
|
+
|
|
3
|
+
public type Runtime = backend.Runtime
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
public function runtime_create() -> Runtime:
|
|
7
|
+
return backend.runtime_create()
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
public function runtime_activate(runtime: Runtime) -> void:
|
|
11
|
+
backend.runtime_activate(runtime)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
public function runtime_deactivate() -> void:
|
|
15
|
+
backend.runtime_deactivate()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
public function runtime_release(runtime: ref[Runtime]) -> void:
|
|
19
|
+
backend.runtime_release(runtime)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
public function runtime_poll(runtime: Runtime) -> int:
|
|
23
|
+
return backend.runtime_poll(runtime)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
public function sleep(timeout: ptr_uint) -> Task[int]:
|
|
27
|
+
return backend.sleep(timeout)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
public function create_runtime() -> Result[Runtime, int]:
|
|
31
|
+
return backend.create_runtime()
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
public function release_runtime(runtime: ref[Runtime]) -> int:
|
|
35
|
+
return backend.release_runtime(runtime)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
public function sleep_on(runtime: Runtime, timeout: ptr_uint) -> Task[int]:
|
|
39
|
+
return backend.sleep_on(runtime, timeout)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
public function work[T](run_work: fn() -> T) -> Task[T]:
|
|
43
|
+
return backend.work[T](run_work)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
public function current_runtime() -> Runtime:
|
|
47
|
+
return backend.current_runtime_handle()
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
public function work_on[T](runtime: Runtime, run_work: fn() -> T) -> Task[T]:
|
|
51
|
+
return backend.work_on[T](runtime, run_work)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
public function pump(runtime: Runtime) -> void:
|
|
55
|
+
backend.pump(runtime)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
public function completed[T](task: Task[T]) -> bool:
|
|
59
|
+
return backend.completed[T](task)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
public function result[T](task: Task[T]) -> T:
|
|
63
|
+
return backend.result[T](task)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
public function wait_on[T](runtime: Runtime, task: Task[T]) -> T:
|
|
67
|
+
return backend.wait_on[T](runtime, task)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
public function run_on(runtime: Runtime, task: Task[void]) -> void:
|
|
71
|
+
backend.run_on(runtime, task)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
public function wait[T](root: proc() -> Task[T]) -> T:
|
|
75
|
+
return backend.wait[T](root)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
public function run(root: proc() -> Task[void]) -> void:
|
|
79
|
+
backend.run(root)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
public function with_runtime[T](body: proc(runtime: Runtime) -> T) -> T:
|
|
83
|
+
return backend.with_runtime[T](body)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
public function run_with_runtime(body: proc(runtime: Runtime) -> void) -> void:
|
|
87
|
+
backend.run_with_runtime(body)
|
data/std/async.mt
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import std.async.runtime as backend
|
|
2
|
+
|
|
3
|
+
public type Runtime = backend.Runtime
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
function runtime_create() -> Runtime:
|
|
7
|
+
return backend.runtime_create()
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
function runtime_activate(runtime: Runtime) -> void:
|
|
11
|
+
backend.runtime_activate(runtime)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
function runtime_deactivate() -> void:
|
|
15
|
+
backend.runtime_deactivate()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
function runtime_release(runtime: ref[Runtime]) -> void:
|
|
19
|
+
backend.runtime_release(runtime)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
function runtime_poll(runtime: Runtime) -> int:
|
|
23
|
+
return backend.runtime_poll(runtime)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
public function sleep(timeout: ptr_uint) -> Task[int]:
|
|
27
|
+
return backend.sleep(timeout)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
public function create_runtime() -> Result[Runtime, int]:
|
|
31
|
+
return backend.create_runtime()
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
public function release_runtime(runtime: ref[Runtime]) -> int:
|
|
35
|
+
return backend.release_runtime(runtime)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
public function sleep_on(runtime: Runtime, timeout: ptr_uint) -> Task[int]:
|
|
39
|
+
return backend.sleep_on(runtime, timeout)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
public function work[T](run_work: fn() -> T) -> Task[T]:
|
|
43
|
+
return backend.work[T](run_work)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
public function current_runtime() -> Runtime:
|
|
47
|
+
return backend.current_runtime()
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
public function work_on[T](runtime: Runtime, run_work: fn() -> T) -> Task[T]:
|
|
51
|
+
return backend.work_on[T](runtime, run_work)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
public function pump(runtime: Runtime) -> void:
|
|
55
|
+
backend.pump(runtime)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
public function completed[T](task: Task[T]) -> bool:
|
|
59
|
+
return backend.completed[T](task)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
public function result[T](task: Task[T]) -> T:
|
|
63
|
+
return backend.result[T](task)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
public function wait_on[T](runtime: Runtime, task: Task[T]) -> T:
|
|
67
|
+
return backend.wait_on[T](runtime, task)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
public function run_on(runtime: Runtime, task: Task[void]) -> void:
|
|
71
|
+
backend.run_on(runtime, task)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
public function wait[T](root: proc() -> Task[T]) -> T:
|
|
75
|
+
return backend.wait[T](root)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
public function run(root: proc() -> Task[void]) -> void:
|
|
79
|
+
backend.run(root)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
public function with_runtime[T](body: proc(runtime: Runtime) -> T) -> T:
|
|
83
|
+
return backend.with_runtime[T](body)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
public function run_with_runtime(body: proc(runtime: Runtime) -> void) -> void:
|
|
87
|
+
backend.run_with_runtime(body)
|
data/std/base64.mt
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import std.bytes as bytes
|
|
2
|
+
import std.mem.heap as heap
|
|
3
|
+
import std.str as text
|
|
4
|
+
import std.string as string
|
|
5
|
+
|
|
6
|
+
const BASE64_ALPHABET: str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
|
7
|
+
const BASE64_URL_ALPHABET: str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
|
|
8
|
+
const BASE64_PAD: ubyte = 61
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
function lookup(value: ubyte) -> Option[ubyte]:
|
|
12
|
+
if value >= 65 and value <= 90:
|
|
13
|
+
return Option[ubyte].some(value = value - 65)
|
|
14
|
+
|
|
15
|
+
if value >= 97 and value <= 122:
|
|
16
|
+
return Option[ubyte].some(value = value - 71)
|
|
17
|
+
|
|
18
|
+
if value >= 48 and value <= 57:
|
|
19
|
+
return Option[ubyte].some(value = value + 4)
|
|
20
|
+
|
|
21
|
+
if value == 43 or value == 45:
|
|
22
|
+
return Option[ubyte].some(value = 62)
|
|
23
|
+
|
|
24
|
+
if value == 47 or value == 95:
|
|
25
|
+
return Option[ubyte].some(value = 63)
|
|
26
|
+
|
|
27
|
+
return Option[ubyte].none
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
function encoded_len(input_len: ptr_uint) -> ptr_uint:
|
|
31
|
+
var padded_len = input_len
|
|
32
|
+
let remainder = padded_len % 3
|
|
33
|
+
if remainder != 0:
|
|
34
|
+
padded_len += 3 - remainder
|
|
35
|
+
|
|
36
|
+
return (padded_len / 3) * 4
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
function encode_impl(input: span[ubyte], alphabet: str, use_padding: bool) -> string.String:
|
|
40
|
+
if input.len == 0:
|
|
41
|
+
return string.String.create()
|
|
42
|
+
|
|
43
|
+
let output_len = encoded_len(input.len)
|
|
44
|
+
var output = string.String.with_capacity(output_len)
|
|
45
|
+
|
|
46
|
+
var index: ptr_uint = 0
|
|
47
|
+
while index < input.len:
|
|
48
|
+
var triple: array[ubyte, 3]
|
|
49
|
+
var group_len: ubyte = 0
|
|
50
|
+
|
|
51
|
+
triple[0] = unsafe: read(input.data + index)
|
|
52
|
+
group_len += 1
|
|
53
|
+
index += 1
|
|
54
|
+
|
|
55
|
+
if index < input.len:
|
|
56
|
+
triple[1] = unsafe: read(input.data + index)
|
|
57
|
+
group_len += 1
|
|
58
|
+
index += 1
|
|
59
|
+
else:
|
|
60
|
+
triple[1] = 0
|
|
61
|
+
|
|
62
|
+
if index < input.len:
|
|
63
|
+
triple[2] = unsafe: read(input.data + index)
|
|
64
|
+
group_len += 1
|
|
65
|
+
index += 1
|
|
66
|
+
else:
|
|
67
|
+
triple[2] = 0
|
|
68
|
+
|
|
69
|
+
let combined = (ulong<-triple[0] << 16) | (ulong<-triple[1] << 8) | ulong<-triple[2]
|
|
70
|
+
|
|
71
|
+
let char0 = alphabet.byte_at(ptr_uint<-( (combined >> 18) & 0x3F) )
|
|
72
|
+
let char1 = alphabet.byte_at(ptr_uint<-( (combined >> 12) & 0x3F) )
|
|
73
|
+
output.push_byte(char0)
|
|
74
|
+
output.push_byte(char1)
|
|
75
|
+
|
|
76
|
+
if group_len >= 2:
|
|
77
|
+
let char2 = alphabet.byte_at(ptr_uint<-( (combined >> 6) & 0x3F) )
|
|
78
|
+
output.push_byte(char2)
|
|
79
|
+
else if use_padding:
|
|
80
|
+
output.push_byte(BASE64_PAD)
|
|
81
|
+
|
|
82
|
+
if group_len >= 3:
|
|
83
|
+
let char3 = alphabet.byte_at(ptr_uint<-(combined & 0x3F))
|
|
84
|
+
output.push_byte(char3)
|
|
85
|
+
else if use_padding:
|
|
86
|
+
output.push_byte(BASE64_PAD)
|
|
87
|
+
|
|
88
|
+
return output
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
public function encode(input: span[ubyte]) -> string.String:
|
|
92
|
+
return encode_impl(input, BASE64_ALPHABET, true)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
public function encode_urlsafe(input: span[ubyte]) -> string.String:
|
|
96
|
+
return encode_impl(input, BASE64_URL_ALPHABET, false)
|
|
97
|
+
|
|
98
|
+
public struct Error:
|
|
99
|
+
message: string.String
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
function error_message(message: str) -> Error:
|
|
103
|
+
return Error(message = string.String.from_str(message))
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
public function decode(text_value: str) -> Result[bytes.Bytes, Error]:
|
|
107
|
+
if text_value.len == 0:
|
|
108
|
+
return Result[bytes.Bytes, Error].success(value = bytes.Bytes.empty())
|
|
109
|
+
|
|
110
|
+
var effective_len = text_value.len
|
|
111
|
+
while effective_len > 0 and text_value.byte_at(effective_len - 1) == BASE64_PAD:
|
|
112
|
+
effective_len -= 1
|
|
113
|
+
|
|
114
|
+
if effective_len == 0:
|
|
115
|
+
return Result[bytes.Bytes, Error].success(value = bytes.Bytes.empty())
|
|
116
|
+
|
|
117
|
+
let remainder = effective_len % 4
|
|
118
|
+
if remainder == 1:
|
|
119
|
+
return Result[bytes.Bytes, Error].failure(error = error_message("base64: invalid input length"))
|
|
120
|
+
|
|
121
|
+
var output_len = (effective_len / 4) * 3
|
|
122
|
+
if remainder != 0:
|
|
123
|
+
output_len = output_len + remainder - 1
|
|
124
|
+
|
|
125
|
+
let output = heap.must_alloc[ubyte](output_len)
|
|
126
|
+
var out_index: ptr_uint = 0
|
|
127
|
+
var index: ptr_uint = 0
|
|
128
|
+
|
|
129
|
+
while index < effective_len:
|
|
130
|
+
let c0 = text_value.byte_at(index)
|
|
131
|
+
index += 1
|
|
132
|
+
let raw0_opt = lookup(c0) else:
|
|
133
|
+
heap.release(output)
|
|
134
|
+
return Result[bytes.Bytes, Error].failure(error = error_message("base64: invalid character"))
|
|
135
|
+
let raw0 = raw0_opt
|
|
136
|
+
|
|
137
|
+
var raw1: ubyte = 0
|
|
138
|
+
if index < effective_len:
|
|
139
|
+
let c1 = text_value.byte_at(index)
|
|
140
|
+
index += 1
|
|
141
|
+
let raw1_opt = lookup(c1) else:
|
|
142
|
+
heap.release(output)
|
|
143
|
+
return Result[bytes.Bytes, Error].failure(error = error_message("base64: invalid character"))
|
|
144
|
+
raw1 = raw1_opt
|
|
145
|
+
|
|
146
|
+
var raw2: ubyte = 0
|
|
147
|
+
if index < effective_len:
|
|
148
|
+
let c2 = text_value.byte_at(index)
|
|
149
|
+
index += 1
|
|
150
|
+
let raw2_opt = lookup(c2) else:
|
|
151
|
+
heap.release(output)
|
|
152
|
+
return Result[bytes.Bytes, Error].failure(error = error_message("base64: invalid character"))
|
|
153
|
+
raw2 = raw2_opt
|
|
154
|
+
|
|
155
|
+
var raw3: ubyte = 0
|
|
156
|
+
if index < effective_len:
|
|
157
|
+
let c3 = text_value.byte_at(index)
|
|
158
|
+
index += 1
|
|
159
|
+
let raw3_opt = lookup(c3) else:
|
|
160
|
+
heap.release(output)
|
|
161
|
+
return Result[bytes.Bytes, Error].failure(error = error_message("base64: invalid character"))
|
|
162
|
+
raw3 = raw3_opt
|
|
163
|
+
|
|
164
|
+
let combined = (ulong<-raw0 << 18) | (ulong<-raw1 << 12) | (ulong<-raw2 << 6) | ulong<-raw3
|
|
165
|
+
|
|
166
|
+
unsafe:
|
|
167
|
+
read(output + out_index) = ubyte<-( (combined >> 16) & 0xFF)
|
|
168
|
+
out_index += 1
|
|
169
|
+
|
|
170
|
+
if out_index < output_len:
|
|
171
|
+
unsafe:
|
|
172
|
+
read(output + out_index) = ubyte<-( (combined >> 8) & 0xFF)
|
|
173
|
+
out_index += 1
|
|
174
|
+
|
|
175
|
+
if out_index < output_len:
|
|
176
|
+
unsafe:
|
|
177
|
+
read(output + out_index) = ubyte<-(combined & 0xFF)
|
|
178
|
+
out_index += 1
|
|
179
|
+
|
|
180
|
+
return Result[bytes.Bytes, Error].success(value = bytes.Bytes(data = output, len = output_len))
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
extending Error:
|
|
184
|
+
public editable function release() -> void:
|
|
185
|
+
this.message.release()
|