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/str.mt ADDED
@@ -0,0 +1,293 @@
1
+ import std.mem.arena as arena
2
+
3
+
4
+ public function cstr_len(text: cstr) -> ptr_uint:
5
+ var count: ptr_uint = 0
6
+ unsafe:
7
+ let data = ptr[char]<-text
8
+ while read(data + count) != zero[char]:
9
+ count += 1
10
+ return count
11
+
12
+
13
+ public function cstr_as_str(text: cstr) -> str:
14
+ return unsafe: str(data = ptr[char]<-text, len = cstr_len(text))
15
+
16
+
17
+ public function chars_as_str(text: ptr[char]) -> str:
18
+ return unsafe: str(data = text, len = cstr_len(cstr<-text))
19
+
20
+
21
+ public function nullable_cstr_as_str(text: cstr?) -> Option[str]:
22
+ if text == null:
23
+ return Option[str].none
24
+
25
+ return Option[str].some(value= cstr_as_str(text))
26
+
27
+
28
+ public function as_byte_span(text: str) -> span[ubyte]:
29
+ return unsafe: span[ubyte](data = ptr[ubyte]<-text.data, len = text.len)
30
+
31
+
32
+ public function utf8_byte_span_as_str(bytes: span[ubyte]) -> Option[str]:
33
+ unsafe:
34
+ let borrowed = str(data = ptr[char]<-bytes.data, len = bytes.len)
35
+ if not borrowed.is_valid_utf8():
36
+ return Option[str].none
37
+
38
+ return Option[str].some(value= borrowed)
39
+
40
+
41
+ public function utf8_continuation_byte(value: ubyte) -> bool:
42
+ return (value & 0xC0) == 0x80
43
+
44
+
45
+ function utf8_boundary(text: str, index: ptr_uint) -> bool:
46
+ if index == 0 or index == text.len:
47
+ return true
48
+
49
+ unsafe:
50
+ let value = ubyte<-read(text.data + index)
51
+ return not utf8_continuation_byte(value)
52
+
53
+
54
+ function is_ascii_space(value: ubyte) -> bool:
55
+ return value == 32 or value == 9 or value == 10 or value == 13 or value == 12
56
+
57
+
58
+ extending str:
59
+ public function byte_at(index: ptr_uint) -> ubyte:
60
+ if index >= this.len:
61
+ fatal(c"str.byte_at index out of bounds")
62
+
63
+ return unsafe: ubyte<-read(this.data + index)
64
+
65
+
66
+ public function equal(right: str) -> bool:
67
+ if this.len != right.len:
68
+ return false
69
+
70
+ var index: ptr_uint = 0
71
+ while index < this.len:
72
+ if this.byte_at(index) != right.byte_at(index):
73
+ return false
74
+ index += 1
75
+ return true
76
+
77
+
78
+ public function starts_with(prefix: str) -> bool:
79
+ if prefix.len > this.len:
80
+ return false
81
+
82
+ var index: ptr_uint = 0
83
+ while index < prefix.len:
84
+ if this.byte_at(index) != prefix.byte_at(index):
85
+ return false
86
+ index += 1
87
+ return true
88
+
89
+
90
+ public function ends_with(suffix: str) -> bool:
91
+ if suffix.len > this.len:
92
+ return false
93
+
94
+ let offset = this.len - suffix.len
95
+ var index: ptr_uint = 0
96
+ while index < suffix.len:
97
+ if this.byte_at(offset + index) != suffix.byte_at(index):
98
+ return false
99
+ index += 1
100
+ return true
101
+
102
+
103
+ public function find_byte(value: ubyte) -> Option[ptr_uint]:
104
+ var index: ptr_uint = 0
105
+ while index < this.len:
106
+ if this.byte_at(index) == value:
107
+ return Option[ptr_uint].some(value= index)
108
+ index += 1
109
+ return Option[ptr_uint].none
110
+
111
+
112
+ public function trim_ascii_whitespace() -> str:
113
+ var start: ptr_uint = 0
114
+ while start < this.len and is_ascii_space(this.byte_at(start)):
115
+ start += 1
116
+
117
+ var stop = this.len
118
+ while stop > start and is_ascii_space(this.byte_at(stop - 1)):
119
+ stop -= 1
120
+
121
+ return unsafe: str(data = this.data + start, len = stop - start)
122
+
123
+
124
+ public function is_valid_utf8() -> bool:
125
+ var index: ptr_uint = 0
126
+ while index < this.len:
127
+ let first = this.byte_at(index)
128
+ if first < 0x80:
129
+ index += 1
130
+ else if first >= 0xC2 and first <= 0xDF:
131
+ if index + 1 >= this.len or not utf8_continuation_byte(this.byte_at(index + 1)):
132
+ return false
133
+ index += 2
134
+ else if first == 0xE0:
135
+ if index + 2 >= this.len:
136
+ return false
137
+ let second = this.byte_at(index + 1)
138
+ if second < 0xA0 or second > 0xBF or not utf8_continuation_byte(this.byte_at(index + 2)):
139
+ return false
140
+ index += 3
141
+ else if first >= 0xE1 and first <= 0xEC:
142
+ if (
143
+ index + 2 >= this.len
144
+ or not utf8_continuation_byte(this.byte_at(index + 1))
145
+ or not utf8_continuation_byte(this.byte_at(index + 2))
146
+ ):
147
+ return false
148
+ index += 3
149
+ else if first == 0xED:
150
+ if index + 2 >= this.len:
151
+ return false
152
+ let second = this.byte_at(index + 1)
153
+ if second < 0x80 or second > 0x9F or not utf8_continuation_byte(this.byte_at(index + 2)):
154
+ return false
155
+ index += 3
156
+ else if first >= 0xEE and first <= 0xEF:
157
+ if (
158
+ index + 2 >= this.len
159
+ or not utf8_continuation_byte(this.byte_at(index + 1))
160
+ or not utf8_continuation_byte(this.byte_at(index + 2))
161
+ ):
162
+ return false
163
+ index += 3
164
+ else if first == 0xF0:
165
+ if index + 3 >= this.len:
166
+ return false
167
+ let second = this.byte_at(index + 1)
168
+ if (
169
+ second < 0x90
170
+ or second > 0xBF
171
+ or not utf8_continuation_byte(this.byte_at(index + 2))
172
+ or not utf8_continuation_byte(this.byte_at(index + 3))
173
+ ):
174
+ return false
175
+ index += 4
176
+ else if first >= 0xF1 and first <= 0xF3:
177
+ if (
178
+ index + 3 >= this.len
179
+ or not utf8_continuation_byte(this.byte_at(index + 1))
180
+ or not utf8_continuation_byte(this.byte_at(index + 2))
181
+ or not utf8_continuation_byte(this.byte_at(index + 3))
182
+ ):
183
+ return false
184
+ index += 4
185
+ else if first == 0xF4:
186
+ if index + 3 >= this.len:
187
+ return false
188
+ let second = this.byte_at(index + 1)
189
+ if (
190
+ second < 0x80
191
+ or second > 0x8F
192
+ or not utf8_continuation_byte(this.byte_at(index + 2))
193
+ or not utf8_continuation_byte(this.byte_at(index + 3))
194
+ ):
195
+ return false
196
+ index += 4
197
+ else:
198
+ return false
199
+
200
+ return true
201
+
202
+
203
+ public function slice(start: ptr_uint, len: ptr_uint) -> str:
204
+ if start > this.len:
205
+ fatal(c"str slice start out of bounds")
206
+ if len > this.len - start:
207
+ fatal(c"str slice length out of bounds")
208
+
209
+ if not utf8_boundary(this, start):
210
+ fatal(c"str slice start must be a UTF-8 boundary")
211
+ var actual_stop = start + len
212
+ if not utf8_boundary(this, actual_stop):
213
+ fatal(c"str slice end must be a UTF-8 boundary")
214
+
215
+ return unsafe: str(data = this.data + start, len = actual_stop - start)
216
+
217
+
218
+ public function find_substring(needle: str) -> Option[ptr_uint]:
219
+ if needle.len == 0:
220
+ return Option[ptr_uint].some(value= 0)
221
+ if needle.len > this.len:
222
+ return Option[ptr_uint].none
223
+
224
+ let limit = this.len - needle.len
225
+ var offset: ptr_uint = 0
226
+ while offset <= limit:
227
+ var matched = true
228
+ var index: ptr_uint = 0
229
+ while index < needle.len:
230
+ if this.byte_at(offset + index) != needle.byte_at(index):
231
+ matched = false
232
+ break
233
+ index += 1
234
+ if matched:
235
+ return Option[ptr_uint].some(value= offset)
236
+ offset += 1
237
+
238
+ return Option[ptr_uint].none
239
+
240
+
241
+ public function contains_substring(needle: str) -> bool:
242
+ return this.find_substring(needle).is_some()
243
+
244
+
245
+ public static function hash(value: const_ptr[str]) -> uint:
246
+ let fnv_offset: uint = 0x811C9DC5
247
+ let fnv_prime: uint = 0x01000193
248
+
249
+ var result = fnv_offset
250
+ unsafe:
251
+ let view = read(value)
252
+ var index: ptr_uint = 0
253
+ while index < view.len:
254
+ let byte_value = uint<-view.byte_at(index)
255
+ result = (result ^ byte_value) * fnv_prime
256
+ index += 1
257
+ return result
258
+
259
+
260
+ public static function equal(left: const_ptr[str], right: const_ptr[str]) -> bool:
261
+ unsafe:
262
+ return read(left).equal(read(right))
263
+
264
+
265
+ public static function order(left: const_ptr[str], right: const_ptr[str]) -> int:
266
+ unsafe:
267
+ let left_view = read(left)
268
+ let right_view = read(right)
269
+ var min_len = left_view.len
270
+ if right_view.len < min_len:
271
+ min_len = right_view.len
272
+
273
+ var index: ptr_uint = 0
274
+ while index < min_len:
275
+ let lb = int<-left_view.byte_at(index)
276
+ let rb = int<-right_view.byte_at(index)
277
+ if lb != rb:
278
+ return lb - rb
279
+ index += 1
280
+
281
+ let left_len = int<-left_view.len
282
+ let right_len = int<-right_view.len
283
+ return left_len - right_len
284
+
285
+
286
+ public function compare(right: str) -> int:
287
+ var left_copy: str = this
288
+ var right_copy: str = right
289
+ return str.order(ptr_of(left_copy), ptr_of(right_copy))
290
+
291
+
292
+ public function to_cstr(space: ref[arena.Arena]) -> cstr:
293
+ return space.to_cstr(this)
data/std/string.mt ADDED
@@ -0,0 +1,234 @@
1
+ import std.str as text_ops
2
+ import std.mem.arena as arena
3
+ import std.mem.heap as heap
4
+ import std.vec as vec
5
+
6
+ public struct String:
7
+ data: ptr[ubyte]?
8
+ len: ptr_uint
9
+ capacity: ptr_uint
10
+ owns_storage: bool
11
+
12
+
13
+ extending String:
14
+ public static function create() -> String:
15
+ return String(data = null, len = 0, capacity = 0, owns_storage = true)
16
+
17
+
18
+ public static function with_capacity(capacity: ptr_uint) -> String:
19
+ var result = String.create()
20
+ result.reserve(capacity)
21
+ return result
22
+
23
+
24
+ public static function from_str(text: str) -> String:
25
+ var result = String.with_capacity(text.len)
26
+ result.append(text)
27
+ return result
28
+
29
+
30
+ public function len() -> ptr_uint:
31
+ return this.len
32
+
33
+
34
+ public function capacity() -> ptr_uint:
35
+ return this.capacity
36
+
37
+
38
+ public function is_empty() -> bool:
39
+ return this.len == 0
40
+
41
+
42
+ public function equal(other: String) -> bool:
43
+ return this.as_str().equal(other.as_str())
44
+
45
+
46
+ public editable function clear() -> void:
47
+ this.len = 0
48
+
49
+
50
+ public editable function truncate(new_len: ptr_uint) -> void:
51
+ if new_len > this.len:
52
+ fatal(c"string.truncate new length exceeds current length")
53
+ this.len = new_len
54
+
55
+
56
+ public editable function release() -> void:
57
+ if this.owns_storage:
58
+ heap.release(this.data)
59
+
60
+ this.data = null
61
+ this.len = 0
62
+ this.capacity = 0
63
+ this.owns_storage = true
64
+
65
+
66
+ public static function hash(value: const_ptr[String]) -> uint:
67
+ let fnv_offset: uint = 0x811C9DC5
68
+ let fnv_prime: uint = 0x01000193
69
+
70
+ unsafe:
71
+ let view = read(value)
72
+ var result = fnv_offset
73
+ let raw = view.as_str()
74
+ var index: ptr_uint = 0
75
+ while index < raw.len:
76
+ let byte_value = uint<-raw.byte_at(index)
77
+ result = (result ^ byte_value) * fnv_prime
78
+ index += 1
79
+ return result
80
+
81
+
82
+ public static function equal(left: const_ptr[String], right: const_ptr[String]) -> bool:
83
+ unsafe:
84
+ let left_view = read(left)
85
+ let right_view = read(right)
86
+ return left_view.as_str().equal(right_view.as_str())
87
+
88
+
89
+ public static function order(left: const_ptr[String], right: const_ptr[String]) -> int:
90
+ unsafe:
91
+ let left_view = read(left)
92
+ let right_view = read(right)
93
+ return left_view.as_str().compare(right_view.as_str())
94
+
95
+
96
+ public function starts_with(prefix: str) -> bool:
97
+ return this.as_str().starts_with(prefix)
98
+
99
+
100
+ public function ends_with(suffix: str) -> bool:
101
+ return this.as_str().ends_with(suffix)
102
+
103
+
104
+ public function find_substring(needle: str) -> Option[ptr_uint]:
105
+ return this.as_str().find_substring(needle)
106
+
107
+
108
+ public function contains_substring(needle: str) -> bool:
109
+ return this.as_str().contains_substring(needle)
110
+
111
+
112
+ public editable function reserve(min_capacity: ptr_uint) -> void:
113
+ if min_capacity <= this.capacity:
114
+ return
115
+
116
+ if not this.owns_storage:
117
+ fatal(c"string.reserve cannot grow borrowed storage")
118
+
119
+ var new_capacity = this.capacity
120
+ if new_capacity == 0:
121
+ new_capacity = 4
122
+
123
+ while new_capacity < min_capacity:
124
+ if new_capacity > heap.ptr_uint_max / 2:
125
+ new_capacity = min_capacity
126
+ else:
127
+ new_capacity *= 2
128
+
129
+ let resized = heap.resize[ubyte](this.data, new_capacity) else:
130
+ fatal(c"string.reserve out of memory")
131
+
132
+ this.data = resized
133
+ this.capacity = new_capacity
134
+
135
+
136
+ public editable function push_byte(value: ubyte) -> void:
137
+ if this.len == this.capacity:
138
+ this.reserve(this.len + 1)
139
+
140
+ let data = this.data else:
141
+ fatal(c"string.push_byte missing storage")
142
+
143
+ unsafe:
144
+ let data_ptr = data
145
+ read(data_ptr + this.len) = value
146
+ this.len += 1
147
+
148
+
149
+ public editable function append(suffix: str) -> void:
150
+ if suffix.len == 0:
151
+ return
152
+
153
+ let current_len = this.len
154
+ if suffix.len > heap.ptr_uint_max - current_len:
155
+ fatal(c"string.append size overflow")
156
+
157
+ let new_len = current_len + suffix.len
158
+ let needs_growth = new_len > this.capacity
159
+
160
+ var copied: ptr[ubyte]? = null
161
+ if needs_growth:
162
+ copied = heap.must_alloc[ubyte](suffix.len)
163
+ unsafe: heap.copy_bytes(copied, ptr[ubyte]<-suffix.data, suffix.len)
164
+
165
+ this.reserve(new_len)
166
+
167
+ let data = this.data else:
168
+ fatal(c"string.append missing storage")
169
+
170
+ unsafe:
171
+ let destination = data + current_len
172
+ if copied != null:
173
+ heap.copy_bytes(destination, copied, suffix.len)
174
+ heap.release(copied)
175
+ else:
176
+ heap.copy_bytes(destination, ptr[ubyte]<-suffix.data, suffix.len)
177
+
178
+ this.len = new_len
179
+
180
+
181
+ public editable function append_format(text: str) -> void:
182
+ this.append(text)
183
+
184
+
185
+ public editable function assign(value_text: str) -> void:
186
+ this.clear()
187
+ this.append(value_text)
188
+
189
+
190
+ public editable function assign_format(text: str) -> void:
191
+ this.assign(text)
192
+
193
+
194
+ public function as_str() -> str:
195
+ let data = this.data
196
+ if data == null and this.len != 0:
197
+ fatal(c"string.as_str requires storage when len > 0")
198
+
199
+ let borrowed = unsafe: str(data = ptr[char]<-data, len = this.len)
200
+ if not borrowed.is_valid_utf8():
201
+ fatal(c"string.as_str text must be valid UTF-8")
202
+
203
+ return borrowed
204
+
205
+
206
+ public function to_cstr(space: ref[arena.Arena]) -> cstr:
207
+ return space.to_cstr(this.as_str())
208
+
209
+
210
+ public function split(separator: str) -> vec.Vec[String]:
211
+ var result = vec.Vec[String].create()
212
+ var remaining = this.as_str()
213
+ while true:
214
+ let found = remaining.find_substring(separator)
215
+ let idx = found else:
216
+ break
217
+ result.push(String.from_str(remaining.slice(0, idx)))
218
+ remaining = remaining.slice(idx + separator.len, remaining.len - idx - separator.len)
219
+ result.push(String.from_str(remaining))
220
+ return result
221
+
222
+
223
+ public function replace(old_substr: str, new_substr: str) -> String:
224
+ var result = String.create()
225
+ var remaining = this.as_str()
226
+ while true:
227
+ let found = remaining.find_substring(old_substr)
228
+ let idx = found else:
229
+ break
230
+ result.append(remaining.slice(0, idx))
231
+ result.append(new_substr)
232
+ remaining = remaining.slice(idx + old_substr.len, remaining.len - idx - old_substr.len)
233
+ result.append(remaining)
234
+ return result