Skip to content

Commit

Permalink
support read_bytes_from_stdin ffi in moonrun (#517)
Browse files Browse the repository at this point in the history
  • Loading branch information
RuifengFu authored Dec 17, 2024
1 parent b57ed1c commit e759b75
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 2 deletions.
35 changes: 33 additions & 2 deletions crates/moonrun/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,31 @@ fn read_char(
}
}

fn read_bytes_from_stdin(
scope: &mut v8::HandleScope,
_args: v8::FunctionCallbackArguments,
mut ret: v8::ReturnValue,
) {
let mut buffer = Vec::new();
let stdin = io::stdin();
let mut handle = stdin.lock();

let size = handle.read_to_end(&mut buffer).unwrap();

if size == 0 {
let empty_array_buffer = v8::ArrayBuffer::new(scope, 0);
let empty_uint8_array = v8::Uint8Array::new(scope, empty_array_buffer, 0, 0).unwrap();
ret.set(empty_uint8_array.into());
} else {
let array_buffer = v8::ArrayBuffer::new(scope, size);
let uint8_array = v8::Uint8Array::new(scope, array_buffer, 0, size).unwrap();
unsafe {
std::ptr::copy(buffer.as_ptr(), get_array_buffer_ptr(array_buffer), size);
}
ret.set(uint8_array.into());
}
}

fn read_file_to_bytes(
scope: &mut v8::HandleScope,
args: v8::FunctionCallbackArguments,
Expand Down Expand Up @@ -332,9 +357,9 @@ fn init_env(dtors: &mut Vec<Box<dyn Any>>, scope: &mut v8::HandleScope, args: &[
// API for the fs module
let identifier = v8::String::new(scope, "__moonbit_fs_unstable").unwrap();
let obj = v8::Object::new(scope);
let obj = js::init_env(obj, scope);
let obj: v8::Local<'_, v8::Object> = js::init_env(obj, scope);
let obj = sys_api::init_env(obj, scope, args);
let obj = fs_api_temp::init_fs(obj, scope);
let obj: v8::Local<'_, v8::Object> = fs_api_temp::init_fs(obj, scope);
global_proxy.set(scope, identifier.into(), obj.into());

{
Expand All @@ -350,6 +375,12 @@ fn init_env(dtors: &mut Vec<Box<dyn Any>>, scope: &mut v8::HandleScope, args: &[
let obj = v8::Object::new(scope);
global_proxy.set(scope, identifier.into(), obj.into());

let identifier = v8::String::new(scope, "read_bytes_from_stdin").unwrap();
let value = v8::Function::builder(read_bytes_from_stdin)
.build(scope)
.unwrap();
obj.set(scope, identifier.into(), value.into());

let identifier = v8::String::new(scope, "read_char").unwrap();
let value = v8::Function::builder(read_char).build(scope).unwrap();
obj.set(scope, identifier.into(), value.into());
Expand Down
35 changes: 35 additions & 0 deletions crates/moonrun/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,38 @@ fn test_moon_run_with_cli_args() {

assert!(s.contains("\"中文\", \"😄👍\", \"hello\", \"1242\""));
}

#[test]
fn test_moon_run_with_read_bytes_from_stdin() {
let dir = TestDir::new("test_read_bytes.in");

snapbox::cmd::Command::new(snapbox::cmd::cargo_bin("moon"))
.current_dir(&dir)
.arg("build")
.assert()
.success();

let wasm_file = dir.join("target/wasm-gc/release/build/main/main.wasm");

let out = snapbox::cmd::Command::new(snapbox::cmd::cargo_bin("moonrun"))
.arg(&wasm_file)
.stdin("中文😄👍hello1242")
.assert()
.success()
.get_output()
.stdout
.to_owned();
let s = std::str::from_utf8(&out).unwrap().to_string();
assert!(s.trim() == "中文😄👍hello1242".as_bytes().len().to_string());

let out = snapbox::cmd::Command::new(snapbox::cmd::cargo_bin("moonrun"))
.arg(&wasm_file)
.stdin("")
.assert()
.success()
.get_output()
.stdout
.to_owned();
let s = std::str::from_utf8(&out).unwrap().to_string();
assert!(s.trim() == "0");
}
2 changes: 2 additions & 0 deletions crates/moonrun/tests/test_cases/test_read_bytes.in/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
target/
.mooncakes/
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# username/hello
63 changes: 63 additions & 0 deletions crates/moonrun/tests/test_cases/test_read_bytes.in/main/main.mbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// moon: The build system and package manager for MoonBit.
// Copyright (C) 2024 International Digital Economy Academy
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// For inquiries, you can contact us via e-mail at jichuruanjian@idea.edu.cn.

///|
pub(all) type XByteArrayCreateHandle

///|
pub(all) type XByteArrayReadHandle

///|
pub(all) type XExternByteArray

fn read_bytes_from_stdin_ffi() -> XExternByteArray = "__moonbit_io_unstable" "read_bytes_from_stdin"
fn read_bytes_from_stdin() -> Bytes {
let content = read_bytes_from_stdin_ffi()
byte_array_from_extern(content)
}

pub fn byte_array_from_extern(e : XExternByteArray) -> Bytes {
let buf = Array::new()
let handle = begin_read_byte_array(e)
while true {
let ch = byte_array_read_byte(handle)
if ch == -1 {
break
} else {
buf.push(ch.to_byte())
}
}
finish_read_byte_array(handle)
Bytes::from_array(buf)
}

///|
fn begin_read_byte_array(s : XExternByteArray) -> XByteArrayReadHandle = "__moonbit_fs_unstable" "begin_read_byte_array"

///|
fn byte_array_read_byte(handle : XByteArrayReadHandle) -> Int = "__moonbit_fs_unstable" "byte_array_read_byte"

///|
fn finish_read_byte_array(handle : XByteArrayReadHandle) = "__moonbit_fs_unstable" "finish_read_byte_array"


fn main {
let bytes = read_bytes_from_stdin()
println(bytes.iter().count())
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"is-main": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "username/hello",
"version": "0.1.0",
"readme": "README.md",
"repository": "",
"license": "Apache-2.0",
"keywords": [],
"description": ""
}

0 comments on commit e759b75

Please sign in to comment.