@shd101wyy/yo 0.0.26 → 0.0.28
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.
- package/README.md +7 -6
- package/out/cjs/index.cjs +568 -563
- package/out/cjs/yo-cli.cjs +686 -556
- package/out/esm/index.mjs +509 -504
- package/out/types/src/build-runner.d.ts +22 -0
- package/out/types/src/cache.d.ts +3 -0
- package/out/types/src/codegen/async/state-machine.d.ts +1 -1
- package/out/types/src/codegen/codegen-c.d.ts +3 -0
- package/out/types/src/codegen/exprs/await.d.ts +1 -0
- package/out/types/src/codegen/exprs/return.d.ts +1 -0
- package/out/types/src/codegen/exprs/while.d.ts +1 -1
- package/out/types/src/codegen/functions/context.d.ts +6 -18
- package/out/types/src/codegen/functions/declarations.d.ts +10 -2
- package/out/types/src/codegen/index.d.ts +4 -0
- package/out/types/src/codegen/utils/index.d.ts +3 -0
- package/out/types/src/evaluator/async/await-analysis.d.ts +1 -0
- package/out/types/src/evaluator/builtins/build.d.ts +135 -0
- package/out/types/src/evaluator/context.d.ts +1 -0
- package/out/types/src/expr.d.ts +18 -0
- package/out/types/src/fetch-command.d.ts +6 -0
- package/out/types/src/fetch.d.ts +10 -0
- package/out/types/src/function-value.d.ts +1 -0
- package/out/types/src/init.d.ts +5 -0
- package/out/types/src/install-command.d.ts +6 -0
- package/out/types/src/lock-file.d.ts +16 -0
- package/out/types/src/module-manager.d.ts +3 -1
- package/out/types/src/pkg-config.d.ts +11 -0
- package/out/types/src/target.d.ts +28 -0
- package/out/types/src/tests/build-system.test.d.ts +1 -0
- package/out/types/src/types/creators.d.ts +2 -1
- package/out/types/src/types/definitions.d.ts +2 -1
- package/out/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/std/build.yo +287 -0
- package/std/crypto/random.yo +27 -15
- package/std/encoding/base64.yo +24 -49
- package/std/encoding/hex.yo +25 -22
- package/std/encoding/json.yo +25 -3
- package/std/encoding/utf16.yo +6 -5
- package/std/fs/dir.yo +107 -104
- package/std/fs/file.yo +122 -158
- package/std/fs/metadata.yo +23 -22
- package/std/fs/temp.yo +42 -48
- package/std/fs/walker.yo +48 -55
- package/std/net/addr.yo +8 -7
- package/std/net/dns.yo +27 -33
- package/std/net/errors.yo +13 -8
- package/std/net/tcp.yo +92 -113
- package/std/net/udp.yo +50 -54
- package/std/os/env.yo +5 -5
- package/std/os/signal.yo +21 -16
- package/std/path.yo +2 -2
- package/std/prelude.yo +23 -2
- package/std/process.yo +23 -43
- package/std/sys/clock.yo +1 -1
- package/std/sys/constants.yo +3 -3
- package/std/sys/errors.yo +45 -33
- package/std/sys/mmap.yo +2 -2
- package/std/sys/signals.yo +4 -4
- package/std/sys/socket.yo +25 -25
- package/std/sys/sysinfo.yo +4 -4
- package/std/url/url.yo +19 -32
- package/out/types/src/codegen/effects/effect-state-machine.d.ts +0 -34
package/package.json
CHANGED
package/std/build.yo
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
// Build System Module
|
|
2
|
+
//
|
|
3
|
+
// Provides the declarative build API for Yo projects.
|
|
4
|
+
// All functions are compile-time only — they register build artifacts
|
|
5
|
+
// and steps that the build runner uses to orchestrate compilation.
|
|
6
|
+
//
|
|
7
|
+
// Usage in build.yo:
|
|
8
|
+
// build :: import "std/build";
|
|
9
|
+
// build.project({ name: "my-app", root: "./src/lib.yo" });
|
|
10
|
+
// exe :: build.executable({ name: "my-app", root: "./src/main.yo" });
|
|
11
|
+
// install :: build.step("install", "Build all artifacts");
|
|
12
|
+
// install.depend_on(exe);
|
|
13
|
+
|
|
14
|
+
// ── Optimization levels ──────────────────────────────────────────────
|
|
15
|
+
|
|
16
|
+
Optimize :: enum(
|
|
17
|
+
Debug,
|
|
18
|
+
ReleaseSafe,
|
|
19
|
+
ReleaseFast,
|
|
20
|
+
ReleaseSmall
|
|
21
|
+
);
|
|
22
|
+
export Optimize;
|
|
23
|
+
|
|
24
|
+
// ── Memory allocators ────────────────────────────────────────────────
|
|
25
|
+
|
|
26
|
+
Allocator :: enum(
|
|
27
|
+
Mimalloc,
|
|
28
|
+
Libc
|
|
29
|
+
);
|
|
30
|
+
export Allocator;
|
|
31
|
+
|
|
32
|
+
// ── Sanitizers ───────────────────────────────────────────────────────
|
|
33
|
+
|
|
34
|
+
Sanitize :: enum(
|
|
35
|
+
None,
|
|
36
|
+
Address,
|
|
37
|
+
Leak
|
|
38
|
+
);
|
|
39
|
+
export Sanitize;
|
|
40
|
+
|
|
41
|
+
// ── Step kinds ───────────────────────────────────────────────────────
|
|
42
|
+
|
|
43
|
+
StepKind :: enum(
|
|
44
|
+
Executable,
|
|
45
|
+
StaticLibrary,
|
|
46
|
+
SharedLibrary,
|
|
47
|
+
SystemLibrary,
|
|
48
|
+
TestSuite,
|
|
49
|
+
Run,
|
|
50
|
+
Custom
|
|
51
|
+
);
|
|
52
|
+
export StepKind;
|
|
53
|
+
|
|
54
|
+
// ── Target utilities ─────────────────────────────────────────────────
|
|
55
|
+
|
|
56
|
+
target_host :: __yo_build_target_host();
|
|
57
|
+
export target_host;
|
|
58
|
+
|
|
59
|
+
// ── Config struct types ──────────────────────────────────────────────
|
|
60
|
+
// Struct types with defaults, like Zig's options structs.
|
|
61
|
+
// Usage: build.executable({ name: "app", root: "./src/main.yo" })
|
|
62
|
+
// Unspecified fields get their default values.
|
|
63
|
+
|
|
64
|
+
Project :: struct(
|
|
65
|
+
name : comptime_string,
|
|
66
|
+
(root : comptime_string) ?= "./src/lib.yo"
|
|
67
|
+
);
|
|
68
|
+
export Project;
|
|
69
|
+
|
|
70
|
+
Executable :: struct(
|
|
71
|
+
name : comptime_string,
|
|
72
|
+
root : comptime_string,
|
|
73
|
+
(target : comptime_string) ?= __yo_build_target_host(),
|
|
74
|
+
(optimize : Optimize) ?= Optimize.Debug,
|
|
75
|
+
(allocator : Allocator) ?= Allocator.Mimalloc,
|
|
76
|
+
(sanitize : Sanitize) ?= Sanitize.None
|
|
77
|
+
);
|
|
78
|
+
export Executable;
|
|
79
|
+
|
|
80
|
+
StaticLibrary :: struct(
|
|
81
|
+
name : comptime_string,
|
|
82
|
+
root : comptime_string,
|
|
83
|
+
(target : comptime_string) ?= __yo_build_target_host(),
|
|
84
|
+
(optimize : Optimize) ?= Optimize.Debug
|
|
85
|
+
);
|
|
86
|
+
export StaticLibrary;
|
|
87
|
+
|
|
88
|
+
SharedLibrary :: struct(
|
|
89
|
+
name : comptime_string,
|
|
90
|
+
root : comptime_string,
|
|
91
|
+
(target : comptime_string) ?= __yo_build_target_host(),
|
|
92
|
+
(optimize : Optimize) ?= Optimize.Debug
|
|
93
|
+
);
|
|
94
|
+
export SharedLibrary;
|
|
95
|
+
|
|
96
|
+
TestSuite :: struct(
|
|
97
|
+
name : comptime_string,
|
|
98
|
+
root : comptime_string,
|
|
99
|
+
(target : comptime_string) ?= __yo_build_target_host()
|
|
100
|
+
);
|
|
101
|
+
export TestSuite;
|
|
102
|
+
|
|
103
|
+
// ── Step type ────────────────────────────────────────────────────────
|
|
104
|
+
// Returned by all build functions. Used to wire dependencies between steps.
|
|
105
|
+
|
|
106
|
+
Step :: struct(
|
|
107
|
+
name : comptime_string,
|
|
108
|
+
kind : StepKind
|
|
109
|
+
);
|
|
110
|
+
export Step;
|
|
111
|
+
|
|
112
|
+
// ── Step methods ─────────────────────────────────────────────────────
|
|
113
|
+
// Methods on Step for Zig-like API: step.depend_on(other), exe.link(lib).
|
|
114
|
+
|
|
115
|
+
impl(Step,
|
|
116
|
+
depend_on : (fn(comptime(self) : Self, comptime(dep) : Step) -> comptime(unit))({
|
|
117
|
+
__yo_build_step_depend_on(self.name, dep.name, dep.kind);
|
|
118
|
+
}),
|
|
119
|
+
link : (fn(comptime(self) : Self, comptime(library) : Step) -> comptime(unit))({
|
|
120
|
+
__yo_build_link(self.name, library.name);
|
|
121
|
+
})
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
// ── Build option config types ────────────────────────────────────────
|
|
125
|
+
// Like Zig's b.option(), declare user-configurable options.
|
|
126
|
+
// CLI usage: yo build -Dname=value
|
|
127
|
+
|
|
128
|
+
BuildOption :: struct(
|
|
129
|
+
name : comptime_string,
|
|
130
|
+
description : comptime_string,
|
|
131
|
+
(default : comptime_string) ?= ""
|
|
132
|
+
);
|
|
133
|
+
export BuildOption;
|
|
134
|
+
|
|
135
|
+
// ── Dependency config types ──────────────────────────────────────────
|
|
136
|
+
|
|
137
|
+
GitDependency :: struct(
|
|
138
|
+
name : comptime_string,
|
|
139
|
+
url : comptime_string,
|
|
140
|
+
(ref : comptime_string) ?= "HEAD",
|
|
141
|
+
(path : comptime_string) ?= ""
|
|
142
|
+
);
|
|
143
|
+
export GitDependency;
|
|
144
|
+
|
|
145
|
+
PathDependency :: struct(
|
|
146
|
+
name : comptime_string,
|
|
147
|
+
path : comptime_string
|
|
148
|
+
);
|
|
149
|
+
export PathDependency;
|
|
150
|
+
|
|
151
|
+
SystemLibrary :: struct(
|
|
152
|
+
name : comptime_string,
|
|
153
|
+
pkg_config : comptime_string,
|
|
154
|
+
(fallback_include : comptime_string) ?= "",
|
|
155
|
+
(fallback_lib : comptime_string) ?= "",
|
|
156
|
+
(fallback_link : comptime_string) ?= ""
|
|
157
|
+
);
|
|
158
|
+
export SystemLibrary;
|
|
159
|
+
|
|
160
|
+
// ── Dependency handle ────────────────────────────────────────────────
|
|
161
|
+
// Returned by build.dependency() and build.path_dependency().
|
|
162
|
+
// Provides access to artifacts defined in the dependency's build.yo.
|
|
163
|
+
|
|
164
|
+
Dependency :: struct(
|
|
165
|
+
name : comptime_string
|
|
166
|
+
);
|
|
167
|
+
export Dependency;
|
|
168
|
+
|
|
169
|
+
impl(Dependency,
|
|
170
|
+
// Access a named artifact from the dependency's build.yo.
|
|
171
|
+
// Returns a Step that can be linked to the consumer's artifacts.
|
|
172
|
+
artifact : (fn(comptime(self) : Self, comptime(artifact_name) : comptime_string) -> comptime(Step))({
|
|
173
|
+
__yo_build_dep_artifact(self.name, artifact_name);
|
|
174
|
+
Step(name: artifact_name, kind: StepKind.StaticLibrary)
|
|
175
|
+
})
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
// ── Build functions ──────────────────────────────────────────────────
|
|
179
|
+
// All registration functions return a Step value, allowing steps to be
|
|
180
|
+
// wired together as dependencies via step.depend_on(dep).
|
|
181
|
+
|
|
182
|
+
// Register project metadata.
|
|
183
|
+
project :: (fn(comptime(config) : Project) -> comptime(unit)) {
|
|
184
|
+
__yo_build_project(config.name, config.root);
|
|
185
|
+
};
|
|
186
|
+
export project;
|
|
187
|
+
|
|
188
|
+
// Register an executable artifact. Returns a Step for dependency wiring.
|
|
189
|
+
executable :: (fn(comptime(config) : Executable) -> comptime(Step)) {
|
|
190
|
+
opt_str :: match(config.optimize,
|
|
191
|
+
.Debug => "debug",
|
|
192
|
+
.ReleaseSafe => "release-safe",
|
|
193
|
+
.ReleaseFast => "release-fast",
|
|
194
|
+
.ReleaseSmall => "release-small"
|
|
195
|
+
);
|
|
196
|
+
alloc_str :: match(config.allocator,
|
|
197
|
+
.Mimalloc => "mimalloc",
|
|
198
|
+
.Libc => "libc"
|
|
199
|
+
);
|
|
200
|
+
san_str :: match(config.sanitize,
|
|
201
|
+
.None => "none",
|
|
202
|
+
.Address => "address",
|
|
203
|
+
.Leak => "leak"
|
|
204
|
+
);
|
|
205
|
+
__yo_build_executable(config.name, config.root, config.target, opt_str, alloc_str, san_str);
|
|
206
|
+
Step(name: config.name, kind: StepKind.Executable)
|
|
207
|
+
};
|
|
208
|
+
export executable;
|
|
209
|
+
|
|
210
|
+
// Register a static library artifact. Returns a Step for dependency wiring.
|
|
211
|
+
static_library :: (fn(comptime(config) : StaticLibrary) -> comptime(Step)) {
|
|
212
|
+
opt_str :: match(config.optimize,
|
|
213
|
+
.Debug => "debug",
|
|
214
|
+
.ReleaseSafe => "release-safe",
|
|
215
|
+
.ReleaseFast => "release-fast",
|
|
216
|
+
.ReleaseSmall => "release-small"
|
|
217
|
+
);
|
|
218
|
+
__yo_build_static_library(config.name, config.root, config.target, opt_str);
|
|
219
|
+
Step(name: config.name, kind: StepKind.StaticLibrary)
|
|
220
|
+
};
|
|
221
|
+
export static_library;
|
|
222
|
+
|
|
223
|
+
// Register a shared/dynamic library artifact. Returns a Step for dependency wiring.
|
|
224
|
+
shared_library :: (fn(comptime(config) : SharedLibrary) -> comptime(Step)) {
|
|
225
|
+
opt_str :: match(config.optimize,
|
|
226
|
+
.Debug => "debug",
|
|
227
|
+
.ReleaseSafe => "release-safe",
|
|
228
|
+
.ReleaseFast => "release-fast",
|
|
229
|
+
.ReleaseSmall => "release-small"
|
|
230
|
+
);
|
|
231
|
+
__yo_build_shared_library(config.name, config.root, config.target, opt_str);
|
|
232
|
+
Step(name: config.name, kind: StepKind.SharedLibrary)
|
|
233
|
+
};
|
|
234
|
+
export shared_library;
|
|
235
|
+
|
|
236
|
+
// Register a test suite. Returns a Step for dependency wiring.
|
|
237
|
+
test :: (fn(comptime(config) : TestSuite) -> comptime(Step)) {
|
|
238
|
+
__yo_build_test(config.name, config.root, config.target);
|
|
239
|
+
Step(name: config.name, kind: StepKind.TestSuite)
|
|
240
|
+
};
|
|
241
|
+
export test;
|
|
242
|
+
|
|
243
|
+
// Create a run step (compile + execute an artifact). Returns a Step.
|
|
244
|
+
run :: (fn(comptime(artifact) : Step) -> comptime(Step)) {
|
|
245
|
+
__yo_build_run(artifact.name);
|
|
246
|
+
Step(name: artifact.name, kind: StepKind.Run)
|
|
247
|
+
};
|
|
248
|
+
export run;
|
|
249
|
+
|
|
250
|
+
// Register a named build step. Use step.depend_on(dep) to add dependencies.
|
|
251
|
+
step :: (fn(
|
|
252
|
+
comptime(name) : comptime_string,
|
|
253
|
+
comptime(description) : comptime_string
|
|
254
|
+
) -> comptime(Step)) {
|
|
255
|
+
__yo_build_step(name, description);
|
|
256
|
+
Step(name: name, kind: StepKind.Custom)
|
|
257
|
+
};
|
|
258
|
+
export step;
|
|
259
|
+
|
|
260
|
+
// Register a git-hosted dependency. Returns a Dependency handle for accessing artifacts.
|
|
261
|
+
dependency :: (fn(comptime(config) : GitDependency) -> comptime(Dependency)) {
|
|
262
|
+
__yo_build_dependency(config.name, config.url, config.ref, config.path);
|
|
263
|
+
Dependency(name: config.name)
|
|
264
|
+
};
|
|
265
|
+
export dependency;
|
|
266
|
+
|
|
267
|
+
// Register a local path dependency. Returns a Dependency handle for accessing artifacts.
|
|
268
|
+
path_dependency :: (fn(comptime(config) : PathDependency) -> comptime(Dependency)) {
|
|
269
|
+
__yo_build_path_dependency(config.name, config.path);
|
|
270
|
+
Dependency(name: config.name)
|
|
271
|
+
};
|
|
272
|
+
export path_dependency;
|
|
273
|
+
|
|
274
|
+
// Register a system C library discovered via pkg-config. Returns a Step for linking.
|
|
275
|
+
system_library :: (fn(comptime(config) : SystemLibrary) -> comptime(Step)) {
|
|
276
|
+
__yo_build_system_library(config.name, config.pkg_config, config.fallback_include, config.fallback_lib, config.fallback_link);
|
|
277
|
+
Step(name: config.name, kind: StepKind.SystemLibrary)
|
|
278
|
+
};
|
|
279
|
+
export system_library;
|
|
280
|
+
|
|
281
|
+
// Declare a user-configurable build option.
|
|
282
|
+
// Returns the option value (from CLI -Dname=value, or the default).
|
|
283
|
+
// Usage: strip :: build.option({ name: "strip", description: "Strip debug symbols", default: "false" });
|
|
284
|
+
option :: (fn(comptime(config) : BuildOption) -> comptime(str))(
|
|
285
|
+
__yo_build_option(config.name, config.description, config.default)
|
|
286
|
+
);
|
|
287
|
+
export option;
|
package/std/crypto/random.yo
CHANGED
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
open import "../string";
|
|
16
16
|
{ snprintf } :: import "../libc/stdio";
|
|
17
17
|
{ hex_encode } :: import "../encoding/hex";
|
|
18
|
+
{ Error, AnyError, Exception } :: import "../error";
|
|
19
|
+
{ ToString } :: import "../fmt";
|
|
18
20
|
|
|
19
21
|
// ============================================================================
|
|
20
22
|
// Error type
|
|
@@ -25,6 +27,17 @@ CryptoError :: enum(
|
|
|
25
27
|
Other(msg: String)
|
|
26
28
|
);
|
|
27
29
|
|
|
30
|
+
impl(CryptoError, ToString(
|
|
31
|
+
to_string : (self ->
|
|
32
|
+
match(self,
|
|
33
|
+
.Unavailable => `crypto: platform random unavailable`,
|
|
34
|
+
.Other(msg) => `crypto error: ${msg}`
|
|
35
|
+
)
|
|
36
|
+
)
|
|
37
|
+
));
|
|
38
|
+
|
|
39
|
+
impl(CryptoError, Error());
|
|
40
|
+
|
|
28
41
|
export CryptoError;
|
|
29
42
|
|
|
30
43
|
// ============================================================================
|
|
@@ -41,26 +54,25 @@ extern "Yo",
|
|
|
41
54
|
// Fill a buffer with cryptographically secure random bytes.
|
|
42
55
|
// ============================================================================
|
|
43
56
|
|
|
44
|
-
random_bytes :: (fn(buf: *(u8), size: usize) ->
|
|
57
|
+
random_bytes :: (fn(buf: *(u8), size: usize, using(exn : Exception)) -> unit)(
|
|
45
58
|
cond(
|
|
46
|
-
(platform == Platform.
|
|
59
|
+
(platform == Platform.Macos) => {
|
|
47
60
|
__yo_arc4random_buf(buf, size);
|
|
48
|
-
.Ok(())
|
|
49
61
|
},
|
|
50
|
-
(platform == Platform.
|
|
62
|
+
(platform == Platform.Windows) => {
|
|
51
63
|
r := __yo_bcrypt_gen_random(buf, u32(size));
|
|
52
64
|
cond(
|
|
53
|
-
(r == i32(0)) =>
|
|
54
|
-
true => .
|
|
55
|
-
)
|
|
65
|
+
(r == i32(0)) => (),
|
|
66
|
+
true => { exn.throw(dyn CryptoError.Unavailable); }
|
|
67
|
+
);
|
|
56
68
|
},
|
|
57
69
|
true => {
|
|
58
70
|
// Linux: getrandom syscall
|
|
59
71
|
ret := __yo_getrandom(buf, size, u32(0));
|
|
60
72
|
cond(
|
|
61
|
-
(ret < isize(0)) => .
|
|
62
|
-
true =>
|
|
63
|
-
)
|
|
73
|
+
(ret < isize(0)) => { exn.throw(dyn CryptoError.Unavailable); },
|
|
74
|
+
true => ()
|
|
75
|
+
);
|
|
64
76
|
}
|
|
65
77
|
)
|
|
66
78
|
);
|
|
@@ -71,7 +83,7 @@ export random_bytes;
|
|
|
71
83
|
// Typed helpers
|
|
72
84
|
// ============================================================================
|
|
73
85
|
|
|
74
|
-
random_u32 :: (fn() -> u32)({
|
|
86
|
+
random_u32 :: (fn(using(exn : Exception)) -> u32)({
|
|
75
87
|
buf := Array(u8, usize(4)).fill(u8(0));
|
|
76
88
|
buf_ptr := &(buf(usize(0)));
|
|
77
89
|
random_bytes(buf_ptr, usize(4));
|
|
@@ -81,18 +93,18 @@ random_u32 :: (fn() -> u32)({
|
|
|
81
93
|
(u32(buf(usize(3))) << u32(24)))
|
|
82
94
|
});
|
|
83
95
|
|
|
84
|
-
random_u64 :: (fn() -> u64)({
|
|
96
|
+
random_u64 :: (fn(using(exn : Exception)) -> u64)({
|
|
85
97
|
lo := u64(random_u32());
|
|
86
98
|
hi := u64(random_u32());
|
|
87
99
|
(lo | (hi << u64(32)))
|
|
88
100
|
});
|
|
89
101
|
|
|
90
|
-
random_f64 :: (fn() -> f64)(
|
|
102
|
+
random_f64 :: (fn(using(exn : Exception)) -> f64)(
|
|
91
103
|
(f64(random_u64()) / f64(18446744073709551615.0))
|
|
92
104
|
);
|
|
93
105
|
|
|
94
106
|
// Return a random integer in the half-open range [min, max).
|
|
95
|
-
random_range :: (fn(min: i64, max: i64) -> i64)({
|
|
107
|
+
random_range :: (fn(min: i64, max: i64, using(exn : Exception)) -> i64)({
|
|
96
108
|
span := (max - min);
|
|
97
109
|
cond(
|
|
98
110
|
(span <= i64(0)) => min,
|
|
@@ -110,7 +122,7 @@ export random_u32, random_u64, random_f64, random_range;
|
|
|
110
122
|
// ============================================================================
|
|
111
123
|
|
|
112
124
|
// Generate a random UUID v4 string: "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
|
|
113
|
-
uuid_v4 :: (fn() -> String)({
|
|
125
|
+
uuid_v4 :: (fn(using(exn : Exception)) -> String)({
|
|
114
126
|
bytes := ArrayList(u8).with_capacity(usize(16));
|
|
115
127
|
buf := Array(u8, usize(16)).fill(u8(0));
|
|
116
128
|
buf_ptr := &(buf(usize(0)));
|
package/std/encoding/base64.yo
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
open import "../string";
|
|
12
12
|
{ ArrayList } :: import "../collections/array_list";
|
|
13
13
|
{ EncodingError } :: import "./hex";
|
|
14
|
+
{ Error, AnyError, Exception } :: import "../error";
|
|
14
15
|
|
|
15
16
|
// ============================================================================
|
|
16
17
|
// Standard alphabet
|
|
@@ -73,81 +74,55 @@ export base64_encode, base64_encode_url;
|
|
|
73
74
|
// Decoding
|
|
74
75
|
// ============================================================================
|
|
75
76
|
|
|
76
|
-
_decode_char :: (fn(c: u8, alpha: str) ->
|
|
77
|
+
_decode_char :: (fn(c: u8, alpha: str, using(exn : Exception)) -> u8)({
|
|
77
78
|
i := usize(0);
|
|
78
79
|
while (i < usize(64)), (i = (i + usize(1))), {
|
|
79
80
|
cond(
|
|
80
|
-
(alpha.bytes(i) == c) => { return
|
|
81
|
+
(alpha.bytes(i) == c) => { return u8(i); },
|
|
81
82
|
true => ()
|
|
82
83
|
);
|
|
83
84
|
};
|
|
84
|
-
.
|
|
85
|
+
exn.throw(dyn EncodingError.InvalidChar(c))
|
|
85
86
|
});
|
|
86
87
|
|
|
87
|
-
_decode_with :: (fn(s: str, alpha: str) ->
|
|
88
|
+
_decode_with :: (fn(s: str, alpha: str, using(exn : Exception)) -> ArrayList(u8))({
|
|
88
89
|
// Strip trailing padding
|
|
89
90
|
len := s.len();
|
|
90
91
|
while ((len > usize(0)) && (s.bytes((len - usize(1))) == _PAD)), (len = (len - usize(1))), ();
|
|
91
92
|
out := ArrayList(u8).with_capacity(((len * usize(3)) / usize(4)));
|
|
92
93
|
i := usize(0);
|
|
93
94
|
while (i < len), (i = (i + usize(4))), {
|
|
94
|
-
|
|
95
|
-
|
|
95
|
+
c0 := _decode_char(s.bytes(i), alpha);
|
|
96
|
+
c1 := cond(
|
|
96
97
|
((i + usize(1)) < len) => _decode_char(s.bytes((i + usize(1))), alpha),
|
|
97
|
-
true =>
|
|
98
|
+
true => u8(0)
|
|
98
99
|
);
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
match(c1_r,
|
|
111
|
-
.Err(e) => { return .Err(e); },
|
|
112
|
-
.Ok(c1) => {
|
|
113
|
-
out.push(((c0 << u8(2)) | (c1 >> u8(4))));
|
|
114
|
-
cond(
|
|
115
|
-
((i + usize(2)) < len) => {
|
|
116
|
-
match(c2_r,
|
|
117
|
-
.Err(e) => { return .Err(e); },
|
|
118
|
-
.Ok(c2) => {
|
|
119
|
-
out.push((((c1 & u8(15)) << u8(4)) | (c2 >> u8(2))));
|
|
120
|
-
cond(
|
|
121
|
-
((i + usize(3)) < len) => {
|
|
122
|
-
match(c3_r,
|
|
123
|
-
.Err(e) => { return .Err(e); },
|
|
124
|
-
.Ok(c3) => {
|
|
125
|
-
out.push((((c2 & u8(3)) << u8(6)) | c3));
|
|
126
|
-
}
|
|
127
|
-
);
|
|
128
|
-
},
|
|
129
|
-
true => ()
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
);
|
|
133
|
-
},
|
|
134
|
-
true => ()
|
|
135
|
-
);
|
|
136
|
-
}
|
|
100
|
+
out.push(((c0 << u8(2)) | (c1 >> u8(4))));
|
|
101
|
+
cond(
|
|
102
|
+
((i + usize(2)) < len) => {
|
|
103
|
+
c2 := _decode_char(s.bytes((i + usize(2))), alpha);
|
|
104
|
+
out.push((((c1 & u8(15)) << u8(4)) | (c2 >> u8(2))));
|
|
105
|
+
cond(
|
|
106
|
+
((i + usize(3)) < len) => {
|
|
107
|
+
c3 := _decode_char(s.bytes((i + usize(3))), alpha);
|
|
108
|
+
out.push((((c2 & u8(3)) << u8(6)) | c3));
|
|
109
|
+
},
|
|
110
|
+
true => ()
|
|
137
111
|
);
|
|
138
|
-
}
|
|
112
|
+
},
|
|
113
|
+
true => ()
|
|
139
114
|
);
|
|
140
115
|
};
|
|
141
|
-
|
|
116
|
+
out
|
|
142
117
|
});
|
|
143
118
|
|
|
144
119
|
// Decode standard base64.
|
|
145
|
-
base64_decode :: (fn(s: str) ->
|
|
120
|
+
base64_decode :: (fn(s: str, using(exn : Exception)) -> ArrayList(u8))(
|
|
146
121
|
_decode_with(s, _STD_ALPHA)
|
|
147
122
|
);
|
|
148
123
|
|
|
149
124
|
// Decode URL-safe base64.
|
|
150
|
-
base64_decode_url :: (fn(s: str) ->
|
|
125
|
+
base64_decode_url :: (fn(s: str, using(exn : Exception)) -> ArrayList(u8))(
|
|
151
126
|
_decode_with(s, _URL_ALPHA)
|
|
152
127
|
);
|
|
153
128
|
|
package/std/encoding/hex.yo
CHANGED
|
@@ -6,10 +6,12 @@
|
|
|
6
6
|
// { hex_encode, hex_decode } :: import "std/encoding/hex";
|
|
7
7
|
//
|
|
8
8
|
// s := hex_encode(data); // "deadbeef"
|
|
9
|
-
// b := hex_decode("deadbeef")
|
|
9
|
+
// b := hex_decode("deadbeef");
|
|
10
10
|
|
|
11
11
|
open import "../string";
|
|
12
12
|
{ ArrayList } :: import "../collections/array_list";
|
|
13
|
+
{ Error, AnyError, Exception } :: import "../error";
|
|
14
|
+
{ ToString } :: import "../fmt";
|
|
13
15
|
|
|
14
16
|
// ============================================================================
|
|
15
17
|
// Error type
|
|
@@ -20,6 +22,17 @@ EncodingError :: enum(
|
|
|
20
22
|
OddLength
|
|
21
23
|
);
|
|
22
24
|
|
|
25
|
+
impl(EncodingError, ToString(
|
|
26
|
+
to_string : (self ->
|
|
27
|
+
match(self,
|
|
28
|
+
.InvalidChar(ch) => `encoding error: invalid character ${ch}`,
|
|
29
|
+
.OddLength => `encoding error: odd length`
|
|
30
|
+
)
|
|
31
|
+
)
|
|
32
|
+
));
|
|
33
|
+
|
|
34
|
+
impl(EncodingError, Error());
|
|
35
|
+
|
|
23
36
|
export EncodingError;
|
|
24
37
|
|
|
25
38
|
// ============================================================================
|
|
@@ -52,41 +65,31 @@ export hex_encode;
|
|
|
52
65
|
// Decoding
|
|
53
66
|
// ============================================================================
|
|
54
67
|
|
|
55
|
-
_hex_nibble :: (fn(c: u8) ->
|
|
68
|
+
_hex_nibble :: (fn(c: u8, using(exn : Exception)) -> u8)(
|
|
56
69
|
cond(
|
|
57
|
-
((c >= u8(48)) && (c <= u8(57))) =>
|
|
58
|
-
((c >= u8(97)) && (c <= u8(102))) =>
|
|
59
|
-
((c >= u8(65)) && (c <= u8(70))) =>
|
|
60
|
-
true => .
|
|
70
|
+
((c >= u8(48)) && (c <= u8(57))) => (c - u8(48)), // '0'-'9'
|
|
71
|
+
((c >= u8(97)) && (c <= u8(102))) => ((c - u8(97)) + u8(10)), // 'a'-'f'
|
|
72
|
+
((c >= u8(65)) && (c <= u8(70))) => ((c - u8(65)) + u8(10)), // 'A'-'F'
|
|
73
|
+
true => exn.throw(dyn EncodingError.InvalidChar(c))
|
|
61
74
|
)
|
|
62
75
|
);
|
|
63
76
|
|
|
64
77
|
// Decode a hexadecimal string into bytes.
|
|
65
|
-
hex_decode :: (fn(s: str) ->
|
|
78
|
+
hex_decode :: (fn(s: str, using(exn : Exception)) -> ArrayList(u8))({
|
|
66
79
|
cond(
|
|
67
80
|
(((s.len() % usize(2)) != usize(0))) => {
|
|
68
|
-
|
|
81
|
+
exn.throw(dyn EncodingError.OddLength);
|
|
69
82
|
},
|
|
70
83
|
true => ()
|
|
71
84
|
);
|
|
72
85
|
out := ArrayList(u8).with_capacity((s.len() / usize(2)));
|
|
73
86
|
i := usize(0);
|
|
74
87
|
while (i < s.len()), (i = (i + usize(2))), {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
.Err(e) => { return .Err(e); },
|
|
79
|
-
.Ok(hi) => {
|
|
80
|
-
match(lo_r,
|
|
81
|
-
.Err(e) => { return .Err(e); },
|
|
82
|
-
.Ok(lo) => {
|
|
83
|
-
out.push(((hi << u8(4)) | lo));
|
|
84
|
-
}
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
);
|
|
88
|
+
hi := _hex_nibble(s.bytes(i));
|
|
89
|
+
lo := _hex_nibble(s.bytes((i + usize(1))));
|
|
90
|
+
out.push(((hi << u8(4)) | lo));
|
|
88
91
|
};
|
|
89
|
-
|
|
92
|
+
out
|
|
90
93
|
});
|
|
91
94
|
|
|
92
95
|
export hex_decode;
|
package/std/encoding/json.yo
CHANGED
|
@@ -4,13 +4,17 @@
|
|
|
4
4
|
//
|
|
5
5
|
// Example:
|
|
6
6
|
// { json_parse, json_stringify, JsonValue } :: import "std/encoding/json";
|
|
7
|
+
// { Exception } :: import "std/error";
|
|
7
8
|
//
|
|
8
|
-
//
|
|
9
|
+
// given(exn) := Exception(throw : ((err) -> { escape (); }));
|
|
10
|
+
// v := json_parse(`{"x": 1}`);
|
|
9
11
|
// println(json_stringify(v));
|
|
10
12
|
|
|
11
13
|
open import "../string";
|
|
12
14
|
{ ArrayList } :: import "../collections/array_list";
|
|
13
15
|
{ snprintf } :: import "../libc/stdio";
|
|
16
|
+
{ Error, AnyError, Exception } :: import "../error";
|
|
17
|
+
{ ToString } :: import "../fmt";
|
|
14
18
|
|
|
15
19
|
// ============================================================================
|
|
16
20
|
// JsonError
|
|
@@ -25,6 +29,21 @@ JsonError :: enum(
|
|
|
25
29
|
Other(msg: String)
|
|
26
30
|
);
|
|
27
31
|
|
|
32
|
+
impl(JsonError, ToString(
|
|
33
|
+
to_string : (self ->
|
|
34
|
+
match(self,
|
|
35
|
+
.UnexpectedChar(ch, pos) => `unexpected character at position ${pos}`,
|
|
36
|
+
.UnexpectedEnd => `unexpected end of input`,
|
|
37
|
+
.InvalidNumber => `invalid number`,
|
|
38
|
+
.InvalidEscape => `invalid escape sequence`,
|
|
39
|
+
.InvalidUnicode => `invalid unicode`,
|
|
40
|
+
.Other(msg) => `JSON error: ${msg}`
|
|
41
|
+
)
|
|
42
|
+
)
|
|
43
|
+
));
|
|
44
|
+
|
|
45
|
+
impl(JsonError, Error());
|
|
46
|
+
|
|
28
47
|
export JsonError;
|
|
29
48
|
|
|
30
49
|
// ============================================================================
|
|
@@ -449,9 +468,12 @@ _parse_value :: (fn(p: _Parser) -> Result(JsonValue, JsonError))({
|
|
|
449
468
|
// Public API
|
|
450
469
|
// ============================================================================
|
|
451
470
|
|
|
452
|
-
json_parse :: (fn(s: str) ->
|
|
471
|
+
json_parse :: (fn(s: str, using(exn : Exception)) -> JsonValue)({
|
|
453
472
|
p := _Parser.new(s);
|
|
454
|
-
_parse_value(p)
|
|
473
|
+
match(_parse_value(p),
|
|
474
|
+
.Ok(v) => v,
|
|
475
|
+
.Err(e) => exn.throw(dyn e)
|
|
476
|
+
)
|
|
455
477
|
});
|
|
456
478
|
|
|
457
479
|
export json_parse;
|