@shd101wyy/yo 0.1.28 → 0.1.30
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/.github/skills/yo-async-effects/SKILL.md +15 -15
- package/.github/skills/yo-async-effects/async-effects-recipes.md +118 -121
- package/.github/skills/yo-core-patterns/core-patterns-cheatsheet.md +33 -13
- package/.github/skills/yo-project-workflow/workflow-cheatsheet.md +1 -1
- package/.github/skills/yo-syntax/SKILL.md +2 -2
- package/.github/skills/yo-syntax/syntax-cheatsheet.md +108 -96
- package/README.md +6 -3
- package/out/cjs/index.cjs +812 -706
- package/out/cjs/yo-cli.cjs +1023 -907
- package/out/cjs/yo-lsp.cjs +836 -730
- package/out/esm/index.mjs +757 -651
- package/out/types/src/codegen/exprs/async.d.ts +2 -0
- package/out/types/src/codegen/exprs/await.d.ts +1 -0
- package/out/types/src/codegen/exprs/closures.d.ts +4 -0
- package/out/types/src/codegen/functions/context.d.ts +6 -0
- package/out/types/src/codegen/functions/declarations.d.ts +1 -1
- package/out/types/src/doc/model.d.ts +0 -1
- package/out/types/src/env.d.ts +2 -2
- package/out/types/src/evaluator/builtins/pragma.d.ts +9 -0
- package/out/types/src/evaluator/builtins/unsafe.d.ts +8 -0
- package/out/types/src/evaluator/context.d.ts +3 -1
- package/out/types/src/evaluator/exprs/{escape.d.ts → unwind.d.ts} +1 -1
- package/out/types/src/evaluator/index.d.ts +1 -1
- package/out/types/src/evaluator/memory-safety.d.ts +14 -0
- package/out/types/src/evaluator/types/flowability.d.ts +6 -0
- package/out/types/src/evaluator/types/function.d.ts +1 -2
- package/out/types/src/evaluator/utils.d.ts +0 -1
- package/out/types/src/expr-traversal.d.ts +1 -0
- package/out/types/src/expr.d.ts +9 -7
- package/out/types/src/public-safe-report.d.ts +19 -0
- package/out/types/src/tests/comptime-ref-gate.test.d.ts +1 -0
- package/out/types/src/tests/pragma-validation.test.d.ts +1 -0
- package/out/types/src/tests/public-safe-report.test.d.ts +1 -0
- package/out/types/src/tests/type-representation-pointer.test.d.ts +1 -0
- package/out/types/src/tests/unsafe-gate.test.d.ts +1 -0
- package/out/types/src/tests/unsafe-report-classify.test.d.ts +1 -0
- package/out/types/src/types/creators.d.ts +4 -6
- package/out/types/src/types/definitions.d.ts +9 -16
- package/out/types/src/types/guards.d.ts +1 -2
- package/out/types/src/types/tags.d.ts +0 -1
- package/out/types/src/types/utils.d.ts +5 -0
- package/out/types/src/unsafe-report.d.ts +29 -0
- package/out/types/src/value.d.ts +1 -0
- package/out/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/scripts/add-pragma-for-pointer-decls.ts +134 -0
- package/scripts/add-pragma.ts +58 -0
- package/scripts/migrate-amp-method-calls.ts +186 -0
- package/scripts/migrate-clone-calls.ts +93 -0
- package/scripts/migrate-get-unwrap.ts +166 -0
- package/scripts/migrate-index-patterns.ts +210 -0
- package/scripts/migrate-index-trait.ts +142 -0
- package/scripts/migrate-iterator.ts +150 -0
- package/scripts/migrate-self-ptr.ts +220 -0
- package/scripts/migrate-skip-pragmas.ts +109 -0
- package/scripts/migrate-tostring.ts +134 -0
- package/scripts/trim-pragma.ts +130 -0
- package/scripts/wrap-extern-calls.ts +161 -0
- package/std/alg/hash.yo +3 -2
- package/std/allocator.yo +6 -5
- package/std/async.yo +2 -2
- package/std/collections/array_list.yo +59 -40
- package/std/collections/btree_map.yo +19 -18
- package/std/collections/deque.yo +9 -8
- package/std/collections/hash_map.yo +101 -13
- package/std/collections/hash_set.yo +5 -4
- package/std/collections/linked_list.yo +39 -4
- package/std/collections/ordered_map.yo +3 -3
- package/std/collections/priority_queue.yo +14 -13
- package/std/crypto/md5.yo +2 -1
- package/std/crypto/random.yo +21 -20
- package/std/crypto/sha256.yo +2 -1
- package/std/encoding/base64.yo +18 -18
- package/std/encoding/hex.yo +5 -5
- package/std/encoding/json.yo +62 -13
- package/std/encoding/punycode.yo +24 -23
- package/std/encoding/toml.yo +4 -3
- package/std/encoding/utf16.yo +3 -3
- package/std/env.yo +43 -28
- package/std/error.yo +15 -3
- package/std/fmt/display.yo +2 -2
- package/std/fmt/index.yo +6 -5
- package/std/fmt/to_string.yo +39 -38
- package/std/fmt/writer.yo +9 -8
- package/std/fs/dir.yo +61 -66
- package/std/fs/file.yo +121 -126
- package/std/fs/metadata.yo +13 -18
- package/std/fs/temp.yo +35 -30
- package/std/fs/walker.yo +14 -19
- package/std/gc.yo +1 -0
- package/std/glob.yo +7 -7
- package/std/http/client.yo +33 -36
- package/std/http/http.yo +6 -6
- package/std/http/index.yo +4 -4
- package/std/imm/list.yo +33 -0
- package/std/imm/map.yo +2 -1
- package/std/imm/set.yo +1 -0
- package/std/imm/sorted_map.yo +1 -0
- package/std/imm/sorted_set.yo +1 -0
- package/std/imm/string.yo +27 -23
- package/std/imm/vec.yo +18 -2
- package/std/io/reader.yo +2 -1
- package/std/io/writer.yo +3 -2
- package/std/libc/assert.yo +1 -0
- package/std/libc/ctype.yo +1 -0
- package/std/libc/dirent.yo +1 -0
- package/std/libc/errno.yo +1 -0
- package/std/libc/fcntl.yo +1 -0
- package/std/libc/float.yo +1 -0
- package/std/libc/limits.yo +1 -0
- package/std/libc/math.yo +1 -0
- package/std/libc/signal.yo +1 -0
- package/std/libc/stdatomic.yo +1 -0
- package/std/libc/stdint.yo +1 -0
- package/std/libc/stdio.yo +1 -0
- package/std/libc/stdlib.yo +1 -0
- package/std/libc/string.yo +1 -0
- package/std/libc/sys/stat.yo +1 -0
- package/std/libc/time.yo +1 -0
- package/std/libc/unistd.yo +1 -0
- package/std/libc/wctype.yo +1 -0
- package/std/libc/windows.yo +2 -0
- package/std/log.yo +7 -6
- package/std/net/addr.yo +6 -5
- package/std/net/dns.yo +13 -16
- package/std/net/errors.yo +9 -9
- package/std/net/tcp.yo +71 -74
- package/std/net/udp.yo +40 -43
- package/std/os/signal.yo +5 -5
- package/std/path.yo +1 -0
- package/std/prelude.yo +377 -200
- package/std/process/command.yo +57 -46
- package/std/process/index.yo +2 -1
- package/std/regex/compiler.yo +10 -9
- package/std/regex/index.yo +41 -41
- package/std/regex/match.yo +2 -2
- package/std/regex/parser.yo +31 -31
- package/std/regex/vm.yo +42 -41
- package/std/string/string.yo +95 -40
- package/std/string/string_builder.yo +9 -9
- package/std/string/unicode.yo +50 -49
- package/std/sync/channel.yo +2 -1
- package/std/sync/cond.yo +5 -4
- package/std/sync/mutex.yo +4 -3
- package/std/sys/advise.yo +1 -0
- package/std/sys/bufio/buf_reader.yo +27 -26
- package/std/sys/bufio/buf_writer.yo +22 -21
- package/std/sys/clock.yo +1 -0
- package/std/sys/copy.yo +1 -0
- package/std/sys/dir.yo +10 -9
- package/std/sys/dns.yo +6 -5
- package/std/sys/errors.yo +12 -12
- package/std/sys/events.yo +1 -0
- package/std/sys/externs.yo +38 -37
- package/std/sys/file.yo +17 -16
- package/std/sys/future.yo +4 -3
- package/std/sys/iov.yo +1 -0
- package/std/sys/mmap.yo +1 -0
- package/std/sys/path.yo +1 -0
- package/std/sys/perm.yo +2 -1
- package/std/sys/pipe.yo +1 -0
- package/std/sys/process.yo +5 -4
- package/std/sys/signal.yo +1 -0
- package/std/sys/socketpair.yo +1 -0
- package/std/sys/sockinfo.yo +1 -0
- package/std/sys/statfs.yo +2 -1
- package/std/sys/statx.yo +1 -0
- package/std/sys/sysinfo.yo +1 -0
- package/std/sys/tcp.yo +15 -14
- package/std/sys/temp.yo +1 -0
- package/std/sys/time.yo +2 -1
- package/std/sys/timer.yo +6 -6
- package/std/sys/tty.yo +2 -1
- package/std/sys/udp.yo +13 -12
- package/std/sys/unix.yo +12 -11
- package/std/testing/bench.yo +4 -3
- package/std/thread.yo +7 -6
- package/std/time/datetime.yo +18 -15
- package/std/time/duration.yo +11 -10
- package/std/time/instant.yo +4 -4
- package/std/time/sleep.yo +1 -0
- package/std/url/index.yo +5 -5
- package/std/worker.yo +4 -3
package/std/fs/file.yo
CHANGED
|
@@ -8,32 +8,27 @@
|
|
|
8
8
|
//! ```rust
|
|
9
9
|
//! { File, read_string, write_file, OpenMode } :: import "std/fs/file";
|
|
10
10
|
//!
|
|
11
|
-
//! main :: (fn(
|
|
12
|
-
//! given(exn) := Exception(
|
|
13
|
-
//! throw : (fn(forall(T : Type), error: AnyError) -> T)(
|
|
14
|
-
//! { println(error); panic("Exception found."); }
|
|
15
|
-
//! )
|
|
16
|
-
//! );
|
|
17
|
-
//!
|
|
11
|
+
//! main :: (fn(io : Io, exn : Exception) -> unit)({
|
|
18
12
|
//! // Write a file
|
|
19
|
-
//! io.await(write_file(Path.new(`test.txt`), `hello world
|
|
13
|
+
//! io.await(write_file(Path.new(`test.txt`), `hello world`, io), { io, exn });
|
|
20
14
|
//!
|
|
21
15
|
//! // Read it back
|
|
22
|
-
//! content := io.await(read_string(Path.new(`test.txt`)));
|
|
16
|
+
//! content := io.await(read_string(Path.new(`test.txt`), io), { io, exn });
|
|
23
17
|
//! println(content);
|
|
24
18
|
//!
|
|
25
19
|
//! // Open with OpenMode
|
|
26
|
-
//! f := io.await(File.open(Path.new(`test.txt`), .Read));
|
|
20
|
+
//! f := io.await(File.open(Path.new(`test.txt`), .Read, io), { io, exn });
|
|
27
21
|
//! });
|
|
28
22
|
//! ```
|
|
23
|
+
pragma(Pragma.AllowUnsafe);
|
|
29
24
|
{ GlobalAllocator } :: import("../allocator");
|
|
30
25
|
{ malloc, free } :: GlobalAllocator;
|
|
31
26
|
{ ArrayList } :: import("../collections/array_list");
|
|
32
27
|
open(import("../string"));
|
|
33
28
|
open(import("../fmt"));
|
|
34
29
|
{ Path } :: import("../path");
|
|
35
|
-
{
|
|
36
|
-
{ Error, AnyError, Exception } :: import("../error");
|
|
30
|
+
{ IoError } :: import("../sys/errors");
|
|
31
|
+
{ Error, AnyError, Exception, IoExn } :: import("../error");
|
|
37
32
|
{ Metadata } :: import("./metadata");
|
|
38
33
|
_metadata_mod :: import("./metadata");
|
|
39
34
|
{ Statx } :: import("../sys/statx");
|
|
@@ -57,18 +52,18 @@ File :: object(
|
|
|
57
52
|
impl(
|
|
58
53
|
File,
|
|
59
54
|
/// Open a file at `path` with the given mode and custom permissions.
|
|
60
|
-
open_with : (fn(path : Path, mode : OpenMode, perm : FilePermission,
|
|
55
|
+
open_with : (fn(path : Path, mode : OpenMode, perm : FilePermission, io : Io) -> Impl(Future(File, IoExn)))({
|
|
61
56
|
flags := _open_mode_to_flags(mode);
|
|
62
57
|
file_mode := cond(
|
|
63
58
|
_open_mode_needs_perm(mode) => i32(perm.mode),
|
|
64
59
|
true => i32(0)
|
|
65
60
|
);
|
|
66
|
-
io.async((
|
|
61
|
+
io.async((e) => {
|
|
67
62
|
path_str := path.to_string();
|
|
68
63
|
cstr_bytes := path_str.to_cstr();
|
|
69
64
|
cstr := cstr_bytes.ptr().unwrap();
|
|
70
|
-
result := io.await(IO_file.openat(AT_FDCWD, cstr, flags, file_mode));
|
|
71
|
-
fd :=
|
|
65
|
+
result := e.io.await(IO_file.openat(AT_FDCWD, cstr, flags, file_mode), e.io);
|
|
66
|
+
fd := IoError.check(result, e.exn);
|
|
72
67
|
File(
|
|
73
68
|
_fd : fd,
|
|
74
69
|
_path : path,
|
|
@@ -77,78 +72,78 @@ impl(
|
|
|
77
72
|
})
|
|
78
73
|
}),
|
|
79
74
|
/// Open a file from a `str` path with the given mode and custom permissions.
|
|
80
|
-
open_with_str : (fn(path : str, mode : OpenMode, perm : FilePermission,
|
|
81
|
-
File.open_with(Path.new(String.from(path)), mode, perm)
|
|
75
|
+
open_with_str : (fn(path : str, mode : OpenMode, perm : FilePermission, io : Io) -> Impl(Future(File, IoExn)))(
|
|
76
|
+
File.open_with(Path.new(String.from(path)), mode, perm, io)
|
|
82
77
|
),
|
|
83
78
|
/// Open a file from a C string path with the given mode and custom permissions.
|
|
84
|
-
open_with_cstr : (fn(path : *(u8), mode : OpenMode, perm : FilePermission,
|
|
85
|
-
File.open_with(Path.from_cstr(path), mode, perm)
|
|
79
|
+
open_with_cstr : (fn(path : *(u8), mode : OpenMode, perm : FilePermission, io : Io) -> Impl(Future(File, IoExn)))(
|
|
80
|
+
File.open_with(Path.from_cstr(path), mode, perm, io)
|
|
86
81
|
),
|
|
87
82
|
/// Open a file at `path` with the given mode and default permissions (0o644).
|
|
88
|
-
open : (fn(path : Path, mode : OpenMode,
|
|
89
|
-
File.open_with(path, mode, FilePermission.default())
|
|
83
|
+
open : (fn(path : Path, mode : OpenMode, io : Io) -> Impl(Future(File, IoExn)))(
|
|
84
|
+
File.open_with(path, mode, FilePermission.default(), io)
|
|
90
85
|
),
|
|
91
86
|
/// Open a file from a `str` path with the given mode and default permissions.
|
|
92
|
-
open_str : (fn(path : str, mode : OpenMode,
|
|
93
|
-
File.open(Path.new(String.from(path)), mode)
|
|
87
|
+
open_str : (fn(path : str, mode : OpenMode, io : Io) -> Impl(Future(File, IoExn)))(
|
|
88
|
+
File.open(Path.new(String.from(path)), mode, io)
|
|
94
89
|
),
|
|
95
90
|
/// Open a file from a C string path with the given mode and default permissions.
|
|
96
|
-
open_cstr : (fn(path : *(u8), mode : OpenMode,
|
|
97
|
-
File.open(Path.from_cstr(path), mode)
|
|
91
|
+
open_cstr : (fn(path : *(u8), mode : OpenMode, io : Io) -> Impl(Future(File, IoExn)))(
|
|
92
|
+
File.open(Path.from_cstr(path), mode, io)
|
|
98
93
|
),
|
|
99
94
|
/// Read up to `size` bytes into the buffer `buf`.
|
|
100
95
|
/// Returns the number of bytes actually read.
|
|
101
|
-
read : (fn(self : Self, buf : *(u8), size : u32,
|
|
96
|
+
read : (fn(self : Self, buf : *(u8), size : u32, io : Io) -> Impl(Future(i32, IoExn)))({
|
|
102
97
|
fd := self._fd;
|
|
103
|
-
io.async((
|
|
104
|
-
result := io.await(IO_file.read(fd, buf, size, u64(0)));
|
|
105
|
-
|
|
98
|
+
io.async((e) => {
|
|
99
|
+
result := e.io.await(IO_file.read(fd, buf, size, u64(0)), e.io);
|
|
100
|
+
IoError.check(result, e.exn)
|
|
106
101
|
})
|
|
107
102
|
}),
|
|
108
103
|
/// Write a `String` to the file.
|
|
109
104
|
/// Returns the number of bytes written.
|
|
110
|
-
write_string : (fn(self : Self, data : String,
|
|
105
|
+
write_string : (fn(self : Self, data : String, io : Io) -> Impl(Future(i32, IoExn)))({
|
|
111
106
|
fd := self._fd;
|
|
112
|
-
io.async((
|
|
107
|
+
io.async((e) => {
|
|
113
108
|
data_bytes := data.as_bytes();
|
|
114
109
|
cond(
|
|
115
110
|
(data_bytes.len() == usize(0)) => i32(0),
|
|
116
111
|
true => {
|
|
117
|
-
result := io.await(IO_file.write(fd, data_bytes.ptr().unwrap(), u32(data_bytes.len()), u64(0)));
|
|
118
|
-
|
|
112
|
+
result := e.io.await(IO_file.write(fd, data_bytes.ptr().unwrap(), u32(data_bytes.len()), u64(0)), e.io);
|
|
113
|
+
IoError.check(result, e.exn)
|
|
119
114
|
}
|
|
120
115
|
)
|
|
121
116
|
})
|
|
122
117
|
}),
|
|
123
118
|
/// Write bytes from an `ArrayList(u8)` to the file.
|
|
124
119
|
/// Returns the number of bytes written.
|
|
125
|
-
write_bytes : (fn(self : Self, data : ArrayList(u8),
|
|
120
|
+
write_bytes : (fn(self : Self, data : ArrayList(u8), io : Io) -> Impl(Future(i32, IoExn)))({
|
|
126
121
|
fd := self._fd;
|
|
127
122
|
io.async(
|
|
128
|
-
(
|
|
123
|
+
(e) =>
|
|
129
124
|
cond(
|
|
130
125
|
(data.len() == usize(0)) => i32(0),
|
|
131
126
|
true => {
|
|
132
|
-
result := io.await(IO_file.write(fd, data.ptr().unwrap(), u32(data.len()), u64(0)));
|
|
133
|
-
|
|
127
|
+
result := e.io.await(IO_file.write(fd, data.ptr().unwrap(), u32(data.len()), u64(0)), e.io);
|
|
128
|
+
IoError.check(result, e.exn)
|
|
134
129
|
}
|
|
135
130
|
)
|
|
136
131
|
)
|
|
137
132
|
}),
|
|
138
133
|
/// Read the entire file contents into an `ArrayList(u8)`.
|
|
139
|
-
read_bytes : (fn(self : Self,
|
|
134
|
+
read_bytes : (fn(self : Self, io : Io) -> Impl(Future(ArrayList(u8), IoExn)))({
|
|
140
135
|
fd := self._fd;
|
|
141
|
-
io.async((
|
|
136
|
+
io.async((e) => {
|
|
142
137
|
buf_size := usize(4096);
|
|
143
138
|
buf := *(u8)(malloc(buf_size).unwrap());
|
|
144
139
|
result := ArrayList(u8).new();
|
|
145
140
|
offset := u64(0);
|
|
146
141
|
while(runtime(true), {
|
|
147
|
-
n := io.await(IO_file.read(fd, buf, u32(buf_size), offset));
|
|
142
|
+
n := e.io.await(IO_file.read(fd, buf, u32(buf_size), offset), e.io);
|
|
148
143
|
cond(
|
|
149
144
|
(n < i32(0)) => {
|
|
150
145
|
free(.Some(*(void)(buf)));
|
|
151
|
-
exn.throw(dyn(
|
|
146
|
+
e.exn.throw(dyn(IoError.from_errno(i32(0) - n)));
|
|
152
147
|
},
|
|
153
148
|
(n == i32(0)) => break,
|
|
154
149
|
true => {
|
|
@@ -166,28 +161,28 @@ impl(
|
|
|
166
161
|
})
|
|
167
162
|
}),
|
|
168
163
|
/// Read the entire file contents into a `String`.
|
|
169
|
-
read_string : (fn(self : Self,
|
|
170
|
-
io.async((
|
|
171
|
-
bytes := io.await(self.read_bytes());
|
|
164
|
+
read_string : (fn(self : Self, io : Io) -> Impl(Future(String, IoExn)))(
|
|
165
|
+
io.async((e) => {
|
|
166
|
+
bytes := e.io.await(self.read_bytes(io), e);
|
|
172
167
|
String.from_bytes(bytes)
|
|
173
168
|
})
|
|
174
169
|
),
|
|
175
170
|
/// Flush (fsync) file data to disk.
|
|
176
|
-
flush : (fn(self : Self,
|
|
171
|
+
flush : (fn(self : Self, io : Io) -> Impl(Future(unit, IoExn)))({
|
|
177
172
|
fd := self._fd;
|
|
178
|
-
io.async((
|
|
179
|
-
result := io.await(IO_file.fsync(fd));
|
|
173
|
+
io.async((e) => {
|
|
174
|
+
result := e.io.await(IO_file.fsync(fd), e.io);
|
|
180
175
|
cond(
|
|
181
|
-
(result < i32(0)) => exn.throw(dyn(
|
|
176
|
+
(result < i32(0)) => e.exn.throw(dyn(IoError.from_errno(i32(0) - result))),
|
|
182
177
|
true => ()
|
|
183
178
|
)
|
|
184
179
|
})
|
|
185
180
|
}),
|
|
186
181
|
/// Seek to a position relative to `from`. Returns the new absolute byte offset.
|
|
187
|
-
seek : (fn(self : Self, offset : i64, from : SeekFrom,
|
|
182
|
+
seek : (fn(self : Self, offset : i64, from : SeekFrom, exn : Exception) -> i64)({
|
|
188
183
|
result := IO_seek.lseek(self._fd, offset, _seek_from_to_whence(from));
|
|
189
184
|
cond(
|
|
190
|
-
(result < i64(0)) => exn.throw(dyn(
|
|
185
|
+
(result < i64(0)) => exn.throw(dyn(IoError.from_errno(i32(i64(0) - result)))),
|
|
191
186
|
true => result
|
|
192
187
|
)
|
|
193
188
|
}),
|
|
@@ -200,17 +195,17 @@ impl(
|
|
|
200
195
|
IO_file.file_size(self._fd)
|
|
201
196
|
),
|
|
202
197
|
/// Close the file descriptor. Safe to call multiple times.
|
|
203
|
-
close : (fn(self : Self,
|
|
198
|
+
close : (fn(self : Self, io : Io) -> Impl(Future(unit, IoExn)))({
|
|
204
199
|
fd := self._fd;
|
|
205
200
|
io.async(
|
|
206
|
-
(
|
|
201
|
+
(e) =>
|
|
207
202
|
cond(
|
|
208
203
|
self._is_closed => (),
|
|
209
204
|
true => {
|
|
210
|
-
result := io.await(IO_file.close(fd));
|
|
205
|
+
result := e.io.await(IO_file.close(fd), e.io);
|
|
211
206
|
self._is_closed = true;
|
|
212
207
|
cond(
|
|
213
|
-
(result < i32(0)) => exn.throw(dyn(
|
|
208
|
+
(result < i32(0)) => e.exn.throw(dyn(IoError.from_errno(i32(0) - result))),
|
|
214
209
|
true => ()
|
|
215
210
|
)
|
|
216
211
|
}
|
|
@@ -226,8 +221,8 @@ impl(
|
|
|
226
221
|
self._path
|
|
227
222
|
),
|
|
228
223
|
/// Get file metadata (size, permissions, timestamps).
|
|
229
|
-
metadata : (fn(self : Self,
|
|
230
|
-
_metadata_mod.metadata(self._path)
|
|
224
|
+
metadata : (fn(self : Self, io : Io) -> Impl(Future(Metadata, IoExn)))(
|
|
225
|
+
_metadata_mod.metadata(self._path, io)
|
|
231
226
|
)
|
|
232
227
|
);
|
|
233
228
|
impl(
|
|
@@ -249,74 +244,74 @@ export(File, OpenMode, FilePermission, SeekFrom);
|
|
|
249
244
|
// Convenience functions
|
|
250
245
|
// ============================================================================
|
|
251
246
|
/// Read an entire file into a `String`.
|
|
252
|
-
read_string :: (fn(path : Path,
|
|
253
|
-
io.async((
|
|
254
|
-
file := io.await(File.open(path,.Read));
|
|
255
|
-
content := io.await(file.read_string());
|
|
256
|
-
io.await(file.close());
|
|
247
|
+
read_string :: (fn(path : Path, io : Io) -> Impl(Future(String, IoExn)))(
|
|
248
|
+
io.async((e) => {
|
|
249
|
+
file := e.io.await(File.open(path,.Read, io), e);
|
|
250
|
+
content := e.io.await(file.read_string(io), e);
|
|
251
|
+
e.io.await(file.close(io), e);
|
|
257
252
|
return(content);
|
|
258
253
|
})
|
|
259
254
|
);
|
|
260
255
|
/// Read an entire file into a `String` (`str` path variant).
|
|
261
|
-
read_string_str :: (fn(path : str,
|
|
262
|
-
read_string(Path.new(String.from(path)))
|
|
256
|
+
read_string_str :: (fn(path : str, io : Io) -> Impl(Future(String, IoExn)))(
|
|
257
|
+
read_string(Path.new(String.from(path)), io)
|
|
263
258
|
);
|
|
264
259
|
/// Read an entire file into a `String` (C string path variant).
|
|
265
|
-
read_string_cstr :: (fn(path : *(u8),
|
|
266
|
-
read_string(Path.from_cstr(path))
|
|
260
|
+
read_string_cstr :: (fn(path : *(u8), io : Io) -> Impl(Future(String, IoExn)))(
|
|
261
|
+
read_string(Path.from_cstr(path), io)
|
|
267
262
|
);
|
|
268
263
|
/// Read an entire file into a byte list (`ArrayList(u8)`).
|
|
269
|
-
read_file :: (fn(path : Path,
|
|
270
|
-
io.async((
|
|
271
|
-
file := io.await(File.open(path,.Read));
|
|
272
|
-
content := io.await(file.read_bytes());
|
|
273
|
-
io.await(file.close());
|
|
264
|
+
read_file :: (fn(path : Path, io : Io) -> Impl(Future(ArrayList(u8), IoExn)))(
|
|
265
|
+
io.async((e) => {
|
|
266
|
+
file := e.io.await(File.open(path,.Read, io), e);
|
|
267
|
+
content := e.io.await(file.read_bytes(io), e);
|
|
268
|
+
e.io.await(file.close(io), e);
|
|
274
269
|
return(content);
|
|
275
270
|
})
|
|
276
271
|
);
|
|
277
272
|
/// Read an entire file into bytes (`str` path variant).
|
|
278
|
-
read_file_str :: (fn(path : str,
|
|
279
|
-
read_file(Path.new(String.from(path)))
|
|
273
|
+
read_file_str :: (fn(path : str, io : Io) -> Impl(Future(ArrayList(u8), IoExn)))(
|
|
274
|
+
read_file(Path.new(String.from(path)), io)
|
|
280
275
|
);
|
|
281
276
|
/// Read an entire file into bytes (C string path variant).
|
|
282
|
-
read_file_cstr :: (fn(path : *(u8),
|
|
283
|
-
read_file(Path.from_cstr(path))
|
|
277
|
+
read_file_cstr :: (fn(path : *(u8), io : Io) -> Impl(Future(ArrayList(u8), IoExn)))(
|
|
278
|
+
read_file(Path.from_cstr(path), io)
|
|
284
279
|
);
|
|
285
280
|
/// Write a `String` to a file, creating or truncating it.
|
|
286
|
-
write_file :: (fn(path : Path, data : String,
|
|
287
|
-
io.async((
|
|
288
|
-
file := io.await(File.open(path,.Write));
|
|
289
|
-
io.await(file.write_string(data));
|
|
290
|
-
io.await(file.close());
|
|
281
|
+
write_file :: (fn(path : Path, data : String, io : Io) -> Impl(Future(unit, IoExn)))(
|
|
282
|
+
io.async((e) => {
|
|
283
|
+
file := e.io.await(File.open(path,.Write, io), e);
|
|
284
|
+
e.io.await(file.write_string(data, io), e);
|
|
285
|
+
e.io.await(file.close(io), e);
|
|
291
286
|
})
|
|
292
287
|
);
|
|
293
288
|
/// Write a `str` to a file, creating or truncating it (`str` path variant).
|
|
294
|
-
write_file_str :: (fn(path : str, data : str,
|
|
295
|
-
write_file(Path.new(String.from(path)), String.from(data))
|
|
289
|
+
write_file_str :: (fn(path : str, data : str, io : Io) -> Impl(Future(unit, IoExn)))(
|
|
290
|
+
write_file(Path.new(String.from(path)), String.from(data), io)
|
|
296
291
|
);
|
|
297
292
|
/// Write a `str` to a file, creating or truncating it (C string path variant).
|
|
298
|
-
write_file_cstr :: (fn(path : *(u8), data : str,
|
|
299
|
-
write_file(Path.from_cstr(path), String.from(data))
|
|
293
|
+
write_file_cstr :: (fn(path : *(u8), data : str, io : Io) -> Impl(Future(unit, IoExn)))(
|
|
294
|
+
write_file(Path.from_cstr(path), String.from(data), io)
|
|
300
295
|
);
|
|
301
296
|
/// Write bytes to a file, creating or truncating it.
|
|
302
|
-
write_bytes :: (fn(path : Path, data : ArrayList(u8),
|
|
303
|
-
io.async((
|
|
304
|
-
file := io.await(File.open(path,.Write));
|
|
305
|
-
io.await(file.write_bytes(data));
|
|
306
|
-
io.await(file.close());
|
|
297
|
+
write_bytes :: (fn(path : Path, data : ArrayList(u8), io : Io) -> Impl(Future(unit, IoExn)))(
|
|
298
|
+
io.async((e) => {
|
|
299
|
+
file := e.io.await(File.open(path,.Write, io), e);
|
|
300
|
+
e.io.await(file.write_bytes(data, io), e);
|
|
301
|
+
e.io.await(file.close(io), e);
|
|
307
302
|
})
|
|
308
303
|
);
|
|
309
304
|
/// Append a `String` to a file, creating it if it does not exist.
|
|
310
|
-
append_file :: (fn(path : Path, data : String,
|
|
311
|
-
io.async((
|
|
312
|
-
file := io.await(File.open(path,.Append));
|
|
313
|
-
io.await(file.write_string(data));
|
|
314
|
-
io.await(file.close());
|
|
305
|
+
append_file :: (fn(path : Path, data : String, io : Io) -> Impl(Future(unit, IoExn)))(
|
|
306
|
+
io.async((e) => {
|
|
307
|
+
file := e.io.await(File.open(path,.Append, io), e);
|
|
308
|
+
e.io.await(file.write_string(data, io), e);
|
|
309
|
+
e.io.await(file.close(io), e);
|
|
315
310
|
})
|
|
316
311
|
);
|
|
317
312
|
/// Append a `str` to a file (`str` path variant).
|
|
318
|
-
append_file_str :: (fn(path : str, data : str,
|
|
319
|
-
append_file(Path.new(String.from(path)), String.from(data))
|
|
313
|
+
append_file_str :: (fn(path : str, data : str, io : Io) -> Impl(Future(unit, IoExn)))(
|
|
314
|
+
append_file(Path.new(String.from(path)), String.from(data), io)
|
|
320
315
|
);
|
|
321
316
|
extern(
|
|
322
317
|
"Yo",
|
|
@@ -324,34 +319,34 @@ extern(
|
|
|
324
319
|
);
|
|
325
320
|
/// Check if a path exists. Returns `false` for any error including file not found.
|
|
326
321
|
/// Does not use the `Exception` effect.
|
|
327
|
-
exists :: (fn(path : Path,
|
|
328
|
-
io.async((
|
|
322
|
+
exists :: (fn(path : Path, io : Io) -> Impl(Future(bool, Io)))(
|
|
323
|
+
io.async((io) => {
|
|
329
324
|
cstr_bytes := path.to_string().to_cstr();
|
|
330
325
|
cstr := cstr_bytes.ptr().unwrap();
|
|
331
326
|
buf_size := __yo_statx_buf_size();
|
|
332
327
|
buf := *(u8)(malloc(buf_size).unwrap());
|
|
333
|
-
result := io.await(IO_file.statx(AT_FDCWD, cstr, AT_STATX_SYNC_AS_STAT, STATX_BASIC_STATS, buf));
|
|
328
|
+
result := io.await(IO_file.statx(AT_FDCWD, cstr, AT_STATX_SYNC_AS_STAT, STATX_BASIC_STATS, buf), io);
|
|
334
329
|
free(.Some(*(void)(buf)));
|
|
335
330
|
result >= i32(0)
|
|
336
331
|
})
|
|
337
332
|
);
|
|
338
333
|
/// Check if a path exists (`str` path variant).
|
|
339
|
-
exists_str :: (fn(path : str,
|
|
340
|
-
exists(Path.new(String.from(path)),
|
|
334
|
+
exists_str :: (fn(path : str, io : Io) -> Impl(Future(bool, Io)))(
|
|
335
|
+
exists(Path.new(String.from(path)), io)
|
|
341
336
|
);
|
|
342
337
|
/// Check if a path exists (C string path variant).
|
|
343
|
-
exists_cstr :: (fn(path : *(u8),
|
|
344
|
-
exists(Path.from_cstr(path),
|
|
338
|
+
exists_cstr :: (fn(path : *(u8), io : Io) -> Impl(Future(bool, Io)))(
|
|
339
|
+
exists(Path.from_cstr(path), io)
|
|
345
340
|
);
|
|
346
341
|
/// Check if a path is a regular file. Returns `false` for any error.
|
|
347
|
-
is_file :: (fn(path : Path,
|
|
348
|
-
io.async((
|
|
342
|
+
is_file :: (fn(path : Path, io : Io) -> Impl(Future(bool, Io)))(
|
|
343
|
+
io.async((io) => {
|
|
349
344
|
path_str := path.to_string();
|
|
350
345
|
cstr_bytes := path_str.to_cstr();
|
|
351
346
|
cstr := cstr_bytes.ptr().unwrap();
|
|
352
347
|
buf_size := __yo_statx_buf_size();
|
|
353
348
|
buf := *(u8)(malloc(buf_size).unwrap());
|
|
354
|
-
result := io.await(IO_file.statx(AT_FDCWD, cstr, AT_STATX_SYNC_AS_STAT, STATX_BASIC_STATS, buf));
|
|
349
|
+
result := io.await(IO_file.statx(AT_FDCWD, cstr, AT_STATX_SYNC_AS_STAT, STATX_BASIC_STATS, buf), io);
|
|
355
350
|
r := cond(
|
|
356
351
|
(result < i32(0)) => false,
|
|
357
352
|
true => {
|
|
@@ -364,22 +359,22 @@ is_file :: (fn(path : Path, using(io : IO)) -> Impl(Future(bool, IO)))(
|
|
|
364
359
|
})
|
|
365
360
|
);
|
|
366
361
|
/// Check if a path is a regular file (`str` path variant).
|
|
367
|
-
is_file_str :: (fn(path : str,
|
|
368
|
-
is_file(Path.new(String.from(path)),
|
|
362
|
+
is_file_str :: (fn(path : str, io : Io) -> Impl(Future(bool, Io)))(
|
|
363
|
+
is_file(Path.new(String.from(path)), io)
|
|
369
364
|
);
|
|
370
365
|
/// Check if a path is a regular file (C string path variant).
|
|
371
|
-
is_file_cstr :: (fn(path : *(u8),
|
|
372
|
-
is_file(Path.from_cstr(path),
|
|
366
|
+
is_file_cstr :: (fn(path : *(u8), io : Io) -> Impl(Future(bool, Io)))(
|
|
367
|
+
is_file(Path.from_cstr(path), io)
|
|
373
368
|
);
|
|
374
369
|
/// Check if a path is a directory. Returns `false` for any error.
|
|
375
|
-
is_dir :: (fn(path : Path,
|
|
376
|
-
io.async((
|
|
370
|
+
is_dir :: (fn(path : Path, io : Io) -> Impl(Future(bool, Io)))(
|
|
371
|
+
io.async((io) => {
|
|
377
372
|
path_str := path.to_string();
|
|
378
373
|
cstr_bytes := path_str.to_cstr();
|
|
379
374
|
cstr := cstr_bytes.ptr().unwrap();
|
|
380
375
|
buf_size := __yo_statx_buf_size();
|
|
381
376
|
buf := *(u8)(malloc(buf_size).unwrap());
|
|
382
|
-
result := io.await(IO_file.statx(AT_FDCWD, cstr, AT_STATX_SYNC_AS_STAT, STATX_BASIC_STATS, buf));
|
|
377
|
+
result := io.await(IO_file.statx(AT_FDCWD, cstr, AT_STATX_SYNC_AS_STAT, STATX_BASIC_STATS, buf), io);
|
|
383
378
|
r := cond(
|
|
384
379
|
(result < i32(0)) => false,
|
|
385
380
|
true => {
|
|
@@ -392,33 +387,33 @@ is_dir :: (fn(path : Path, using(io : IO)) -> Impl(Future(bool, IO)))(
|
|
|
392
387
|
})
|
|
393
388
|
);
|
|
394
389
|
/// Check if a path is a directory (`str` path variant).
|
|
395
|
-
is_dir_str :: (fn(path : str,
|
|
396
|
-
is_dir(Path.new(String.from(path)),
|
|
390
|
+
is_dir_str :: (fn(path : str, io : Io) -> Impl(Future(bool, Io)))(
|
|
391
|
+
is_dir(Path.new(String.from(path)), io)
|
|
397
392
|
);
|
|
398
393
|
/// Check if a path is a directory (C string path variant).
|
|
399
|
-
is_dir_cstr :: (fn(path : *(u8),
|
|
400
|
-
is_dir(Path.from_cstr(path),
|
|
394
|
+
is_dir_cstr :: (fn(path : *(u8), io : Io) -> Impl(Future(bool, Io)))(
|
|
395
|
+
is_dir(Path.from_cstr(path), io)
|
|
401
396
|
);
|
|
402
397
|
/// Resolve a path to its canonical absolute form (resolves symlinks, `.` and `..`).
|
|
403
398
|
/// Throws if the path does not exist.
|
|
404
|
-
canonical :: (fn(path : Path,
|
|
405
|
-
io.async((
|
|
399
|
+
canonical :: (fn(path : Path, io : Io) -> Impl(Future(Path, IoExn)))(
|
|
400
|
+
io.async((e) => {
|
|
406
401
|
path_str := path.to_string();
|
|
407
402
|
cstr_bytes := path_str.to_cstr();
|
|
408
403
|
cstr := cstr_bytes.ptr().unwrap();
|
|
409
404
|
// Async stat to verify path exists (provides await point for proper RC cleanup)
|
|
410
405
|
buf_size := __yo_statx_buf_size();
|
|
411
406
|
stat_buf := *(u8)(malloc(buf_size).unwrap());
|
|
412
|
-
stat_result := io.await(IO_file.statx(AT_FDCWD, cstr, AT_STATX_SYNC_AS_STAT, STATX_BASIC_STATS, stat_buf));
|
|
407
|
+
stat_result := e.io.await(IO_file.statx(AT_FDCWD, cstr, AT_STATX_SYNC_AS_STAT, STATX_BASIC_STATS, stat_buf), e.io);
|
|
413
408
|
free(.Some(*(void)(stat_buf)));
|
|
414
|
-
|
|
409
|
+
IoError.check(stat_result, e.exn);
|
|
415
410
|
// Resolve the canonical path
|
|
416
411
|
resolved_buf := *(u8)(malloc(usize(4096)).unwrap());
|
|
417
412
|
rp_result := IO_path.realpath(cstr, resolved_buf);
|
|
418
413
|
cond(
|
|
419
414
|
(rp_result < i32(0)) => {
|
|
420
415
|
free(.Some(*(void)(resolved_buf)));
|
|
421
|
-
|
|
416
|
+
IoError.check(rp_result, e.exn);
|
|
422
417
|
},
|
|
423
418
|
true => ()
|
|
424
419
|
);
|
|
@@ -428,12 +423,12 @@ canonical :: (fn(path : Path, using(io : IO)) -> Impl(Future(Path, IO, Exception
|
|
|
428
423
|
})
|
|
429
424
|
);
|
|
430
425
|
/// Resolve a path to its canonical absolute form (`str` path variant).
|
|
431
|
-
canonical_str :: (fn(path : str,
|
|
432
|
-
canonical(Path.new(String.from(path)))
|
|
426
|
+
canonical_str :: (fn(path : str, io : Io) -> Impl(Future(Path, IoExn)))(
|
|
427
|
+
canonical(Path.new(String.from(path)), io)
|
|
433
428
|
);
|
|
434
429
|
/// Resolve a path to its canonical absolute form (C string path variant).
|
|
435
|
-
canonical_cstr :: (fn(path : *(u8),
|
|
436
|
-
canonical(Path.from_cstr(path))
|
|
430
|
+
canonical_cstr :: (fn(path : *(u8), io : Io) -> Impl(Future(Path, IoExn)))(
|
|
431
|
+
canonical(Path.from_cstr(path), io)
|
|
437
432
|
);
|
|
438
433
|
export(
|
|
439
434
|
read_string,
|
package/std/fs/metadata.yo
CHANGED
|
@@ -6,24 +6,19 @@
|
|
|
6
6
|
//! ```rust
|
|
7
7
|
//! { metadata } :: import "std/fs/metadata";
|
|
8
8
|
//!
|
|
9
|
-
//! main :: (fn(
|
|
10
|
-
//!
|
|
11
|
-
//! throw : (fn(forall(T : Type), error: AnyError) -> T)(
|
|
12
|
-
//! { println(error.to_string()); exit(i32(1)); }
|
|
13
|
-
//! )
|
|
14
|
-
//! };
|
|
15
|
-
//!
|
|
16
|
-
//! m := io.await(metadata(Path.new(`/tmp/test.txt`)));
|
|
9
|
+
//! main :: (fn(io : Io, exn : Exception) -> unit)({
|
|
10
|
+
//! m := io.await(metadata(Path.new(`/tmp/test.txt`), io), { io, exn });
|
|
17
11
|
//! printf("size: %lld\n", m.size());
|
|
18
12
|
//! printf("is file: %d\n", i32(m.is_file()));
|
|
19
13
|
//! });
|
|
20
14
|
//! ```
|
|
15
|
+
pragma(Pragma.AllowUnsafe);
|
|
21
16
|
{ GlobalAllocator } :: import("../allocator");
|
|
22
17
|
{ malloc, free } :: GlobalAllocator;
|
|
23
18
|
open(import("../string"));
|
|
24
19
|
{ Path } :: import("../path");
|
|
25
|
-
{
|
|
26
|
-
{ Error, AnyError, Exception } :: import("../error");
|
|
20
|
+
{ IoError } :: import("../sys/errors");
|
|
21
|
+
{ Error, AnyError, Exception, IoExn } :: import("../error");
|
|
27
22
|
{ Statx } :: import("../sys/statx");
|
|
28
23
|
IO_file :: import("../sys/file");
|
|
29
24
|
{ AT_FDCWD, AT_SYMLINK_NOFOLLOW, AT_STATX_SYNC_AS_STAT, STATX_BASIC_STATS, S_IFMT, S_IFREG, S_IFDIR, S_IFLNK, S_IWUSR, S_IWGRP, S_IWOTH } :: import("../sys/constants");
|
|
@@ -107,17 +102,17 @@ extern(
|
|
|
107
102
|
// ============================================================================
|
|
108
103
|
// Internal helper to stat a path
|
|
109
104
|
// ============================================================================
|
|
110
|
-
_stat_path :: (fn(path : Path, flags : i32,
|
|
111
|
-
io.async((
|
|
105
|
+
_stat_path :: (fn(path : Path, flags : i32, io : Io) -> Impl(Future(Metadata, IoExn)))(
|
|
106
|
+
io.async((e) => {
|
|
112
107
|
cstr_bytes := path.to_string().to_cstr();
|
|
113
108
|
cstr := cstr_bytes.ptr().unwrap();
|
|
114
109
|
buf_size := __yo_statx_buf_size();
|
|
115
110
|
buf := *(u8)(malloc(buf_size).unwrap());
|
|
116
|
-
result := io.await(IO_file.statx(AT_FDCWD, cstr, flags, STATX_BASIC_STATS, buf));
|
|
111
|
+
result := e.io.await(IO_file.statx(AT_FDCWD, cstr, flags, STATX_BASIC_STATS, buf), e.io);
|
|
117
112
|
cond(
|
|
118
113
|
(result < i32(0)) => {
|
|
119
114
|
free(.Some(*(void)(buf)));
|
|
120
|
-
exn.throw(dyn(
|
|
115
|
+
e.exn.throw(dyn(IoError.from_errno(i32(0) - result)))
|
|
121
116
|
},
|
|
122
117
|
true => {
|
|
123
118
|
sx := Statx(_buf_ptr : buf, _buf_size : buf_size);
|
|
@@ -127,11 +122,11 @@ _stat_path :: (fn(path : Path, flags : i32, using(io : IO)) -> Impl(Future(Metad
|
|
|
127
122
|
})
|
|
128
123
|
);
|
|
129
124
|
/// Get metadata for a path (follows symlinks).
|
|
130
|
-
metadata :: (fn(path : Path,
|
|
125
|
+
metadata :: (fn(path : Path, io : Io) -> Impl(Future(Metadata, IoExn)))(_stat_path(path, AT_STATX_SYNC_AS_STAT, io));
|
|
131
126
|
/// Get metadata for a path given as a raw string (follows symlinks).
|
|
132
|
-
metadata_str :: (fn(path : str,
|
|
127
|
+
metadata_str :: (fn(path : str, io : Io) -> Impl(Future(Metadata, IoExn)))(metadata(Path.new(String.from(path)), io));
|
|
133
128
|
/// Get metadata for a path (does NOT follow symlinks).
|
|
134
|
-
symlink_metadata :: (fn(path : Path,
|
|
129
|
+
symlink_metadata :: (fn(path : Path, io : Io) -> Impl(Future(Metadata, IoExn)))(_stat_path(path, AT_SYMLINK_NOFOLLOW | AT_STATX_SYNC_AS_STAT, io));
|
|
135
130
|
/// Get metadata for a path given as a raw string (does NOT follow symlinks).
|
|
136
|
-
symlink_metadata_str :: (fn(path : str,
|
|
131
|
+
symlink_metadata_str :: (fn(path : str, io : Io) -> Impl(Future(Metadata, IoExn)))(symlink_metadata(Path.new(String.from(path)), io));
|
|
137
132
|
export(metadata, metadata_str, symlink_metadata, symlink_metadata_str);
|