mt-lang 0.2.0 → 0.2.2
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/README.md +12 -0
- data/Rakefile +1 -1
- data/docs/index.html +13 -3
- data/lib/milk_tea/base.rb +7 -2
- 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
data/std/toml.mt
ADDED
|
@@ -0,0 +1,1310 @@
|
|
|
1
|
+
import std.str as text_ops
|
|
2
|
+
import std.fmt as fmt
|
|
3
|
+
import std.string as string
|
|
4
|
+
import std.vec as vec
|
|
5
|
+
import std.mem.heap as heap
|
|
6
|
+
|
|
7
|
+
const byte_tab: ubyte = 9
|
|
8
|
+
const byte_newline: ubyte = 10
|
|
9
|
+
const byte_carriage_return: ubyte = 13
|
|
10
|
+
const byte_space: ubyte = 32
|
|
11
|
+
const byte_quote: ubyte = 34
|
|
12
|
+
const byte_hash: ubyte = 35
|
|
13
|
+
const byte_plus: ubyte = 43
|
|
14
|
+
const byte_comma: ubyte = 44
|
|
15
|
+
const byte_minus: ubyte = 45
|
|
16
|
+
const byte_equal: ubyte = 61
|
|
17
|
+
const byte_left_bracket: ubyte = 91
|
|
18
|
+
const byte_backslash: ubyte = 92
|
|
19
|
+
const byte_right_bracket: ubyte = 93
|
|
20
|
+
const byte_left_brace: ubyte = 123
|
|
21
|
+
const byte_right_brace: ubyte = 125
|
|
22
|
+
const byte_underscore: ubyte = 95
|
|
23
|
+
|
|
24
|
+
public struct ParseError:
|
|
25
|
+
line: ptr_uint
|
|
26
|
+
column: ptr_uint
|
|
27
|
+
message: string.String
|
|
28
|
+
|
|
29
|
+
public enum ValueKind: int
|
|
30
|
+
string_ = 0
|
|
31
|
+
integer = 1
|
|
32
|
+
boolean = 2
|
|
33
|
+
array_ = 3
|
|
34
|
+
object_ = 4
|
|
35
|
+
|
|
36
|
+
public struct Value:
|
|
37
|
+
kind: ValueKind
|
|
38
|
+
string_value: string.String
|
|
39
|
+
integer_value: long
|
|
40
|
+
boolean_value: bool
|
|
41
|
+
array_value: ptr[Array]?
|
|
42
|
+
object_value: ptr[Object]?
|
|
43
|
+
|
|
44
|
+
public struct Entry:
|
|
45
|
+
key: string.String
|
|
46
|
+
value: Value
|
|
47
|
+
|
|
48
|
+
public struct Object:
|
|
49
|
+
entries: vec.Vec[Entry]
|
|
50
|
+
|
|
51
|
+
public struct Array:
|
|
52
|
+
values: vec.Vec[Value]
|
|
53
|
+
|
|
54
|
+
public struct Table:
|
|
55
|
+
name: string.String
|
|
56
|
+
entries: Object
|
|
57
|
+
|
|
58
|
+
public struct ArrayTable:
|
|
59
|
+
name: string.String
|
|
60
|
+
tables: vec.Vec[Object]
|
|
61
|
+
|
|
62
|
+
public struct Document:
|
|
63
|
+
root: Object
|
|
64
|
+
tables: vec.Vec[Table]
|
|
65
|
+
array_tables: vec.Vec[ArrayTable]
|
|
66
|
+
|
|
67
|
+
struct Parser:
|
|
68
|
+
text_value: str
|
|
69
|
+
index: ptr_uint
|
|
70
|
+
line: ptr_uint
|
|
71
|
+
column: ptr_uint
|
|
72
|
+
|
|
73
|
+
enum SectionKind: int
|
|
74
|
+
root = 0
|
|
75
|
+
table = 1
|
|
76
|
+
array_table = 2
|
|
77
|
+
|
|
78
|
+
struct Cursor:
|
|
79
|
+
kind: SectionKind
|
|
80
|
+
table_index: ptr_uint
|
|
81
|
+
array_table_index: ptr_uint
|
|
82
|
+
array_item_index: ptr_uint
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
function string_value(value: string.String) -> Value:
|
|
86
|
+
return Value(
|
|
87
|
+
kind = ValueKind.string_,
|
|
88
|
+
string_value = value,
|
|
89
|
+
integer_value = 0,
|
|
90
|
+
boolean_value = false,
|
|
91
|
+
array_value = null,
|
|
92
|
+
object_value = null
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
function integer_value(value: long) -> Value:
|
|
97
|
+
return Value(
|
|
98
|
+
kind = ValueKind.integer,
|
|
99
|
+
string_value = string.String.create(),
|
|
100
|
+
integer_value = value,
|
|
101
|
+
boolean_value = false,
|
|
102
|
+
array_value = null,
|
|
103
|
+
object_value = null
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
function boolean_value(value: bool) -> Value:
|
|
108
|
+
return Value(
|
|
109
|
+
kind = ValueKind.boolean,
|
|
110
|
+
string_value = string.String.create(),
|
|
111
|
+
integer_value = 0,
|
|
112
|
+
boolean_value = value,
|
|
113
|
+
array_value = null,
|
|
114
|
+
object_value = null
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
function array_value(value: ptr[Array]?) -> Value:
|
|
119
|
+
return Value(
|
|
120
|
+
kind = ValueKind.array_,
|
|
121
|
+
string_value = string.String.create(),
|
|
122
|
+
integer_value = 0,
|
|
123
|
+
boolean_value = false,
|
|
124
|
+
array_value = value,
|
|
125
|
+
object_value = null
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
function object_value(value: ptr[Object]?) -> Value:
|
|
130
|
+
return Value(
|
|
131
|
+
kind = ValueKind.object_,
|
|
132
|
+
string_value = string.String.create(),
|
|
133
|
+
integer_value = 0,
|
|
134
|
+
boolean_value = false,
|
|
135
|
+
array_value = null,
|
|
136
|
+
object_value = value
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
public function release_value(value: Value) -> void:
|
|
141
|
+
var owned = value.string_value
|
|
142
|
+
owned.release()
|
|
143
|
+
|
|
144
|
+
let nested_array = value.array_value
|
|
145
|
+
if nested_array != null:
|
|
146
|
+
unsafe:
|
|
147
|
+
read(nested_array).release()
|
|
148
|
+
heap.release(nested_array)
|
|
149
|
+
|
|
150
|
+
let nested_object = value.object_value
|
|
151
|
+
if nested_object != null:
|
|
152
|
+
unsafe:
|
|
153
|
+
read(nested_object).release()
|
|
154
|
+
heap.release(nested_object)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
function value_as_string(value: Value) -> Option[str]:
|
|
158
|
+
if value.kind == ValueKind.string_:
|
|
159
|
+
return Option[str].some(value= value.string_value.as_str())
|
|
160
|
+
|
|
161
|
+
return Option[str].none
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
function value_as_integer(value: Value) -> Option[long]:
|
|
165
|
+
if value.kind == ValueKind.integer:
|
|
166
|
+
return Option[long].some(value= value.integer_value)
|
|
167
|
+
|
|
168
|
+
return Option[long].none
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
function value_as_boolean(value: Value) -> Option[bool]:
|
|
172
|
+
if value.kind == ValueKind.boolean:
|
|
173
|
+
return Option[bool].some(value= value.boolean_value)
|
|
174
|
+
|
|
175
|
+
return Option[bool].none
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
function value_as_array(value: Value) -> ptr[Array]?:
|
|
179
|
+
if value.kind == ValueKind.array_:
|
|
180
|
+
return value.array_value
|
|
181
|
+
|
|
182
|
+
return null
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
function value_as_object(value: Value) -> ptr[Object]?:
|
|
186
|
+
if value.kind == ValueKind.object_:
|
|
187
|
+
return value.object_value
|
|
188
|
+
|
|
189
|
+
return null
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
extending ParseError:
|
|
193
|
+
public editable function release() -> void:
|
|
194
|
+
this.message.release()
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
extending Entry:
|
|
198
|
+
public editable function release() -> void:
|
|
199
|
+
this.key.release()
|
|
200
|
+
release_value(this.value)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
extending Object:
|
|
204
|
+
public static function create() -> Object:
|
|
205
|
+
return Object(entries = vec.Vec[Entry].create())
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
static function find_entry(current: Object, key: str) -> ptr[Entry]?:
|
|
209
|
+
return current.entries.find(proc(entry: ptr[Entry]) -> bool: unsafe: read(entry).key.as_str().equal(key))
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
public function contains(key: str) -> bool:
|
|
213
|
+
return Object.find_entry(this, key) != null
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
public function get_string(key: str) -> Option[str]:
|
|
217
|
+
let entry = Object.find_entry(this, key) else:
|
|
218
|
+
return Option[str].none
|
|
219
|
+
|
|
220
|
+
unsafe:
|
|
221
|
+
return value_as_string(read(entry).value)
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
public function get_integer(key: str) -> Option[long]:
|
|
225
|
+
let entry = Object.find_entry(this, key) else:
|
|
226
|
+
return Option[long].none
|
|
227
|
+
|
|
228
|
+
unsafe:
|
|
229
|
+
return value_as_integer(read(entry).value)
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
public function get_boolean(key: str) -> Option[bool]:
|
|
233
|
+
let entry = Object.find_entry(this, key) else:
|
|
234
|
+
return Option[bool].none
|
|
235
|
+
|
|
236
|
+
unsafe:
|
|
237
|
+
return value_as_boolean(read(entry).value)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
public function get_array(key: str) -> ptr[Array]?:
|
|
241
|
+
let entry = Object.find_entry(this, key) else:
|
|
242
|
+
return null
|
|
243
|
+
|
|
244
|
+
unsafe:
|
|
245
|
+
return value_as_array(read(entry).value)
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
public function get_object(key: str) -> ptr[Object]?:
|
|
249
|
+
let entry = Object.find_entry(this, key) else:
|
|
250
|
+
return null
|
|
251
|
+
|
|
252
|
+
unsafe:
|
|
253
|
+
return value_as_object(read(entry).value)
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
public editable function release() -> void:
|
|
257
|
+
var index: ptr_uint = 0
|
|
258
|
+
while index < this.entries.len():
|
|
259
|
+
let entry = this.entries.get(index) else:
|
|
260
|
+
fatal(c"toml.Object.release missing entry")
|
|
261
|
+
|
|
262
|
+
unsafe:
|
|
263
|
+
read(entry).release()
|
|
264
|
+
|
|
265
|
+
index += 1
|
|
266
|
+
|
|
267
|
+
this.entries.release()
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
extending Array:
|
|
271
|
+
public static function create() -> Array:
|
|
272
|
+
return Array(values = vec.Vec[Value].create())
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
public function len() -> ptr_uint:
|
|
276
|
+
return this.values.len()
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
public function get_string(index: ptr_uint) -> Option[str]:
|
|
280
|
+
let value_ptr = this.values.get(index) else:
|
|
281
|
+
return Option[str].none
|
|
282
|
+
|
|
283
|
+
unsafe:
|
|
284
|
+
return value_as_string(read(value_ptr))
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
public function get_integer(index: ptr_uint) -> Option[long]:
|
|
288
|
+
let value_ptr = this.values.get(index) else:
|
|
289
|
+
return Option[long].none
|
|
290
|
+
|
|
291
|
+
unsafe:
|
|
292
|
+
return value_as_integer(read(value_ptr))
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
public function get_boolean(index: ptr_uint) -> Option[bool]:
|
|
296
|
+
let value_ptr = this.values.get(index) else:
|
|
297
|
+
return Option[bool].none
|
|
298
|
+
|
|
299
|
+
unsafe:
|
|
300
|
+
return value_as_boolean(read(value_ptr))
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
public function get_array(index: ptr_uint) -> ptr[Array]?:
|
|
304
|
+
let value_ptr = this.values.get(index) else:
|
|
305
|
+
return null
|
|
306
|
+
|
|
307
|
+
unsafe:
|
|
308
|
+
return value_as_array(read(value_ptr))
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
public function get_object(index: ptr_uint) -> ptr[Object]?:
|
|
312
|
+
let value_ptr = this.values.get(index) else:
|
|
313
|
+
return null
|
|
314
|
+
|
|
315
|
+
unsafe:
|
|
316
|
+
return value_as_object(read(value_ptr))
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
public editable function release() -> void:
|
|
320
|
+
var index: ptr_uint = 0
|
|
321
|
+
while index < this.values.len():
|
|
322
|
+
let value_ptr = this.values.get(index) else:
|
|
323
|
+
fatal(c"toml.Array.release missing value")
|
|
324
|
+
|
|
325
|
+
unsafe:
|
|
326
|
+
release_value(read(value_ptr))
|
|
327
|
+
|
|
328
|
+
index += 1
|
|
329
|
+
|
|
330
|
+
this.values.release()
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
extending Table:
|
|
334
|
+
public function get_string(key: str) -> Option[str]:
|
|
335
|
+
return this.entries.get_string(key)
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
public function get_integer(key: str) -> Option[long]:
|
|
339
|
+
return this.entries.get_integer(key)
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
public function get_boolean(key: str) -> Option[bool]:
|
|
343
|
+
return this.entries.get_boolean(key)
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
public function get_array(key: str) -> ptr[Array]?:
|
|
347
|
+
return this.entries.get_array(key)
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
public function get_object(key: str) -> ptr[Object]?:
|
|
351
|
+
return this.entries.get_object(key)
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
public editable function release() -> void:
|
|
355
|
+
this.name.release()
|
|
356
|
+
this.entries.release()
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
extending ArrayTable:
|
|
360
|
+
public function len() -> ptr_uint:
|
|
361
|
+
return this.tables.len()
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
public function get(index: ptr_uint) -> ptr[Object]?:
|
|
365
|
+
return this.tables.get(index)
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
public function at(index: ptr_uint) -> Option[Object]:
|
|
369
|
+
return this.tables.at(index)
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
public editable function release() -> void:
|
|
373
|
+
this.name.release()
|
|
374
|
+
|
|
375
|
+
var index: ptr_uint = 0
|
|
376
|
+
while index < this.tables.len():
|
|
377
|
+
let table_ptr = this.tables.get(index) else:
|
|
378
|
+
fatal(c"toml.ArrayTable.release missing table")
|
|
379
|
+
|
|
380
|
+
unsafe:
|
|
381
|
+
read(table_ptr).release()
|
|
382
|
+
|
|
383
|
+
index += 1
|
|
384
|
+
|
|
385
|
+
this.tables.release()
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
extending Document:
|
|
389
|
+
public static function create() -> Document:
|
|
390
|
+
return Document(
|
|
391
|
+
root = Object.create(),
|
|
392
|
+
tables = vec.Vec[Table].create(),
|
|
393
|
+
array_tables = vec.Vec[ArrayTable].create()
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
public function get_string(key: str) -> Option[str]:
|
|
398
|
+
return this.root.get_string(key)
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
public function get_integer(key: str) -> Option[long]:
|
|
402
|
+
return this.root.get_integer(key)
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
public function get_boolean(key: str) -> Option[bool]:
|
|
406
|
+
return this.root.get_boolean(key)
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
public function get_array(key: str) -> ptr[Array]?:
|
|
410
|
+
return this.root.get_array(key)
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
public function get_object(key: str) -> ptr[Object]?:
|
|
414
|
+
return this.root.get_object(key)
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
public function get_table(name: str) -> ptr[Table]?:
|
|
418
|
+
var index: ptr_uint = 0
|
|
419
|
+
while index < this.tables.len():
|
|
420
|
+
let table_ptr = this.tables.get(index) else:
|
|
421
|
+
fatal(c"toml.Document.get_table missing table")
|
|
422
|
+
|
|
423
|
+
unsafe:
|
|
424
|
+
if read(table_ptr).name.as_str().equal(name):
|
|
425
|
+
return table_ptr
|
|
426
|
+
|
|
427
|
+
index += 1
|
|
428
|
+
|
|
429
|
+
return null
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
public function get_array_table(name: str) -> ptr[ArrayTable]?:
|
|
433
|
+
var index: ptr_uint = 0
|
|
434
|
+
while index < this.array_tables.len():
|
|
435
|
+
let table_ptr = this.array_tables.get(index) else:
|
|
436
|
+
fatal(c"toml.Document.get_array_table missing table")
|
|
437
|
+
|
|
438
|
+
unsafe:
|
|
439
|
+
if read(table_ptr).name.as_str().equal(name):
|
|
440
|
+
return table_ptr
|
|
441
|
+
|
|
442
|
+
index += 1
|
|
443
|
+
|
|
444
|
+
return null
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
public editable function release() -> void:
|
|
448
|
+
this.root.release()
|
|
449
|
+
|
|
450
|
+
var table_index: ptr_uint = 0
|
|
451
|
+
while table_index < this.tables.len():
|
|
452
|
+
let table_ptr = this.tables.get(table_index) else:
|
|
453
|
+
fatal(c"toml.Document.release missing table")
|
|
454
|
+
|
|
455
|
+
unsafe:
|
|
456
|
+
read(table_ptr).release()
|
|
457
|
+
|
|
458
|
+
table_index += 1
|
|
459
|
+
|
|
460
|
+
var array_table_index: ptr_uint = 0
|
|
461
|
+
while array_table_index < this.array_tables.len():
|
|
462
|
+
let table_ptr = this.array_tables.get(array_table_index) else:
|
|
463
|
+
fatal(c"toml.Document.release missing array table")
|
|
464
|
+
|
|
465
|
+
unsafe:
|
|
466
|
+
read(table_ptr).release()
|
|
467
|
+
|
|
468
|
+
array_table_index += 1
|
|
469
|
+
|
|
470
|
+
this.tables.release()
|
|
471
|
+
this.array_tables.release()
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
function parse_error(parser: ref[Parser], message: str) -> ParseError:
|
|
475
|
+
return ParseError(line = parser.line, column = parser.column, message = string.String.from_str(message))
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
function ascii_letter(value: ubyte) -> bool:
|
|
479
|
+
return (value >= 65 and value <= 90) or (value >= 97 and value <= 122)
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
function ascii_digit(value: ubyte) -> bool:
|
|
483
|
+
return value >= 48 and value <= 57
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
function inline_space(value: ubyte) -> bool:
|
|
487
|
+
return value == byte_space or value == byte_tab
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
function bare_key_byte(value: ubyte) -> bool:
|
|
491
|
+
return ascii_letter(value) or ascii_digit(value) or value == byte_minus or value == byte_underscore
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
function header_name_byte(value: ubyte) -> bool:
|
|
495
|
+
return bare_key_byte(value)
|
|
496
|
+
|
|
497
|
+
|
|
498
|
+
function parser_peek_byte(parser: ref[Parser]) -> Option[ubyte]:
|
|
499
|
+
if parser.index >= parser.text_value.len:
|
|
500
|
+
return Option[ubyte].none
|
|
501
|
+
|
|
502
|
+
return Option[ubyte].some(value= parser.text_value.byte_at(parser.index))
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
function parser_peek_offset_byte(parser: ref[Parser], offset: ptr_uint) -> Option[ubyte]:
|
|
506
|
+
if offset > heap.ptr_uint_max - parser.index:
|
|
507
|
+
return Option[ubyte].none
|
|
508
|
+
|
|
509
|
+
let index = parser.index + offset
|
|
510
|
+
if index >= parser.text_value.len:
|
|
511
|
+
return Option[ubyte].none
|
|
512
|
+
|
|
513
|
+
return Option[ubyte].some(value= parser.text_value.byte_at(index))
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
function parser_advance(parser: ref[Parser]) -> Option[ubyte]:
|
|
517
|
+
if parser.index >= parser.text_value.len:
|
|
518
|
+
return Option[ubyte].none
|
|
519
|
+
|
|
520
|
+
let current = parser.text_value.byte_at(parser.index)
|
|
521
|
+
if current == byte_carriage_return:
|
|
522
|
+
parser.index += 1
|
|
523
|
+
if parser.index < parser.text_value.len and parser.text_value.byte_at(parser.index) == byte_newline:
|
|
524
|
+
parser.index += 1
|
|
525
|
+
parser.line += 1
|
|
526
|
+
parser.column = 1
|
|
527
|
+
return Option[ubyte].some(value= byte_newline)
|
|
528
|
+
|
|
529
|
+
parser.index += 1
|
|
530
|
+
if current == byte_newline:
|
|
531
|
+
parser.line += 1
|
|
532
|
+
parser.column = 1
|
|
533
|
+
else:
|
|
534
|
+
parser.column += 1
|
|
535
|
+
|
|
536
|
+
return Option[ubyte].some(value= current)
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
function parser_consume_byte(parser: ref[Parser], expected: ubyte) -> bool:
|
|
540
|
+
match parser_peek_byte(parser):
|
|
541
|
+
Option.none:
|
|
542
|
+
return false
|
|
543
|
+
Option.some as payload:
|
|
544
|
+
if payload.value != expected:
|
|
545
|
+
return false
|
|
546
|
+
|
|
547
|
+
parser_advance(parser)
|
|
548
|
+
return true
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
function parser_skip_inline_space(parser: ref[Parser]) -> void:
|
|
552
|
+
while true:
|
|
553
|
+
match parser_peek_byte(parser):
|
|
554
|
+
Option.none:
|
|
555
|
+
return
|
|
556
|
+
Option.some as payload:
|
|
557
|
+
if not inline_space(payload.value):
|
|
558
|
+
return
|
|
559
|
+
parser_advance(parser)
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
function parser_skip_comment(parser: ref[Parser]) -> void:
|
|
563
|
+
if not parser_consume_byte(parser, byte_hash):
|
|
564
|
+
return
|
|
565
|
+
|
|
566
|
+
while true:
|
|
567
|
+
match parser_peek_byte(parser):
|
|
568
|
+
Option.none:
|
|
569
|
+
return
|
|
570
|
+
Option.some as payload:
|
|
571
|
+
if payload.value == byte_newline or payload.value == byte_carriage_return:
|
|
572
|
+
return
|
|
573
|
+
parser_advance(parser)
|
|
574
|
+
|
|
575
|
+
|
|
576
|
+
function parser_skip_layout(parser: ref[Parser]) -> void:
|
|
577
|
+
while true:
|
|
578
|
+
parser_skip_inline_space(parser)
|
|
579
|
+
|
|
580
|
+
match parser_peek_byte(parser):
|
|
581
|
+
Option.none:
|
|
582
|
+
return
|
|
583
|
+
Option.some as payload:
|
|
584
|
+
if payload.value == byte_hash:
|
|
585
|
+
parser_skip_comment(parser)
|
|
586
|
+
continue
|
|
587
|
+
if payload.value == byte_newline or payload.value == byte_carriage_return:
|
|
588
|
+
parser_advance(parser)
|
|
589
|
+
continue
|
|
590
|
+
return
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
function parser_finish_line(parser: ref[Parser]) -> Result[bool, ParseError]:
|
|
594
|
+
parser_skip_inline_space(parser)
|
|
595
|
+
parser_skip_comment(parser)
|
|
596
|
+
|
|
597
|
+
match parser_peek_byte(parser):
|
|
598
|
+
Option.none:
|
|
599
|
+
return Result[bool, ParseError].success(value= true)
|
|
600
|
+
Option.some as payload:
|
|
601
|
+
if payload.value == byte_newline or payload.value == byte_carriage_return:
|
|
602
|
+
parser_advance(parser)
|
|
603
|
+
return Result[bool, ParseError].success(value= true)
|
|
604
|
+
|
|
605
|
+
return Result[bool, ParseError].failure(error= parse_error(parser, "expected end of line"))
|
|
606
|
+
|
|
607
|
+
|
|
608
|
+
function parser_starts_with(parser: ref[Parser], literal: str) -> bool:
|
|
609
|
+
if parser.text_value.len - parser.index < literal.len:
|
|
610
|
+
return false
|
|
611
|
+
|
|
612
|
+
var offset: ptr_uint = 0
|
|
613
|
+
while offset < literal.len:
|
|
614
|
+
if parser.text_value.byte_at(parser.index + offset) != literal.byte_at(offset):
|
|
615
|
+
return false
|
|
616
|
+
offset += 1
|
|
617
|
+
|
|
618
|
+
return true
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
function parser_consume_literal(parser: ref[Parser], literal: str) -> bool:
|
|
622
|
+
if not parser_starts_with(parser, literal):
|
|
623
|
+
return false
|
|
624
|
+
|
|
625
|
+
var offset: ptr_uint = 0
|
|
626
|
+
while offset < literal.len:
|
|
627
|
+
parser_advance(parser)
|
|
628
|
+
offset += 1
|
|
629
|
+
|
|
630
|
+
return true
|
|
631
|
+
|
|
632
|
+
|
|
633
|
+
function parse_string(parser: ref[Parser]) -> Result[string.String, ParseError]:
|
|
634
|
+
if not parser_consume_byte(parser, byte_quote):
|
|
635
|
+
return Result[string.String, ParseError].failure(error= parse_error(parser, "expected string"))
|
|
636
|
+
|
|
637
|
+
var result = string.String.create()
|
|
638
|
+
while true:
|
|
639
|
+
match parser_peek_byte(parser):
|
|
640
|
+
Option.none:
|
|
641
|
+
result.release()
|
|
642
|
+
return Result[string.String, ParseError].failure(error= parse_error(parser, "unterminated string"))
|
|
643
|
+
Option.some as payload:
|
|
644
|
+
let current = payload.value
|
|
645
|
+
if current == byte_quote:
|
|
646
|
+
parser_advance(parser)
|
|
647
|
+
return Result[string.String, ParseError].success(value= result)
|
|
648
|
+
if current == byte_newline or current == byte_carriage_return:
|
|
649
|
+
result.release()
|
|
650
|
+
return Result[string.String, ParseError].failure(error= parse_error(parser, "unterminated string"))
|
|
651
|
+
if current != byte_backslash:
|
|
652
|
+
result.push_byte(current)
|
|
653
|
+
parser_advance(parser)
|
|
654
|
+
continue
|
|
655
|
+
|
|
656
|
+
parser_advance(parser)
|
|
657
|
+
match parser_advance(parser):
|
|
658
|
+
Option.none:
|
|
659
|
+
result.release()
|
|
660
|
+
return Result[string.String, ParseError].failure(error= parse_error(parser, "unterminated escape"))
|
|
661
|
+
Option.some as payload:
|
|
662
|
+
let escaped = payload.value
|
|
663
|
+
if escaped == 98:
|
|
664
|
+
result.push_byte(8)
|
|
665
|
+
else if escaped == 102:
|
|
666
|
+
result.push_byte(12)
|
|
667
|
+
else if escaped == 110:
|
|
668
|
+
result.push_byte(byte_newline)
|
|
669
|
+
else if escaped == 114:
|
|
670
|
+
result.push_byte(byte_carriage_return)
|
|
671
|
+
else if escaped == 116:
|
|
672
|
+
result.push_byte(byte_tab)
|
|
673
|
+
else if escaped == byte_quote:
|
|
674
|
+
result.push_byte(byte_quote)
|
|
675
|
+
else if escaped == byte_backslash:
|
|
676
|
+
result.push_byte(byte_backslash)
|
|
677
|
+
else:
|
|
678
|
+
result.release()
|
|
679
|
+
return Result[string.String, ParseError].failure(error= parse_error(
|
|
680
|
+
parser,
|
|
681
|
+
"unsupported string escape"
|
|
682
|
+
))
|
|
683
|
+
|
|
684
|
+
|
|
685
|
+
function parse_key(parser: ref[Parser]) -> Result[string.String, ParseError]:
|
|
686
|
+
match parser_peek_byte(parser):
|
|
687
|
+
Option.none:
|
|
688
|
+
return Result[string.String, ParseError].failure(error= parse_error(parser, "expected key"))
|
|
689
|
+
Option.some as payload:
|
|
690
|
+
if payload.value == byte_quote:
|
|
691
|
+
return parse_string(parser)
|
|
692
|
+
if not bare_key_byte(payload.value):
|
|
693
|
+
return Result[string.String, ParseError].failure(error= parse_error(parser, "expected key"))
|
|
694
|
+
|
|
695
|
+
let start = parser.index
|
|
696
|
+
while true:
|
|
697
|
+
var advance = false
|
|
698
|
+
match parser_peek_byte(parser):
|
|
699
|
+
Option.none:
|
|
700
|
+
pass
|
|
701
|
+
Option.some as payload:
|
|
702
|
+
if not bare_key_byte(payload.value):
|
|
703
|
+
pass
|
|
704
|
+
else:
|
|
705
|
+
advance = true
|
|
706
|
+
|
|
707
|
+
if not advance:
|
|
708
|
+
break
|
|
709
|
+
|
|
710
|
+
parser_advance(parser)
|
|
711
|
+
|
|
712
|
+
let key_text = parser.text_value.slice(start, parser.index - start)
|
|
713
|
+
return Result[string.String, ParseError].success(value= string.String.from_str(key_text))
|
|
714
|
+
|
|
715
|
+
|
|
716
|
+
function parse_header_name(parser: ref[Parser]) -> Result[string.String, ParseError]:
|
|
717
|
+
match parser_peek_byte(parser):
|
|
718
|
+
Option.none:
|
|
719
|
+
return Result[string.String, ParseError].failure(error= parse_error(parser, "expected header name"))
|
|
720
|
+
Option.some as payload:
|
|
721
|
+
if payload.value == byte_quote:
|
|
722
|
+
return parse_string(parser)
|
|
723
|
+
if not header_name_byte(payload.value):
|
|
724
|
+
return Result[string.String, ParseError].failure(error= parse_error(parser, "expected header name"))
|
|
725
|
+
|
|
726
|
+
let start = parser.index
|
|
727
|
+
while true:
|
|
728
|
+
var advance = false
|
|
729
|
+
match parser_peek_byte(parser):
|
|
730
|
+
Option.none:
|
|
731
|
+
pass
|
|
732
|
+
Option.some as payload:
|
|
733
|
+
if not header_name_byte(payload.value):
|
|
734
|
+
pass
|
|
735
|
+
else:
|
|
736
|
+
advance = true
|
|
737
|
+
|
|
738
|
+
if not advance:
|
|
739
|
+
break
|
|
740
|
+
|
|
741
|
+
parser_advance(parser)
|
|
742
|
+
|
|
743
|
+
let name_text = parser.text_value.slice(start, parser.index - start)
|
|
744
|
+
return Result[string.String, ParseError].success(value= string.String.from_str(name_text))
|
|
745
|
+
|
|
746
|
+
|
|
747
|
+
function parse_integer(parser: ref[Parser]) -> Result[long, ParseError]:
|
|
748
|
+
var negative = false
|
|
749
|
+
match parser_peek_byte(parser):
|
|
750
|
+
Option.none:
|
|
751
|
+
return Result[long, ParseError].failure(error= parse_error(parser, "expected integer"))
|
|
752
|
+
Option.some as payload:
|
|
753
|
+
if payload.value == byte_minus:
|
|
754
|
+
negative = true
|
|
755
|
+
parser_advance(parser)
|
|
756
|
+
else if payload.value == byte_plus:
|
|
757
|
+
parser_advance(parser)
|
|
758
|
+
|
|
759
|
+
match parser_peek_byte(parser):
|
|
760
|
+
Option.none:
|
|
761
|
+
return Result[long, ParseError].failure(error= parse_error(parser, "expected integer"))
|
|
762
|
+
Option.some as payload:
|
|
763
|
+
if not ascii_digit(payload.value):
|
|
764
|
+
return Result[long, ParseError].failure(error= parse_error(parser, "expected integer"))
|
|
765
|
+
|
|
766
|
+
var result: long = 0
|
|
767
|
+
while true:
|
|
768
|
+
var advance = false
|
|
769
|
+
match parser_peek_byte(parser):
|
|
770
|
+
Option.none:
|
|
771
|
+
pass
|
|
772
|
+
Option.some as payload:
|
|
773
|
+
if not ascii_digit(payload.value):
|
|
774
|
+
pass
|
|
775
|
+
else:
|
|
776
|
+
result = result * 10 + long<-(payload.value - 48ub)
|
|
777
|
+
advance = true
|
|
778
|
+
|
|
779
|
+
if not advance:
|
|
780
|
+
break
|
|
781
|
+
|
|
782
|
+
parser_advance(parser)
|
|
783
|
+
|
|
784
|
+
if negative:
|
|
785
|
+
result = -result
|
|
786
|
+
|
|
787
|
+
return Result[long, ParseError].success(value= result)
|
|
788
|
+
|
|
789
|
+
|
|
790
|
+
function parse_boolean(parser: ref[Parser]) -> Result[bool, ParseError]:
|
|
791
|
+
if parser_consume_literal(parser, "true"):
|
|
792
|
+
return Result[bool, ParseError].success(value= true)
|
|
793
|
+
if parser_consume_literal(parser, "false"):
|
|
794
|
+
return Result[bool, ParseError].success(value= false)
|
|
795
|
+
|
|
796
|
+
return Result[bool, ParseError].failure(error= parse_error(parser, "expected boolean"))
|
|
797
|
+
|
|
798
|
+
|
|
799
|
+
function parse_array(parser: ref[Parser]) -> Result[ptr[Array]?, ParseError]:
|
|
800
|
+
if not parser_consume_byte(parser, byte_left_bracket):
|
|
801
|
+
return Result[ptr[Array]?, ParseError].failure(error= parse_error(parser, "expected array"))
|
|
802
|
+
|
|
803
|
+
let array_ptr = heap.must_alloc[Array](1)
|
|
804
|
+
unsafe:
|
|
805
|
+
read(array_ptr) = Array.create()
|
|
806
|
+
|
|
807
|
+
parser_skip_inline_space(parser)
|
|
808
|
+
if parser_consume_byte(parser, byte_right_bracket):
|
|
809
|
+
return Result[ptr[Array]?, ParseError].success(value= array_ptr)
|
|
810
|
+
|
|
811
|
+
while true:
|
|
812
|
+
parser_skip_inline_space(parser)
|
|
813
|
+
let value_result = parse_value(parser)
|
|
814
|
+
match value_result:
|
|
815
|
+
Result.failure as payload:
|
|
816
|
+
unsafe:
|
|
817
|
+
read(array_ptr).release()
|
|
818
|
+
heap.release(array_ptr)
|
|
819
|
+
return Result[ptr[Array]?, ParseError].failure(error= payload.error)
|
|
820
|
+
Result.success as payload:
|
|
821
|
+
unsafe:
|
|
822
|
+
read(array_ptr).values.push(payload.value)
|
|
823
|
+
|
|
824
|
+
parser_skip_inline_space(parser)
|
|
825
|
+
if parser_consume_byte(parser, byte_comma):
|
|
826
|
+
continue
|
|
827
|
+
if parser_consume_byte(parser, byte_right_bracket):
|
|
828
|
+
return Result[ptr[Array]?, ParseError].success(value= array_ptr)
|
|
829
|
+
|
|
830
|
+
unsafe:
|
|
831
|
+
read(array_ptr).release()
|
|
832
|
+
heap.release(array_ptr)
|
|
833
|
+
return Result[ptr[Array]?, ParseError].failure(error= parse_error(parser, "expected ',' or ']'"))
|
|
834
|
+
|
|
835
|
+
|
|
836
|
+
function parse_inline_object(parser: ref[Parser]) -> Result[ptr[Object]?, ParseError]:
|
|
837
|
+
if not parser_consume_byte(parser, byte_left_brace):
|
|
838
|
+
return Result[ptr[Object]?, ParseError].failure(error= parse_error(parser, "expected inline table"))
|
|
839
|
+
|
|
840
|
+
let object_ptr = heap.must_alloc[Object](1)
|
|
841
|
+
unsafe:
|
|
842
|
+
read(object_ptr) = Object.create()
|
|
843
|
+
|
|
844
|
+
parser_skip_inline_space(parser)
|
|
845
|
+
if parser_consume_byte(parser, byte_right_brace):
|
|
846
|
+
return Result[ptr[Object]?, ParseError].success(value= object_ptr)
|
|
847
|
+
|
|
848
|
+
while true:
|
|
849
|
+
parser_skip_inline_space(parser)
|
|
850
|
+
let key_result = parse_key(parser)
|
|
851
|
+
match key_result:
|
|
852
|
+
Result.failure as payload:
|
|
853
|
+
unsafe:
|
|
854
|
+
read(object_ptr).release()
|
|
855
|
+
heap.release(object_ptr)
|
|
856
|
+
return Result[ptr[Object]?, ParseError].failure(error= payload.error)
|
|
857
|
+
Result.success as key_payload:
|
|
858
|
+
var key = key_payload.value
|
|
859
|
+
parser_skip_inline_space(parser)
|
|
860
|
+
if not parser_consume_byte(parser, byte_equal):
|
|
861
|
+
key.release()
|
|
862
|
+
unsafe:
|
|
863
|
+
read(object_ptr).release()
|
|
864
|
+
heap.release(object_ptr)
|
|
865
|
+
return Result[ptr[Object]?, ParseError].failure(error= parse_error(parser, "expected '='"))
|
|
866
|
+
|
|
867
|
+
parser_skip_inline_space(parser)
|
|
868
|
+
let value_result = parse_value(parser)
|
|
869
|
+
match value_result:
|
|
870
|
+
Result.failure as payload:
|
|
871
|
+
key.release()
|
|
872
|
+
unsafe:
|
|
873
|
+
read(object_ptr).release()
|
|
874
|
+
heap.release(object_ptr)
|
|
875
|
+
return Result[ptr[Object]?, ParseError].failure(error= payload.error)
|
|
876
|
+
Result.success as value_payload:
|
|
877
|
+
let key_text = key.as_str()
|
|
878
|
+
if unsafe: read(object_ptr).contains(key_text):
|
|
879
|
+
key.release()
|
|
880
|
+
release_value(value_payload.value)
|
|
881
|
+
unsafe:
|
|
882
|
+
read(object_ptr).release()
|
|
883
|
+
heap.release(object_ptr)
|
|
884
|
+
return Result[ptr[Object]?, ParseError].failure(error= parse_error(parser, "duplicate key"))
|
|
885
|
+
|
|
886
|
+
unsafe:
|
|
887
|
+
read(object_ptr).entries.push(Entry(key = key, value = value_payload.value))
|
|
888
|
+
|
|
889
|
+
parser_skip_inline_space(parser)
|
|
890
|
+
if parser_consume_byte(parser, byte_comma):
|
|
891
|
+
continue
|
|
892
|
+
if parser_consume_byte(parser, byte_right_brace):
|
|
893
|
+
return Result[ptr[Object]?, ParseError].success(value= object_ptr)
|
|
894
|
+
|
|
895
|
+
unsafe:
|
|
896
|
+
read(object_ptr).release()
|
|
897
|
+
heap.release(object_ptr)
|
|
898
|
+
return Result[ptr[Object]?, ParseError].failure(error= parse_error(parser, "expected ',' or '}'"))
|
|
899
|
+
|
|
900
|
+
|
|
901
|
+
function parse_value(parser: ref[Parser]) -> Result[Value, ParseError]:
|
|
902
|
+
match parser_peek_byte(parser):
|
|
903
|
+
Option.none:
|
|
904
|
+
return Result[Value, ParseError].failure(error= parse_error(parser, "expected value"))
|
|
905
|
+
Option.some as payload:
|
|
906
|
+
let current = payload.value
|
|
907
|
+
if current == byte_quote:
|
|
908
|
+
let string_result = parse_string(parser)
|
|
909
|
+
match string_result:
|
|
910
|
+
Result.failure as error_payload:
|
|
911
|
+
return Result[Value, ParseError].failure(error= error_payload.error)
|
|
912
|
+
Result.success as string_payload:
|
|
913
|
+
return Result[Value, ParseError].success(value= string_value(string_payload.value))
|
|
914
|
+
|
|
915
|
+
if current == byte_left_bracket:
|
|
916
|
+
let array_result = parse_array(parser)
|
|
917
|
+
match array_result:
|
|
918
|
+
Result.failure as error_payload:
|
|
919
|
+
return Result[Value, ParseError].failure(error= error_payload.error)
|
|
920
|
+
Result.success as array_payload:
|
|
921
|
+
return Result[Value, ParseError].success(value= array_value(array_payload.value))
|
|
922
|
+
|
|
923
|
+
if current == byte_left_brace:
|
|
924
|
+
let object_result = parse_inline_object(parser)
|
|
925
|
+
match object_result:
|
|
926
|
+
Result.failure as error_payload:
|
|
927
|
+
return Result[Value, ParseError].failure(error= error_payload.error)
|
|
928
|
+
Result.success as object_payload:
|
|
929
|
+
return Result[Value, ParseError].success(value= object_value(object_payload.value))
|
|
930
|
+
|
|
931
|
+
if current == 116 or current == 102:
|
|
932
|
+
let boolean_result = parse_boolean(parser)
|
|
933
|
+
match boolean_result:
|
|
934
|
+
Result.failure as error_payload:
|
|
935
|
+
return Result[Value, ParseError].failure(error= error_payload.error)
|
|
936
|
+
Result.success as boolean_payload:
|
|
937
|
+
return Result[Value, ParseError].success(value= boolean_value(boolean_payload.value))
|
|
938
|
+
|
|
939
|
+
if ascii_digit(current) or current == byte_minus or current == byte_plus:
|
|
940
|
+
let integer_result = parse_integer(parser)
|
|
941
|
+
match integer_result:
|
|
942
|
+
Result.failure as error_payload:
|
|
943
|
+
return Result[Value, ParseError].failure(error= error_payload.error)
|
|
944
|
+
Result.success as integer_payload:
|
|
945
|
+
return Result[Value, ParseError].success(value= integer_value(integer_payload.value))
|
|
946
|
+
|
|
947
|
+
return Result[Value, ParseError].failure(error= parse_error(parser, "unsupported value"))
|
|
948
|
+
|
|
949
|
+
|
|
950
|
+
function document_find_table_index(document: ref[Document], name: str) -> Option[ptr_uint]:
|
|
951
|
+
return document.tables.find_index(proc(table_ptr: ptr[Table]) -> bool: unsafe: read(table_ptr).name.as_str().equal(name))
|
|
952
|
+
|
|
953
|
+
|
|
954
|
+
function document_find_array_table_index(document: ref[Document], name: str) -> Option[ptr_uint]:
|
|
955
|
+
return document.array_tables.find_index(proc(table_ptr: ptr[ArrayTable]) -> bool: unsafe: read(table_ptr).name.as_str().equal(name))
|
|
956
|
+
|
|
957
|
+
|
|
958
|
+
function current_object_contains(document: ref[Document], cursor: Cursor, key: str) -> bool:
|
|
959
|
+
match cursor.kind:
|
|
960
|
+
SectionKind.root:
|
|
961
|
+
return document.root.contains(key)
|
|
962
|
+
SectionKind.table:
|
|
963
|
+
let table_ptr = document.tables.get(cursor.table_index) else:
|
|
964
|
+
fatal(c"toml.current_object_contains missing table")
|
|
965
|
+
|
|
966
|
+
unsafe:
|
|
967
|
+
return read(table_ptr).entries.contains(key)
|
|
968
|
+
SectionKind.array_table:
|
|
969
|
+
let array_table_ptr = document.array_tables.get(cursor.array_table_index) else:
|
|
970
|
+
fatal(c"toml.current_object_contains missing array table")
|
|
971
|
+
|
|
972
|
+
unsafe:
|
|
973
|
+
let object_ptr = read(array_table_ptr).tables.get(cursor.array_item_index) else:
|
|
974
|
+
fatal(c"toml.current_object_contains missing array table item")
|
|
975
|
+
|
|
976
|
+
return read(object_ptr).contains(key)
|
|
977
|
+
|
|
978
|
+
|
|
979
|
+
function current_object_push(document: ref[Document], cursor: Cursor, entry: Entry) -> void:
|
|
980
|
+
match cursor.kind:
|
|
981
|
+
SectionKind.root:
|
|
982
|
+
document.root.entries.push(entry)
|
|
983
|
+
return
|
|
984
|
+
SectionKind.table:
|
|
985
|
+
let table_ptr = document.tables.get(cursor.table_index) else:
|
|
986
|
+
fatal(c"toml.current_object_push missing table")
|
|
987
|
+
|
|
988
|
+
unsafe:
|
|
989
|
+
read(table_ptr).entries.entries.push(entry)
|
|
990
|
+
return
|
|
991
|
+
SectionKind.array_table:
|
|
992
|
+
let array_table_ptr = document.array_tables.get(cursor.array_table_index) else:
|
|
993
|
+
fatal(c"toml.current_object_push missing array table")
|
|
994
|
+
|
|
995
|
+
unsafe:
|
|
996
|
+
let object_ptr = read(array_table_ptr).tables.get(cursor.array_item_index) else:
|
|
997
|
+
fatal(c"toml.current_object_push missing array table item")
|
|
998
|
+
|
|
999
|
+
read(object_ptr).entries.push(entry)
|
|
1000
|
+
return
|
|
1001
|
+
|
|
1002
|
+
|
|
1003
|
+
function parse_assignment(document: ref[Document], cursor: Cursor, parser: ref[Parser]) -> Result[bool, ParseError]:
|
|
1004
|
+
let key_result = parse_key(parser)
|
|
1005
|
+
match key_result:
|
|
1006
|
+
Result.failure as payload:
|
|
1007
|
+
return Result[bool, ParseError].failure(error= payload.error)
|
|
1008
|
+
Result.success as key_payload:
|
|
1009
|
+
var key = key_payload.value
|
|
1010
|
+
parser_skip_inline_space(parser)
|
|
1011
|
+
if not parser_consume_byte(parser, byte_equal):
|
|
1012
|
+
key.release()
|
|
1013
|
+
return Result[bool, ParseError].failure(error= parse_error(parser, "expected '='"))
|
|
1014
|
+
|
|
1015
|
+
parser_skip_inline_space(parser)
|
|
1016
|
+
let value_result = parse_value(parser)
|
|
1017
|
+
match value_result:
|
|
1018
|
+
Result.failure as payload:
|
|
1019
|
+
key.release()
|
|
1020
|
+
return Result[bool, ParseError].failure(error= payload.error)
|
|
1021
|
+
Result.success as value_payload:
|
|
1022
|
+
let key_text = key.as_str()
|
|
1023
|
+
if current_object_contains(document, cursor, key_text):
|
|
1024
|
+
key.release()
|
|
1025
|
+
release_value(value_payload.value)
|
|
1026
|
+
return Result[bool, ParseError].failure(error= parse_error(parser, "duplicate key"))
|
|
1027
|
+
|
|
1028
|
+
current_object_push(document, cursor, Entry(key = key, value = value_payload.value))
|
|
1029
|
+
return Result[bool, ParseError].success(value= true)
|
|
1030
|
+
|
|
1031
|
+
|
|
1032
|
+
function parse_header(document: ref[Document], cursor: ref[Cursor], parser: ref[Parser]) -> Result[bool, ParseError]:
|
|
1033
|
+
if not parser_consume_byte(parser, byte_left_bracket):
|
|
1034
|
+
return Result[bool, ParseError].failure(error= parse_error(parser, "expected table header"))
|
|
1035
|
+
|
|
1036
|
+
let array_table = parser_consume_byte(parser, byte_left_bracket)
|
|
1037
|
+
parser_skip_inline_space(parser)
|
|
1038
|
+
|
|
1039
|
+
let name_result = parse_header_name(parser)
|
|
1040
|
+
match name_result:
|
|
1041
|
+
Result.failure as payload:
|
|
1042
|
+
return Result[bool, ParseError].failure(error= payload.error)
|
|
1043
|
+
Result.success as name_payload:
|
|
1044
|
+
var name = name_payload.value
|
|
1045
|
+
parser_skip_inline_space(parser)
|
|
1046
|
+
|
|
1047
|
+
if array_table:
|
|
1048
|
+
if not parser_consume_byte(
|
|
1049
|
+
parser,
|
|
1050
|
+
byte_right_bracket
|
|
1051
|
+
) or not parser_consume_byte(parser, byte_right_bracket):
|
|
1052
|
+
name.release()
|
|
1053
|
+
return Result[bool, ParseError].failure(error= parse_error(parser, "expected ']]'"))
|
|
1054
|
+
|
|
1055
|
+
match document_find_table_index(document, name.as_str()):
|
|
1056
|
+
Option.some:
|
|
1057
|
+
name.release()
|
|
1058
|
+
return Result[bool, ParseError].failure(error= parse_error(parser, "table name already used"))
|
|
1059
|
+
Option.none:
|
|
1060
|
+
pass
|
|
1061
|
+
|
|
1062
|
+
match document_find_array_table_index(document, name.as_str()):
|
|
1063
|
+
Option.some as payload:
|
|
1064
|
+
let index = payload.value
|
|
1065
|
+
name.release()
|
|
1066
|
+
let array_table_ptr = document.array_tables.get(index) else:
|
|
1067
|
+
fatal(c"toml.parse_header missing array table")
|
|
1068
|
+
|
|
1069
|
+
unsafe:
|
|
1070
|
+
read(array_table_ptr).tables.push(Object.create())
|
|
1071
|
+
cursor.kind = SectionKind.array_table
|
|
1072
|
+
cursor.array_table_index = index
|
|
1073
|
+
cursor.array_item_index = read(array_table_ptr).tables.len() - 1
|
|
1074
|
+
return Result[bool, ParseError].success(value= true)
|
|
1075
|
+
Option.none:
|
|
1076
|
+
var next = ArrayTable(name = name, tables = vec.Vec[Object].create())
|
|
1077
|
+
next.tables.push(Object.create())
|
|
1078
|
+
document.array_tables.push(next)
|
|
1079
|
+
cursor.kind = SectionKind.array_table
|
|
1080
|
+
cursor.array_table_index = document.array_tables.len() - 1
|
|
1081
|
+
cursor.array_item_index = 0
|
|
1082
|
+
return Result[bool, ParseError].success(value= true)
|
|
1083
|
+
|
|
1084
|
+
if not parser_consume_byte(parser, byte_right_bracket):
|
|
1085
|
+
name.release()
|
|
1086
|
+
return Result[bool, ParseError].failure(error= parse_error(parser, "expected ']'"))
|
|
1087
|
+
|
|
1088
|
+
match document_find_table_index(document, name.as_str()):
|
|
1089
|
+
Option.some:
|
|
1090
|
+
name.release()
|
|
1091
|
+
return Result[bool, ParseError].failure(error= parse_error(parser, "duplicate table"))
|
|
1092
|
+
Option.none:
|
|
1093
|
+
pass
|
|
1094
|
+
|
|
1095
|
+
match document_find_array_table_index(document, name.as_str()):
|
|
1096
|
+
Option.some:
|
|
1097
|
+
name.release()
|
|
1098
|
+
return Result[bool, ParseError].failure(error= parse_error(parser, "duplicate table"))
|
|
1099
|
+
Option.none:
|
|
1100
|
+
pass
|
|
1101
|
+
|
|
1102
|
+
document.tables.push(Table(name = name, entries = Object.create()))
|
|
1103
|
+
cursor.kind = SectionKind.table
|
|
1104
|
+
cursor.table_index = document.tables.len() - 1
|
|
1105
|
+
return Result[bool, ParseError].success(value= true)
|
|
1106
|
+
|
|
1107
|
+
|
|
1108
|
+
public function parse(text_value: str) -> Result[Document, ParseError]:
|
|
1109
|
+
var parser = Parser(text_value = text_value, index = 0, line = 1, column = 1)
|
|
1110
|
+
var document = Document.create()
|
|
1111
|
+
var cursor = Cursor(kind = SectionKind.root, table_index = 0, array_table_index = 0, array_item_index = 0)
|
|
1112
|
+
|
|
1113
|
+
while true:
|
|
1114
|
+
parser_skip_layout(ref_of(parser))
|
|
1115
|
+
|
|
1116
|
+
let next_byte = parser_peek_byte(ref_of(parser)) else:
|
|
1117
|
+
return Result[Document, ParseError].success(value= document)
|
|
1118
|
+
|
|
1119
|
+
var statement_result = Result[bool, ParseError].success(value= true)
|
|
1120
|
+
if next_byte == byte_left_bracket:
|
|
1121
|
+
statement_result = parse_header(ref_of(document), ref_of(cursor), ref_of(parser))
|
|
1122
|
+
else:
|
|
1123
|
+
statement_result = parse_assignment(ref_of(document), cursor, ref_of(parser))
|
|
1124
|
+
|
|
1125
|
+
match statement_result:
|
|
1126
|
+
Result.failure as payload:
|
|
1127
|
+
document.release()
|
|
1128
|
+
return Result[Document, ParseError].failure(error= payload.error)
|
|
1129
|
+
Result.success:
|
|
1130
|
+
let line_result = parser_finish_line(ref_of(parser))
|
|
1131
|
+
match line_result:
|
|
1132
|
+
Result.failure as payload:
|
|
1133
|
+
document.release()
|
|
1134
|
+
return Result[Document, ParseError].failure(error= payload.error)
|
|
1135
|
+
Result.success:
|
|
1136
|
+
pass
|
|
1137
|
+
|
|
1138
|
+
|
|
1139
|
+
function append_quoted_string(output: ref[string.String], text_value: str) -> void:
|
|
1140
|
+
output.push_byte(byte_quote)
|
|
1141
|
+
|
|
1142
|
+
var index: ptr_uint = 0
|
|
1143
|
+
while index < text_value.len:
|
|
1144
|
+
let value = text_value.byte_at(index)
|
|
1145
|
+
if value == byte_backslash:
|
|
1146
|
+
output.append("\\\\")
|
|
1147
|
+
else if value == byte_quote:
|
|
1148
|
+
output.append("\\\"")
|
|
1149
|
+
else if value == byte_newline:
|
|
1150
|
+
output.append("\\n")
|
|
1151
|
+
else if value == byte_carriage_return:
|
|
1152
|
+
output.append("\\r")
|
|
1153
|
+
else if value == byte_tab:
|
|
1154
|
+
output.append("\\t")
|
|
1155
|
+
else if value == 8:
|
|
1156
|
+
output.append("\\b")
|
|
1157
|
+
else if value == 12:
|
|
1158
|
+
output.append("\\f")
|
|
1159
|
+
else:
|
|
1160
|
+
output.push_byte(value)
|
|
1161
|
+
index += 1
|
|
1162
|
+
|
|
1163
|
+
output.push_byte(byte_quote)
|
|
1164
|
+
|
|
1165
|
+
|
|
1166
|
+
function bare_header_name(text_value: str) -> bool:
|
|
1167
|
+
if text_value.len == 0:
|
|
1168
|
+
return false
|
|
1169
|
+
|
|
1170
|
+
var index: ptr_uint = 0
|
|
1171
|
+
while index < text_value.len:
|
|
1172
|
+
if not header_name_byte(text_value.byte_at(index)):
|
|
1173
|
+
return false
|
|
1174
|
+
index += 1
|
|
1175
|
+
|
|
1176
|
+
return true
|
|
1177
|
+
|
|
1178
|
+
|
|
1179
|
+
function append_header_name(output: ref[string.String], name: str) -> void:
|
|
1180
|
+
if bare_header_name(name):
|
|
1181
|
+
output.append(name)
|
|
1182
|
+
else:
|
|
1183
|
+
append_quoted_string(output, name)
|
|
1184
|
+
|
|
1185
|
+
|
|
1186
|
+
function append_entry_key(output: ref[string.String], key: str) -> void:
|
|
1187
|
+
append_quoted_string(output, key)
|
|
1188
|
+
|
|
1189
|
+
|
|
1190
|
+
function append_value(output: ref[string.String], value: Value) -> void:
|
|
1191
|
+
if value.kind == ValueKind.string_:
|
|
1192
|
+
append_quoted_string(output, value.string_value.as_str())
|
|
1193
|
+
return
|
|
1194
|
+
|
|
1195
|
+
if value.kind == ValueKind.integer:
|
|
1196
|
+
fmt.append_long(output, value.integer_value)
|
|
1197
|
+
return
|
|
1198
|
+
|
|
1199
|
+
if value.kind == ValueKind.boolean:
|
|
1200
|
+
fmt.append_bool(output, value.boolean_value)
|
|
1201
|
+
return
|
|
1202
|
+
|
|
1203
|
+
if value.kind == ValueKind.array_:
|
|
1204
|
+
output.push_byte(byte_left_bracket)
|
|
1205
|
+
let nested_array = value.array_value
|
|
1206
|
+
if nested_array != null:
|
|
1207
|
+
unsafe:
|
|
1208
|
+
let values = read(nested_array)
|
|
1209
|
+
var index: ptr_uint = 0
|
|
1210
|
+
while index < values.len():
|
|
1211
|
+
if index != 0:
|
|
1212
|
+
output.append(", ")
|
|
1213
|
+
|
|
1214
|
+
let item = values.values.get(index) else:
|
|
1215
|
+
fatal(c"toml.append_value missing array item")
|
|
1216
|
+
|
|
1217
|
+
append_value(output, unsafe: read(item))
|
|
1218
|
+
index += 1
|
|
1219
|
+
|
|
1220
|
+
output.push_byte(byte_right_bracket)
|
|
1221
|
+
return
|
|
1222
|
+
|
|
1223
|
+
output.push_byte(byte_left_brace)
|
|
1224
|
+
let nested_object = value.object_value
|
|
1225
|
+
if nested_object != null:
|
|
1226
|
+
unsafe:
|
|
1227
|
+
let object_entries = read(nested_object)
|
|
1228
|
+
var index: ptr_uint = 0
|
|
1229
|
+
while index < object_entries.entries.len():
|
|
1230
|
+
if index != 0:
|
|
1231
|
+
output.append(", ")
|
|
1232
|
+
|
|
1233
|
+
let entry = object_entries.entries.get(index) else:
|
|
1234
|
+
fatal(c"toml.append_value missing object entry")
|
|
1235
|
+
|
|
1236
|
+
let current = unsafe: read(entry)
|
|
1237
|
+
append_entry_key(output, current.key.as_str())
|
|
1238
|
+
output.append(" = ")
|
|
1239
|
+
append_value(output, current.value)
|
|
1240
|
+
index += 1
|
|
1241
|
+
|
|
1242
|
+
output.push_byte(byte_right_brace)
|
|
1243
|
+
|
|
1244
|
+
|
|
1245
|
+
function append_table_entries(output: ref[string.String], object_entries: Object) -> void:
|
|
1246
|
+
var index: ptr_uint = 0
|
|
1247
|
+
while index < object_entries.entries.len():
|
|
1248
|
+
let entry = object_entries.entries.get(index) else:
|
|
1249
|
+
fatal(c"toml.append_table_entries missing entry")
|
|
1250
|
+
|
|
1251
|
+
let current = unsafe: read(entry)
|
|
1252
|
+
append_entry_key(output, current.key.as_str())
|
|
1253
|
+
output.append(" = ")
|
|
1254
|
+
append_value(output, current.value)
|
|
1255
|
+
output.append("\n")
|
|
1256
|
+
index += 1
|
|
1257
|
+
|
|
1258
|
+
|
|
1259
|
+
public function render(document: Document) -> string.String:
|
|
1260
|
+
var output = string.String.create()
|
|
1261
|
+
|
|
1262
|
+
append_table_entries(ref_of(output), document.root)
|
|
1263
|
+
|
|
1264
|
+
let has_root = document.root.entries.len() > 0
|
|
1265
|
+
let has_sections = document.tables.len() > 0 or document.array_tables.len() > 0
|
|
1266
|
+
if has_root and has_sections:
|
|
1267
|
+
output.append("\n")
|
|
1268
|
+
|
|
1269
|
+
var table_index: ptr_uint = 0
|
|
1270
|
+
while table_index < document.tables.len():
|
|
1271
|
+
if table_index != 0:
|
|
1272
|
+
output.append("\n")
|
|
1273
|
+
|
|
1274
|
+
let table_ptr = document.tables.get(table_index) else:
|
|
1275
|
+
fatal(c"toml.render missing table")
|
|
1276
|
+
|
|
1277
|
+
let current = unsafe: read(table_ptr)
|
|
1278
|
+
output.push_byte(byte_left_bracket)
|
|
1279
|
+
append_header_name(ref_of(output), current.name.as_str())
|
|
1280
|
+
output.push_byte(byte_right_bracket)
|
|
1281
|
+
output.append("\n")
|
|
1282
|
+
append_table_entries(ref_of(output), current.entries)
|
|
1283
|
+
table_index += 1
|
|
1284
|
+
|
|
1285
|
+
var array_table_index: ptr_uint = 0
|
|
1286
|
+
while array_table_index < document.array_tables.len():
|
|
1287
|
+
let array_table_ptr = document.array_tables.get(array_table_index) else:
|
|
1288
|
+
fatal(c"toml.render missing array table")
|
|
1289
|
+
|
|
1290
|
+
let current = unsafe: read(array_table_ptr)
|
|
1291
|
+
var object_index: ptr_uint = 0
|
|
1292
|
+
while object_index < current.tables.len():
|
|
1293
|
+
if output.len() > 0 and not output.as_str().ends_with("\n\n"):
|
|
1294
|
+
output.append("\n")
|
|
1295
|
+
|
|
1296
|
+
output.push_byte(byte_left_bracket)
|
|
1297
|
+
output.push_byte(byte_left_bracket)
|
|
1298
|
+
append_header_name(ref_of(output), current.name.as_str())
|
|
1299
|
+
output.push_byte(byte_right_bracket)
|
|
1300
|
+
output.push_byte(byte_right_bracket)
|
|
1301
|
+
output.append("\n")
|
|
1302
|
+
|
|
1303
|
+
let object_ptr = current.tables.get(object_index) else:
|
|
1304
|
+
fatal(c"toml.render missing array table item")
|
|
1305
|
+
|
|
1306
|
+
append_table_entries(ref_of(output), unsafe: read(object_ptr))
|
|
1307
|
+
object_index += 1
|
|
1308
|
+
array_table_index += 1
|
|
1309
|
+
|
|
1310
|
+
return output
|