Skip to content

Commit 891e91a

Browse files
committed
add predicates for @os_error.OSError
1 parent d98b1cf commit 891e91a

File tree

7 files changed

+87
-27
lines changed

7 files changed

+87
-27
lines changed

src/fs/stub.c

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -102,14 +102,6 @@ int moonbitlang_async_f_ok() {
102102
return F_OK;
103103
}
104104

105-
int moonbitlang_async_get_ENOENT() {
106-
return ENOENT;
107-
}
108-
109-
int moonbitlang_async_get_EACCES() {
110-
return EACCES;
111-
}
112-
113105
#ifdef __MACH__
114106
#define GET_STAT_TIMESTAMP(statp, kind) (statp)->st_##kind##timespec
115107
#else

src/fs/utils.mbt

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -75,22 +75,10 @@ extern "C" fn w_ok() -> Int = "moonbitlang_async_w_ok"
7575
///|
7676
extern "C" fn x_ok() -> Int = "moonbitlang_async_x_ok"
7777

78-
///|
79-
extern "C" fn get_ENOENT() -> Int = "moonbitlang_async_get_ENOENT"
80-
81-
///|
82-
let _ENOENT : Int = get_ENOENT()
83-
84-
///|
85-
extern "C" fn get_EACCES() -> Int = "moonbitlang_async_get_EACCES"
86-
87-
///|
88-
let _EACCES : Int = get_EACCES()
89-
9078
///|
9179
pub async fn exists(path : StringView) -> Bool {
9280
try @event_loop.access(path, amode=f_ok(), context="@fs.exists()") catch {
93-
@os_error.OSError(code, ..) if code == _ENOENT => false
81+
@os_error.OSError(_) as err if err.is_ENOENT() => false
9482
err => raise err
9583
} noraise {
9684
_ => true
@@ -100,8 +88,8 @@ pub async fn exists(path : StringView) -> Bool {
10088
///|
10189
pub async fn can_read(path : StringView) -> Bool {
10290
try @event_loop.access(path, amode=r_ok(), context="@fs.can_read()") catch {
103-
@os_error.OSError(code, ..) if code == _ENOENT => false
104-
@os_error.OSError(code, ..) if code == _EACCES => false
91+
@os_error.OSError(_) as err if err.is_ENOENT() => false
92+
@os_error.OSError(_) as err if err.is_EACCES() => false
10593
err => raise err
10694
} noraise {
10795
_ => true
@@ -111,8 +99,8 @@ pub async fn can_read(path : StringView) -> Bool {
11199
///|
112100
pub async fn can_write(path : StringView) -> Bool {
113101
try @event_loop.access(path, amode=w_ok(), context="@fs.can_write()") catch {
114-
@os_error.OSError(code, ..) if code == _ENOENT => false
115-
@os_error.OSError(code, ..) if code == _EACCES => false
102+
@os_error.OSError(_) as err if err.is_ENOENT() => false
103+
@os_error.OSError(_) as err if err.is_EACCES() => false
116104
err => raise err
117105
} noraise {
118106
_ => true
@@ -122,8 +110,8 @@ pub async fn can_write(path : StringView) -> Bool {
122110
///|
123111
pub async fn can_execute(path : StringView) -> Bool {
124112
try @event_loop.access(path, amode=x_ok(), context="@fs.can_execute") catch {
125-
@os_error.OSError(code, ..) if code == _ENOENT => false
126-
@os_error.OSError(code, ..) if code == _EACCES => false
113+
@os_error.OSError(_) as err if err.is_ENOENT() => false
114+
@os_error.OSError(_) as err if err.is_EACCES() => false
127115
err => raise err
128116
} noraise {
129117
_ => true

src/os_error/error.mbt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@ extern "C" fn errno_is_nonblocking_io_error(errno : Int) -> Bool = "moonbitlang_
2121
///|
2222
extern "C" fn errno_is_EINTR(errno : Int) -> Bool = "moonbitlang_async_is_EINTR"
2323

24+
///|
25+
extern "C" fn errno_is_ENOENT(errno : Int) -> Bool = "moonbitlang_async_is_ENOENT"
26+
27+
///|
28+
extern "C" fn errno_is_EEXIST(errno : Int) -> Bool = "moonbitlang_async_is_EEXIST"
29+
30+
///|
31+
extern "C" fn errno_is_EACCES(errno : Int) -> Bool = "moonbitlang_async_is_EACCES"
32+
2433
///|
2534
pub fn is_nonblocking_io_error() -> Bool {
2635
errno_is_nonblocking_io_error(get_errno())
@@ -62,6 +71,27 @@ pub fn OSError::is_EINTR(err : OSError) -> Bool {
6271
errno_is_EINTR(errno)
6372
}
6473

74+
///|
75+
/// Detect whether the error is the `ENOENT` (no such file or directory) error.
76+
pub fn OSError::is_ENOENT(err : OSError) -> Bool {
77+
let OSError(errno, ..) = err
78+
errno_is_ENOENT(errno)
79+
}
80+
81+
///|
82+
/// Detect whether the error is the `EEXIST` (already exists) error.
83+
pub fn OSError::is_EEXIST(err : OSError) -> Bool {
84+
let OSError(errno, ..) = err
85+
errno_is_EEXIST(errno)
86+
}
87+
88+
///|
89+
/// Detect whether the error is the `EACCES` (permission denied) error.
90+
pub fn OSError::is_EACCES(err : OSError) -> Bool {
91+
let OSError(errno, ..) = err
92+
errno_is_EACCES(errno)
93+
}
94+
6595
///|
6696
pub fn check_errno(context : String) -> Unit raise OSError {
6797
let err_code = get_errno()

src/os_error/moon.pkg.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,9 @@
22
"import": [
33
"moonbitlang/async/internal/c_buffer"
44
],
5+
"test-import": [
6+
"moonbitlang/async",
7+
"moonbitlang/async/fs"
8+
],
59
"native-stub": [ "stub.c" ]
610
}

src/os_error/os_error_test.mbt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2025 International Digital Economy Academy
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
///|
16+
async test "is_ENOENT" {
17+
let result = try? @fs.open("does_not_exist", mode=ReadOnly)
18+
guard result is Err(@os_error.OSError(_) as err) else {
19+
fail("result is not OSError")
20+
}
21+
assert_true(err.is_ENOENT())
22+
}
23+
24+
///|
25+
async test "is_EEXIST" {
26+
let result = try? @fs.mkdir("src", permission=0o755)
27+
guard result is Err(@os_error.OSError(_) as err) else {
28+
fail("result is not OSError")
29+
}
30+
assert_true(err.is_EEXIST())
31+
}

src/os_error/pkg.generated.mbti

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ fn is_nonblocking_io_error() -> Bool
1212
pub(all) suberror OSError {
1313
OSError(Int, context~ : String)
1414
}
15+
fn OSError::is_EACCES(Self) -> Bool
16+
fn OSError::is_EEXIST(Self) -> Bool
1517
fn OSError::is_EINTR(Self) -> Bool
18+
fn OSError::is_ENOENT(Self) -> Bool
1619
fn OSError::is_nonblocking_io_error(Self) -> Bool
1720
fn OSError::output(Self, &Logger) -> Unit // from trait `Show`
1821
fn OSError::to_string(Self) -> String // from trait `Show`

src/os_error/stub.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,18 @@ int moonbitlang_async_is_EINTR(int err) {
2929
return err == EINTR;
3030
}
3131

32+
int moonbitlang_async_is_ENOENT(int err) {
33+
return err == ENOENT;
34+
}
35+
36+
int moonbitlang_async_is_EEXIST(int err) {
37+
return err == EEXIST;
38+
}
39+
40+
int moonbitlang_async_is_EACCES(int err) {
41+
return err == EACCES;
42+
}
43+
3244
char *moonbitlang_async_errno_to_string(int err) {
3345
return strerror(err);
3446
}

0 commit comments

Comments
 (0)