From ac45ec2b036b6c07df1f7aa3ab3003a88053e4e5 Mon Sep 17 00:00:00 2001 From: Nanaloveyuki Date: Wed, 20 May 2026 08:44:54 +0800 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Extract=20file=20backend?= =?UTF-8?q?=20into=20utils=20subpackage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/file_backend_native.mbt | 120 +++++------------------------- src/file_backend_stub.mbt | 54 +++++--------- src/utils/file_backend_native.mbt | 117 +++++++++++++++++++++++++++++ src/utils/file_backend_stub.mbt | 51 +++++++++++++ src/utils/moon.pkg | 7 ++ 5 files changed, 215 insertions(+), 134 deletions(-) create mode 100644 src/utils/file_backend_native.mbt create mode 100644 src/utils/file_backend_stub.mbt diff --git a/src/file_backend_native.mbt b/src/file_backend_native.mbt index c04e528..2d2527d 100644 --- a/src/file_backend_native.mbt +++ b/src/file_backend_native.mbt @@ -1,117 +1,37 @@ -fn string_to_c_bytes(str : String) -> Bytes { - let res : Array[Byte] = [] - let len = str.length() - let mut i = 0 - while i < len { - let mut c = str.code_unit_at(i).to_int() - if 0xD800 <= c && c <= 0xDBFF { - c -= 0xD800 - i = i + 1 - let l = str.code_unit_at(i).to_int() - 0xDC00 - c = (c << 10) + l + 0x10000 - } - if c < 0x80 { - res.push(c.to_byte()) - } else if c < 0x800 { - res.push((0xc0 + (c >> 6)).to_byte()) - res.push((0x80 + (c & 0x3f)).to_byte()) - } else if c < 0x10000 { - res.push((0xe0 + (c >> 12)).to_byte()) - res.push((0x80 + ((c >> 6) & 0x3f)).to_byte()) - res.push((0x80 + (c & 0x3f)).to_byte()) - } else { - res.push((0xf0 + (c >> 18)).to_byte()) - res.push((0x80 + ((c >> 12) & 0x3f)).to_byte()) - res.push((0x80 + ((c >> 6) & 0x3f)).to_byte()) - res.push((0x80 + (c & 0x3f)).to_byte()) - } - i = i + 1 - } - res.push((0).to_byte()) - Bytes::from_array(res) +pub type FileHandle = @utils.FileHandle + +pub fn open_file_handle_internal(path : String, append : Bool) -> FileHandle? { + @utils.open_file_handle_internal(path, append) } -#external -type NativeFileHandle - -#borrow(path, mode) -extern "C" fn file_open_ffi(path : Bytes, mode : Bytes) -> NativeFileHandle = "fopen" - -extern "C" fn file_is_null_ffi(handle : NativeFileHandle) -> Bool = "moonbitlang_async_pointer_is_null" - -#borrow(buffer) -extern "C" fn file_write_ffi( - buffer : Bytes, - size : Int, - count : Int, - handle : NativeFileHandle, -) -> Int = "fwrite" - -extern "C" fn file_flush_ffi(handle : NativeFileHandle) -> Int = "fflush" - -extern "C" fn file_close_ffi(handle : NativeFileHandle) -> Int = "fclose" - -extern "C" fn file_seek_ffi(handle : NativeFileHandle, offset : Int, origin : Int) -> Int = "fseek" - -extern "C" fn file_tell_ffi(handle : NativeFileHandle) -> Int = "ftell" - -#borrow(from_path, to_path) -extern "C" fn file_rename_ffi(from_path : Bytes, to_path : Bytes) -> Int = "rename" - -#borrow(path) -extern "C" fn file_remove_ffi(path : Bytes) -> Int = "remove" - -pub struct FileHandle { - path : String - raw : NativeFileHandle +pub fn write_file_handle_internal(handle : FileHandle, content : String) -> Bool { + @utils.write_file_handle_internal(handle, content) } -fn open_file_handle_internal(path : String, append : Bool) -> FileHandle? { - let mode = if append { "ab" } else { "wb" } - let raw = file_open_ffi(string_to_c_bytes(path), string_to_c_bytes(mode)) - if file_is_null_ffi(raw) { - None - } else { - Some({ raw, path }) - } +pub fn flush_file_handle_internal(handle : FileHandle) -> Bool { + @utils.flush_file_handle_internal(handle) } -fn write_file_handle_internal(handle : FileHandle, content : String) -> Bool { - let bytes = string_to_c_bytes(content) - let written = file_write_ffi(bytes, 1, bytes.length() - 1, handle.raw) - written == bytes.length() - 1 +pub fn close_file_handle_internal(handle : FileHandle) -> Bool { + @utils.close_file_handle_internal(handle) } -fn flush_file_handle_internal(handle : FileHandle) -> Bool { - file_flush_ffi(handle.raw) == 0 +pub fn file_size_internal(handle : FileHandle) -> Int { + @utils.file_size_internal(handle) } -fn close_file_handle_internal(handle : FileHandle) -> Bool { - file_close_ffi(handle.raw) == 0 +pub fn rename_file_internal(from_path : String, to_path : String) -> Bool { + @utils.rename_file_internal(from_path, to_path) } -fn file_size_internal(handle : FileHandle) -> Int { - ignore(file_seek_ffi(handle.raw, 0, 2)) - let size = file_tell_ffi(handle.raw) - if size < 0 { - 0 - } else { - size - } +pub fn remove_file_internal(path : String) -> Bool { + @utils.remove_file_internal(path) } -fn rename_file_internal(from_path : String, to_path : String) -> Bool { - file_rename_ffi(string_to_c_bytes(from_path), string_to_c_bytes(to_path)) == 0 +pub fn string_byte_length_internal(content : String) -> Int { + @utils.string_byte_length_internal(content) } -fn remove_file_internal(path : String) -> Bool { - file_remove_ffi(string_to_c_bytes(path)) == 0 -} - -fn string_byte_length_internal(content : String) -> Int { - string_to_c_bytes(content).length() - 1 -} - -fn native_files_supported_internal() -> Bool { - true +pub fn native_files_supported_internal() -> Bool { + @utils.native_files_supported_internal() } diff --git a/src/file_backend_stub.mbt b/src/file_backend_stub.mbt index 03be947..2d2527d 100644 --- a/src/file_backend_stub.mbt +++ b/src/file_backend_stub.mbt @@ -1,51 +1,37 @@ -pub struct FileHandle { - path : String +pub type FileHandle = @utils.FileHandle + +pub fn open_file_handle_internal(path : String, append : Bool) -> FileHandle? { + @utils.open_file_handle_internal(path, append) } -fn open_file_handle_internal(path : String, append : Bool) -> FileHandle? { - ignore(append) - ignore(path) - let _unused : FileHandle = { path: "" } - ignore(_unused) - None +pub fn write_file_handle_internal(handle : FileHandle, content : String) -> Bool { + @utils.write_file_handle_internal(handle, content) } -fn write_file_handle_internal(handle : FileHandle, content : String) -> Bool { - ignore(handle) - ignore(content) - false +pub fn flush_file_handle_internal(handle : FileHandle) -> Bool { + @utils.flush_file_handle_internal(handle) } -fn flush_file_handle_internal(handle : FileHandle) -> Bool { - ignore(handle) - false +pub fn close_file_handle_internal(handle : FileHandle) -> Bool { + @utils.close_file_handle_internal(handle) } -fn close_file_handle_internal(handle : FileHandle) -> Bool { - ignore(handle) - false +pub fn file_size_internal(handle : FileHandle) -> Int { + @utils.file_size_internal(handle) } -fn file_size_internal(handle : FileHandle) -> Int { - ignore(handle) - 0 +pub fn rename_file_internal(from_path : String, to_path : String) -> Bool { + @utils.rename_file_internal(from_path, to_path) } -fn rename_file_internal(from_path : String, to_path : String) -> Bool { - ignore(from_path) - ignore(to_path) - false +pub fn remove_file_internal(path : String) -> Bool { + @utils.remove_file_internal(path) } -fn remove_file_internal(path : String) -> Bool { - ignore(path) - false +pub fn string_byte_length_internal(content : String) -> Int { + @utils.string_byte_length_internal(content) } -fn string_byte_length_internal(content : String) -> Int { - content.length() -} - -fn native_files_supported_internal() -> Bool { - false +pub fn native_files_supported_internal() -> Bool { + @utils.native_files_supported_internal() } diff --git a/src/utils/file_backend_native.mbt b/src/utils/file_backend_native.mbt new file mode 100644 index 0000000..dde4854 --- /dev/null +++ b/src/utils/file_backend_native.mbt @@ -0,0 +1,117 @@ +fn string_to_c_bytes(str : String) -> Bytes { + let res : Array[Byte] = [] + let len = str.length() + let mut i = 0 + while i < len { + let mut c = str.code_unit_at(i).to_int() + if 0xD800 <= c && c <= 0xDBFF { + c -= 0xD800 + i = i + 1 + let l = str.code_unit_at(i).to_int() - 0xDC00 + c = (c << 10) + l + 0x10000 + } + if c < 0x80 { + res.push(c.to_byte()) + } else if c < 0x800 { + res.push((0xc0 + (c >> 6)).to_byte()) + res.push((0x80 + (c & 0x3f)).to_byte()) + } else if c < 0x10000 { + res.push((0xe0 + (c >> 12)).to_byte()) + res.push((0x80 + ((c >> 6) & 0x3f)).to_byte()) + res.push((0x80 + (c & 0x3f)).to_byte()) + } else { + res.push((0xf0 + (c >> 18)).to_byte()) + res.push((0x80 + ((c >> 12) & 0x3f)).to_byte()) + res.push((0x80 + ((c >> 6) & 0x3f)).to_byte()) + res.push((0x80 + (c & 0x3f)).to_byte()) + } + i = i + 1 + } + res.push((0).to_byte()) + Bytes::from_array(res) +} + +#external +type NativeFileHandle + +#borrow(path, mode) +extern "C" fn file_open_ffi(path : Bytes, mode : Bytes) -> NativeFileHandle = "fopen" + +extern "C" fn file_is_null_ffi(handle : NativeFileHandle) -> Bool = "moonbitlang_async_pointer_is_null" + +#borrow(buffer) +extern "C" fn file_write_ffi( + buffer : Bytes, + size : Int, + count : Int, + handle : NativeFileHandle, +) -> Int = "fwrite" + +extern "C" fn file_flush_ffi(handle : NativeFileHandle) -> Int = "fflush" + +extern "C" fn file_close_ffi(handle : NativeFileHandle) -> Int = "fclose" + +extern "C" fn file_seek_ffi(handle : NativeFileHandle, offset : Int, origin : Int) -> Int = "fseek" + +extern "C" fn file_tell_ffi(handle : NativeFileHandle) -> Int = "ftell" + +#borrow(from_path, to_path) +extern "C" fn file_rename_ffi(from_path : Bytes, to_path : Bytes) -> Int = "rename" + +#borrow(path) +extern "C" fn file_remove_ffi(path : Bytes) -> Int = "remove" + +pub struct FileHandle { + path : String + raw : NativeFileHandle +} + +pub fn open_file_handle_internal(path : String, append : Bool) -> FileHandle? { + let mode = if append { "ab" } else { "wb" } + let raw = file_open_ffi(string_to_c_bytes(path), string_to_c_bytes(mode)) + if file_is_null_ffi(raw) { + None + } else { + Some({ raw, path }) + } +} + +pub fn write_file_handle_internal(handle : FileHandle, content : String) -> Bool { + let bytes = string_to_c_bytes(content) + let written = file_write_ffi(bytes, 1, bytes.length() - 1, handle.raw) + written == bytes.length() - 1 +} + +pub fn flush_file_handle_internal(handle : FileHandle) -> Bool { + file_flush_ffi(handle.raw) == 0 +} + +pub fn close_file_handle_internal(handle : FileHandle) -> Bool { + file_close_ffi(handle.raw) == 0 +} + +pub fn file_size_internal(handle : FileHandle) -> Int { + ignore(file_seek_ffi(handle.raw, 0, 2)) + let size = file_tell_ffi(handle.raw) + if size < 0 { + 0 + } else { + size + } +} + +pub fn rename_file_internal(from_path : String, to_path : String) -> Bool { + file_rename_ffi(string_to_c_bytes(from_path), string_to_c_bytes(to_path)) == 0 +} + +pub fn remove_file_internal(path : String) -> Bool { + file_remove_ffi(string_to_c_bytes(path)) == 0 +} + +pub fn string_byte_length_internal(content : String) -> Int { + string_to_c_bytes(content).length() - 1 +} + +pub fn native_files_supported_internal() -> Bool { + true +} diff --git a/src/utils/file_backend_stub.mbt b/src/utils/file_backend_stub.mbt new file mode 100644 index 0000000..9877d6f --- /dev/null +++ b/src/utils/file_backend_stub.mbt @@ -0,0 +1,51 @@ +pub struct FileHandle { + path : String +} + +pub fn open_file_handle_internal(path : String, append : Bool) -> FileHandle? { + ignore(append) + ignore(path) + let _unused : FileHandle = { path: "" } + ignore(_unused) + None +} + +pub fn write_file_handle_internal(handle : FileHandle, content : String) -> Bool { + ignore(handle) + ignore(content) + false +} + +pub fn flush_file_handle_internal(handle : FileHandle) -> Bool { + ignore(handle) + false +} + +pub fn close_file_handle_internal(handle : FileHandle) -> Bool { + ignore(handle) + false +} + +pub fn file_size_internal(handle : FileHandle) -> Int { + ignore(handle) + 0 +} + +pub fn rename_file_internal(from_path : String, to_path : String) -> Bool { + ignore(from_path) + ignore(to_path) + false +} + +pub fn remove_file_internal(path : String) -> Bool { + ignore(path) + false +} + +pub fn string_byte_length_internal(content : String) -> Int { + content.length() +} + +pub fn native_files_supported_internal() -> Bool { + false +} diff --git a/src/utils/moon.pkg b/src/utils/moon.pkg index f1c50a1..462b689 100644 --- a/src/utils/moon.pkg +++ b/src/utils/moon.pkg @@ -4,3 +4,10 @@ import { "moonbitlang/core/json", "moonbitlang/core/ref", } + +options( + targets: { + "file_backend_native.mbt": [ "native", "llvm" ], + "file_backend_stub.mbt": [ "js", "wasm", "wasm-gc" ], + }, +)