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
data/std/cookie.mt
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import std.str as text
|
|
2
|
+
import std.string as string
|
|
3
|
+
import std.time as time
|
|
4
|
+
|
|
5
|
+
public struct Cookie:
|
|
6
|
+
name: string.String
|
|
7
|
+
value: string.String
|
|
8
|
+
domain: Option[string.String]
|
|
9
|
+
path: Option[string.String]
|
|
10
|
+
max_age: Option[ptr_int]
|
|
11
|
+
expires: Option[time.Timestamp]
|
|
12
|
+
secure: bool
|
|
13
|
+
http_only: bool
|
|
14
|
+
same_site: Option[string.String]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
public function parse_set_cookie(header_value: str) -> Option[Cookie]:
|
|
18
|
+
var pos: ptr_uint = 0
|
|
19
|
+
|
|
20
|
+
let semi = find_byte_from(header_value, 59, pos)
|
|
21
|
+
var end = header_value.len
|
|
22
|
+
match semi:
|
|
23
|
+
Option.none:
|
|
24
|
+
pass
|
|
25
|
+
Option.some as s:
|
|
26
|
+
end = s.value
|
|
27
|
+
|
|
28
|
+
let part = header_value.slice(pos, end - pos).trim_ascii_whitespace()
|
|
29
|
+
if part.len == 0:
|
|
30
|
+
return Option[Cookie].none
|
|
31
|
+
|
|
32
|
+
var cookie = parse_name_value(part)?
|
|
33
|
+
match semi:
|
|
34
|
+
Option.none:
|
|
35
|
+
return Option[Cookie].some(value = cookie)
|
|
36
|
+
Option.some as s:
|
|
37
|
+
pos = s.value + 1
|
|
38
|
+
|
|
39
|
+
while pos < header_value.len:
|
|
40
|
+
let next_semi = find_byte_from(header_value, 59, pos)
|
|
41
|
+
var next_end = header_value.len
|
|
42
|
+
match next_semi:
|
|
43
|
+
Option.none:
|
|
44
|
+
pass
|
|
45
|
+
Option.some as ns:
|
|
46
|
+
next_end = ns.value
|
|
47
|
+
|
|
48
|
+
let next_part = header_value.slice(pos, next_end - pos).trim_ascii_whitespace()
|
|
49
|
+
if next_part.len > 0:
|
|
50
|
+
apply_attribute(ref_of(cookie), next_part)
|
|
51
|
+
|
|
52
|
+
match next_semi:
|
|
53
|
+
Option.none:
|
|
54
|
+
pos = header_value.len
|
|
55
|
+
Option.some as ns:
|
|
56
|
+
pos = ns.value + 1
|
|
57
|
+
|
|
58
|
+
return Option[Cookie].some(value = cookie)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
function parse_name_value(text_value: str) -> Option[Cookie]:
|
|
62
|
+
let eq = text_value.find_byte(61)
|
|
63
|
+
match eq:
|
|
64
|
+
Option.none:
|
|
65
|
+
return Option[Cookie].none
|
|
66
|
+
Option.some as e:
|
|
67
|
+
let name_text = text_value.slice(0, e.value).trim_ascii_whitespace()
|
|
68
|
+
let value_text = text_value.slice(e.value + 1, text_value.len - e.value - 1).trim_ascii_whitespace()
|
|
69
|
+
|
|
70
|
+
var cookie_value = string.String.from_str(value_text)
|
|
71
|
+
if cookie_value.len() >= 2 and cookie_value.as_str().byte_at(0) == 34:
|
|
72
|
+
let last = cookie_value.len() - 1
|
|
73
|
+
if cookie_value.as_str().byte_at(last) == 34:
|
|
74
|
+
let inner = cookie_value.as_str().slice(1, last - 1)
|
|
75
|
+
cookie_value.assign(inner)
|
|
76
|
+
|
|
77
|
+
let cookie = Cookie(
|
|
78
|
+
name = string.String.from_str(name_text),
|
|
79
|
+
value = cookie_value,
|
|
80
|
+
domain = Option[string.String].none,
|
|
81
|
+
path = Option[string.String].none,
|
|
82
|
+
max_age = Option[ptr_int].none,
|
|
83
|
+
expires = Option[time.Timestamp].none,
|
|
84
|
+
secure = false,
|
|
85
|
+
http_only = false,
|
|
86
|
+
same_site = Option[string.String].none
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
return Option[Cookie].some(value = cookie)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
function apply_attribute(cookie: ref[Cookie], attribute_text: str) -> void:
|
|
93
|
+
let eq = attribute_text.find_byte(61)
|
|
94
|
+
match eq:
|
|
95
|
+
Option.none:
|
|
96
|
+
var normalized = ascii_lower(attribute_text)
|
|
97
|
+
defer normalized.release()
|
|
98
|
+
|
|
99
|
+
if normalized.as_str().equal("secure"):
|
|
100
|
+
cookie.secure = true
|
|
101
|
+
else if normalized.as_str().equal("httponly"):
|
|
102
|
+
cookie.http_only = true
|
|
103
|
+
|
|
104
|
+
Option.some as e:
|
|
105
|
+
let key_text = attribute_text.slice(0, e.value).trim_ascii_whitespace()
|
|
106
|
+
let value_text = attribute_text.slice(e.value + 1, attribute_text.len - e.value - 1).trim_ascii_whitespace()
|
|
107
|
+
|
|
108
|
+
var normalized_key = ascii_lower(key_text)
|
|
109
|
+
defer normalized_key.release()
|
|
110
|
+
|
|
111
|
+
if normalized_key.as_str().equal("domain"):
|
|
112
|
+
cookie.domain = Option[string.String].some(value = string.String.from_str(value_text))
|
|
113
|
+
else if normalized_key.as_str().equal("path"):
|
|
114
|
+
cookie.path = Option[string.String].some(value = string.String.from_str(value_text))
|
|
115
|
+
else if normalized_key.as_str().equal("max-age"):
|
|
116
|
+
let parsed = parse_decimal(value_text)
|
|
117
|
+
match parsed:
|
|
118
|
+
Option.some as payload:
|
|
119
|
+
cookie.max_age = Option[ptr_int].some(value = ptr_int<-payload.value)
|
|
120
|
+
Option.none:
|
|
121
|
+
pass
|
|
122
|
+
else if normalized_key.as_str().equal("samesite"):
|
|
123
|
+
cookie.same_site = Option[string.String].some(value = ascii_lower(value_text))
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
public function format_cookie(cookie: Cookie) -> string.String:
|
|
127
|
+
var result = string.String.with_capacity(cookie.name.len() + cookie.value.len() + 128)
|
|
128
|
+
|
|
129
|
+
result.append(cookie.name.as_str())
|
|
130
|
+
result.push_byte(61)
|
|
131
|
+
result.append(cookie.value.as_str())
|
|
132
|
+
|
|
133
|
+
return result
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
function ascii_lower(text_value: str) -> string.String:
|
|
137
|
+
var result = string.String.with_capacity(text_value.len)
|
|
138
|
+
var index: ptr_uint = 0
|
|
139
|
+
while index < text_value.len:
|
|
140
|
+
let value = text_value.byte_at(index)
|
|
141
|
+
if value >= 65 and value <= 90:
|
|
142
|
+
result.push_byte(value + 32)
|
|
143
|
+
else:
|
|
144
|
+
result.push_byte(value)
|
|
145
|
+
index += 1
|
|
146
|
+
|
|
147
|
+
return result
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
function find_byte_from(data: str, target: ubyte, start: ptr_uint) -> Option[ptr_uint]:
|
|
151
|
+
var index = start
|
|
152
|
+
while index < data.len:
|
|
153
|
+
if data.byte_at(index) == target:
|
|
154
|
+
return Option[ptr_uint].some(value = index)
|
|
155
|
+
index += 1
|
|
156
|
+
|
|
157
|
+
return Option[ptr_uint].none
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
function parse_decimal(text_value: str) -> Option[ptr_uint]:
|
|
161
|
+
if text_value.len == 0:
|
|
162
|
+
return Option[ptr_uint].none
|
|
163
|
+
|
|
164
|
+
var value: ptr_uint = 0
|
|
165
|
+
var index: ptr_uint = 0
|
|
166
|
+
while index < text_value.len:
|
|
167
|
+
let current = text_value.byte_at(index)
|
|
168
|
+
if current < 48 or current > 57:
|
|
169
|
+
return Option[ptr_uint].none
|
|
170
|
+
|
|
171
|
+
value = value * 10 + ptr_uint<-(current - 48)
|
|
172
|
+
index += 1
|
|
173
|
+
|
|
174
|
+
return Option[ptr_uint].some(value = value)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
extending Cookie:
|
|
178
|
+
public editable function release() -> void:
|
|
179
|
+
this.name.release()
|
|
180
|
+
this.value.release()
|
|
181
|
+
|
|
182
|
+
match this.domain:
|
|
183
|
+
Option.some as payload:
|
|
184
|
+
payload.value.release()
|
|
185
|
+
Option.none:
|
|
186
|
+
pass
|
|
187
|
+
|
|
188
|
+
match this.path:
|
|
189
|
+
Option.some as payload:
|
|
190
|
+
payload.value.release()
|
|
191
|
+
Option.none:
|
|
192
|
+
pass
|
|
193
|
+
|
|
194
|
+
match this.same_site:
|
|
195
|
+
Option.some as payload:
|
|
196
|
+
payload.value.release()
|
|
197
|
+
Option.none:
|
|
198
|
+
pass
|
data/std/counter.mt
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import std.linked_map as linked_map
|
|
2
|
+
import std.linked_map_view as linked_map_view
|
|
3
|
+
import std.mem.heap as heap
|
|
4
|
+
|
|
5
|
+
public struct Entry[T]:
|
|
6
|
+
key: const_ptr[T]
|
|
7
|
+
count: ptr_uint
|
|
8
|
+
|
|
9
|
+
public struct Entries[T]:
|
|
10
|
+
values: linked_map_view.SnapshotEntries[T, ptr_uint]
|
|
11
|
+
|
|
12
|
+
public struct Counter[T]:
|
|
13
|
+
values: linked_map.LinkedMap[T, ptr_uint]
|
|
14
|
+
total: ptr_uint
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
extending Counter[T]:
|
|
18
|
+
public static function create() -> Counter[T]:
|
|
19
|
+
return Counter[T](values = linked_map.LinkedMap[T, ptr_uint].create(), total = 0)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
public static function with_capacity(capacity: ptr_uint) -> Counter[T]:
|
|
23
|
+
var result = Counter[T].create()
|
|
24
|
+
result.reserve(capacity)
|
|
25
|
+
return result
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
public function len() -> ptr_uint:
|
|
29
|
+
return this.values.len()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
public function total_count() -> ptr_uint:
|
|
33
|
+
return this.total
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
public function capacity() -> ptr_uint:
|
|
37
|
+
return this.values.capacity()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
public function is_empty() -> bool:
|
|
41
|
+
return this.total == 0
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
public function count(value: T) -> ptr_uint:
|
|
45
|
+
let stored = this.values.get(value) else:
|
|
46
|
+
return 0
|
|
47
|
+
|
|
48
|
+
unsafe:
|
|
49
|
+
return read(stored)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
public function contains(value: T) -> bool:
|
|
53
|
+
return this.values.contains(value)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
public function iter() -> Entries[T]:
|
|
57
|
+
return this.entries()
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
public function keys() -> linked_map.Keys[T, ptr_uint]:
|
|
61
|
+
return this.values.keys()
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
public function counts() -> linked_map_view.SnapshotValues[T, ptr_uint]:
|
|
65
|
+
return linked_map_view.SnapshotValues[T, ptr_uint].create(this.values.entries())
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
public function entries() -> Entries[T]:
|
|
69
|
+
return Entries[T](values = linked_map_view.SnapshotEntries[T, ptr_uint].create(this.values.entries()))
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
public editable function clear() -> void:
|
|
73
|
+
this.values.clear()
|
|
74
|
+
this.total = 0
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
public editable function release() -> void:
|
|
78
|
+
this.values.release()
|
|
79
|
+
this.total = 0
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
public editable function reserve(min_capacity: ptr_uint) -> void:
|
|
83
|
+
this.values.reserve(min_capacity)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
public editable function add(value: T, amount: ptr_uint) -> ptr_uint:
|
|
87
|
+
if amount == 0:
|
|
88
|
+
let stored = this.values.get(value) else:
|
|
89
|
+
return 0
|
|
90
|
+
|
|
91
|
+
unsafe:
|
|
92
|
+
return read(stored)
|
|
93
|
+
|
|
94
|
+
if this.total > heap.ptr_uint_max - amount:
|
|
95
|
+
fatal(c"counter.Counter.add total count overflow")
|
|
96
|
+
|
|
97
|
+
let current = this.values.get_or_insert(value, 0z)
|
|
98
|
+
unsafe:
|
|
99
|
+
if read(current) > heap.ptr_uint_max - amount:
|
|
100
|
+
fatal(c"counter.Counter.add entry count overflow")
|
|
101
|
+
read(current) += amount
|
|
102
|
+
|
|
103
|
+
this.total += amount
|
|
104
|
+
unsafe:
|
|
105
|
+
return read(current)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
public editable function increment(value: T) -> ptr_uint:
|
|
109
|
+
return this.add(value, 1)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
public editable function remove_one(value: T) -> bool:
|
|
113
|
+
let current = this.values.get(value) else:
|
|
114
|
+
return false
|
|
115
|
+
|
|
116
|
+
unsafe:
|
|
117
|
+
let count = read(current)
|
|
118
|
+
if count <= 1:
|
|
119
|
+
let removed = this.values.remove(value)
|
|
120
|
+
match removed:
|
|
121
|
+
Option.none:
|
|
122
|
+
fatal(c"counter.Counter.remove_one missing value")
|
|
123
|
+
Option.some:
|
|
124
|
+
if this.total == 0:
|
|
125
|
+
fatal(c"counter.Counter.remove_one missing total")
|
|
126
|
+
this.total -= 1
|
|
127
|
+
return true
|
|
128
|
+
|
|
129
|
+
read(current) = count - 1
|
|
130
|
+
|
|
131
|
+
if this.total == 0:
|
|
132
|
+
fatal(c"counter.Counter.remove_one missing total")
|
|
133
|
+
this.total -= 1
|
|
134
|
+
return true
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
public editable function remove(value: T) -> Option[ptr_uint]:
|
|
138
|
+
let removed = this.values.remove(value)
|
|
139
|
+
match removed:
|
|
140
|
+
Option.none:
|
|
141
|
+
return Option[ptr_uint].none
|
|
142
|
+
Option.some as payload:
|
|
143
|
+
if this.total < payload.value:
|
|
144
|
+
fatal(c"counter.Counter.remove total underflow")
|
|
145
|
+
this.total -= payload.value
|
|
146
|
+
return Option[ptr_uint].some(value = payload.value)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
extending Entries[T]:
|
|
150
|
+
public function iter() -> Entries[T]:
|
|
151
|
+
return this
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
public editable function next() -> bool:
|
|
155
|
+
return this.values.next()
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
public function current() -> Entry[T]:
|
|
159
|
+
let entry = this.values.current()
|
|
160
|
+
return Entry[T](key = entry.key, count = entry.value)
|
data/std/crypto.mt
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import std.bytes as bytes
|
|
2
|
+
import std.c.crypto as raw
|
|
3
|
+
import std.mem.heap as heap
|
|
4
|
+
import std.string as string
|
|
5
|
+
|
|
6
|
+
public struct Error:
|
|
7
|
+
message: string.String
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
function status_error(message: str) -> Error:
|
|
11
|
+
return Error(message = string.String.from_str(message))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
public function sha256(data: span[ubyte]) -> bytes.Bytes:
|
|
15
|
+
let digest = heap.must_alloc[ubyte](raw.SHA256_DIGEST_LENGTH)
|
|
16
|
+
let ok = raw.mt_sha256(data.data, data.len, digest)
|
|
17
|
+
if ok == 0:
|
|
18
|
+
heap.release(digest)
|
|
19
|
+
return bytes.Bytes.empty()
|
|
20
|
+
|
|
21
|
+
return bytes.Bytes(data = digest, len = raw.SHA256_DIGEST_LENGTH)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
public function sha256_to_str(data: span[ubyte]) -> string.String:
|
|
25
|
+
var digest = sha256(data)
|
|
26
|
+
defer digest.release()
|
|
27
|
+
|
|
28
|
+
var result = string.String.with_capacity(raw.SHA256_DIGEST_LENGTH * 2)
|
|
29
|
+
var index: ptr_uint = 0
|
|
30
|
+
let digest_span = digest.as_span()
|
|
31
|
+
while index < raw.SHA256_DIGEST_LENGTH:
|
|
32
|
+
let value = unsafe: read(digest_span.data + index)
|
|
33
|
+
let high = value >> 4
|
|
34
|
+
let low = value & 0x0F
|
|
35
|
+
result.push_byte(hex_digit(high))
|
|
36
|
+
result.push_byte(hex_digit(low))
|
|
37
|
+
index += 1
|
|
38
|
+
|
|
39
|
+
return result
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
public function hmac_sha256(key: span[ubyte], data: span[ubyte]) -> bytes.Bytes:
|
|
43
|
+
let digest = heap.must_alloc[ubyte](raw.SHA256_DIGEST_LENGTH)
|
|
44
|
+
let ok = raw.mt_hmac_sha256(key.data, key.len, data.data, data.len, digest)
|
|
45
|
+
if ok == 0:
|
|
46
|
+
heap.release(digest)
|
|
47
|
+
return bytes.Bytes.empty()
|
|
48
|
+
|
|
49
|
+
return bytes.Bytes(data = digest, len = raw.SHA256_DIGEST_LENGTH)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
public function random_bytes(count: ptr_uint) -> Result[bytes.Bytes, Error]:
|
|
53
|
+
if count == 0:
|
|
54
|
+
return Result[bytes.Bytes, Error].failure(error = status_error("random_bytes: count must be greater than zero"))
|
|
55
|
+
|
|
56
|
+
let buffer = heap.must_alloc[ubyte](count)
|
|
57
|
+
let ok = raw.mt_random_bytes(buffer, count)
|
|
58
|
+
if ok == 0:
|
|
59
|
+
heap.release(buffer)
|
|
60
|
+
return Result[bytes.Bytes, Error].failure(error = status_error("random_bytes: failed to generate random data"))
|
|
61
|
+
|
|
62
|
+
return Result[bytes.Bytes, Error].success(value = bytes.Bytes(data = buffer, len = count))
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
function hex_digit(value: ubyte) -> ubyte:
|
|
66
|
+
if value < 10:
|
|
67
|
+
return 48 + value
|
|
68
|
+
|
|
69
|
+
return 97 + (value - 10)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
extending Error:
|
|
73
|
+
public editable function release() -> void:
|
|
74
|
+
this.message.release()
|
data/std/cstring.mt
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import std.c.string as c
|
|
2
|
+
|
|
3
|
+
public foreign function copy_bytes(destination: ptr[void], source: const_ptr[void], size_bytes: ptr_uint) -> ptr[void] = c.mt_string_memcpy
|
|
4
|
+
public foreign function move_bytes(destination: ptr[void], source: const_ptr[void], size_bytes: ptr_uint) -> ptr[void] = c.mt_string_memmove
|
|
5
|
+
public foreign function set_bytes(destination: ptr[void], value: int, size_bytes: ptr_uint) -> ptr[void] = c.mt_string_memset
|
|
6
|
+
public foreign function compare_bytes(left: const_ptr[void], right: const_ptr[void], size_bytes: ptr_uint) -> int = c.mt_string_memcmp
|
|
7
|
+
public foreign function find_byte(source: const_ptr[void], value: int, size_bytes: ptr_uint) -> ptr[void]? = c.mt_string_memchr
|
|
8
|
+
public foreign function length(text: str as cstr) -> ptr_uint = c.mt_string_strlen
|
|
9
|
+
public foreign function compare(left: str as cstr, right: str as cstr) -> int = c.mt_string_strcmp
|
|
10
|
+
public foreign function compare_prefix(left: str as cstr, right: str as cstr, size_bytes: ptr_uint) -> int = c.mt_string_strncmp
|
|
11
|
+
public foreign function find_char(text: str as cstr, value: int) -> ptr[char]? = c.mt_string_strchr
|
|
12
|
+
public foreign function find_last_char(text: str as cstr, value: int) -> ptr[char]? = c.mt_string_strrchr
|
|
13
|
+
public foreign function find_substring(haystack: str as cstr, needle: str as cstr) -> ptr[char]? = c.mt_string_strstr
|
data/std/ctype.mt
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import std.c.ctype as c
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
public function is_alnum(value: int) -> bool:
|
|
5
|
+
return c.mt_ctype_isalnum(value) != 0
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
public function is_alpha(value: int) -> bool:
|
|
9
|
+
return c.mt_ctype_isalpha(value) != 0
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
public function is_blank(value: int) -> bool:
|
|
13
|
+
return c.mt_ctype_isblank(value) != 0
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
public function is_cntrl(value: int) -> bool:
|
|
17
|
+
return c.mt_ctype_iscntrl(value) != 0
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
public function is_digit(value: int) -> bool:
|
|
21
|
+
return c.mt_ctype_isdigit(value) != 0
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
public function is_graph(value: int) -> bool:
|
|
25
|
+
return c.mt_ctype_isgraph(value) != 0
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
public function is_lower(value: int) -> bool:
|
|
29
|
+
return c.mt_ctype_islower(value) != 0
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
public function is_print(value: int) -> bool:
|
|
33
|
+
return c.mt_ctype_isprint(value) != 0
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
public function is_punct(value: int) -> bool:
|
|
37
|
+
return c.mt_ctype_ispunct(value) != 0
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
public function is_space(value: int) -> bool:
|
|
41
|
+
return c.mt_ctype_isspace(value) != 0
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
public function is_upper(value: int) -> bool:
|
|
45
|
+
return c.mt_ctype_isupper(value) != 0
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
public function is_xdigit(value: int) -> bool:
|
|
49
|
+
return c.mt_ctype_isxdigit(value) != 0
|
|
50
|
+
|
|
51
|
+
public foreign function to_lower(value: int) -> int = c.mt_ctype_tolower
|
|
52
|
+
public foreign function to_upper(value: int) -> int = c.mt_ctype_toupper
|