Skip to content

Commit

Permalink
Display error messages in the wasm demo (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
ppputtyo authored Oct 27, 2023
1 parent b93cb59 commit 9d377fb
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 29 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ jobs:
-o ./wasm/uroborosql-fmt.js
-s ALLOW_MEMORY_GROWTH=1
-s STACK_SIZE=5MB
-s EXPORTED_FUNCTIONS=['_format_sql','_free_format_string']
-s EXPORTED_FUNCTIONS=['_format_sql','_get_result_address','_get_error_msg_address']
-s EXPORTED_RUNTIME_METHODS=ccall
- name: Upload artifact
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export EMCC_CFLAGS="-O3
-o ./wasm/uroborosql-fmt.js
-s ALLOW_MEMORY_GROWTH=1
-s STACK_SIZE=5MB
-s EXPORTED_FUNCTIONS=['_format_sql','_free_format_string']
-s EXPORTED_FUNCTIONS=['_format_sql','_get_result_address','_get_error_msg_address']
-s EXPORTED_RUNTIME_METHODS=ccall"
# 全体のビルドを実行
cargo build --package uroborosql-fmt-wasm --target wasm32-unknown-emscripten --release
1 change: 1 addition & 0 deletions crates/uroborosql-fmt-wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ repository.workspace = true
crate-type = ["cdylib"]

[dependencies]
once_cell = "1.18.0"
uroborosql-fmt = { workspace = true }
58 changes: 37 additions & 21 deletions crates/uroborosql-fmt-wasm/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,34 @@
use std::ffi::{c_char, CStr, CString};
use once_cell::sync::Lazy;
use std::{
ffi::{c_char, CStr, CString},
sync::Mutex,
};

static RESULT: Lazy<Mutex<CString>> = Lazy::new(|| Mutex::new(CString::new("").unwrap()));
static ERROR_MSG: Lazy<Mutex<CString>> = Lazy::new(|| Mutex::new(CString::new("").unwrap()));

use uroborosql_fmt::{config::Config, format_sql_with_config};

/// Returns the address of the result string.
///
/// # Safety
///
/// This is unsafe because it returns a raw pointer.
#[no_mangle]
pub unsafe extern "C" fn get_result_address() -> *const c_char {
RESULT.lock().unwrap().as_c_str().as_ptr()
}

/// Returns the address of the error message string.
///
/// # Safety
///
/// This is unsafe because it returns a raw pointer.
#[no_mangle]
pub unsafe extern "C" fn get_error_msg_address() -> *const c_char {
ERROR_MSG.lock().unwrap().as_c_str().as_ptr()
}

/// Formats SQL code given as char pointer `src` by WASM (JavaScript).
///
/// # Safety
Expand All @@ -10,31 +37,20 @@ use uroborosql_fmt::{config::Config, format_sql_with_config};
/// [`CStr::from_ptr`](https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html#method.from_ptr).
#[export_name = "format_sql"]
#[no_mangle]
pub unsafe extern "C" fn format_sql_for_wasm(
src: *mut c_char,
config_json_str: *mut c_char,
) -> *mut c_char {
pub unsafe extern "C" fn format_sql_for_wasm(src: *const c_char, config_json_str: *const c_char) {
// Clear previous format result
*RESULT.lock().unwrap() = CString::new("").unwrap();
*ERROR_MSG.lock().unwrap() = CString::new("").unwrap();

let src = CStr::from_ptr(src).to_str().unwrap().to_owned();

let config_json_str = CStr::from_ptr(config_json_str).to_str().unwrap();
let config = Config::from_json_str(config_json_str).unwrap();

// TODO: error handling
let result = format_sql_with_config(&src, config).unwrap();

CString::new(result).unwrap().into_raw()
}
let result = format_sql_with_config(&src, config);

/// Free the string `s` allocated by Rust.
///
/// # Safety
///
/// This is unsafe because it uses the unsafe function
/// [`CString::from_war()`](https://doc.rust-lang.org/std/ffi/struct.CString.html#method.from_raw).
#[no_mangle]
pub unsafe extern "C" fn free_format_string(s: *mut c_char) {
if s.is_null() {
return;
match result {
Ok(result) => *RESULT.lock().unwrap() = CString::new(result).unwrap(),
Err(err) => *ERROR_MSG.lock().unwrap() = CString::new(err.to_string()).unwrap(),
}
let _ = CString::from_raw(s);
}
2 changes: 2 additions & 0 deletions wasm/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ <h2>Japanese<h2>
</div>
</div>

<div id="error_msg" style="color: red;"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.43.0/min/vs/loader.min.js"></script>
<script src="main.js"></script>
<script async src="uroborosql-fmt.js"></script>
Expand Down
2 changes: 2 additions & 0 deletions wasm/ja.html
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ <h2>English<h2>
</div>
</div>

<div id="error_msg" style="color: red;"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.43.0/min/vs/loader.min.js"></script>
<script src="main.js"></script>
<script async src="uroborosql-fmt.js"></script>
Expand Down
15 changes: 9 additions & 6 deletions wasm/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,9 @@ function initialize() {
// タイマースタート
const startTime = performance.now();

const ptr = ccall(
ccall(
"format_sql",
"number",
null,
["string", "string"],
[target, config_str]
);
Expand All @@ -233,13 +233,16 @@ function initialize() {
// 何ミリ秒かかったかを表示する
console.log("format complete: " + (endTime - startTime) + "ms");

// Module.UTF8ToString() でポインタを js の string に変換
const res = UTF8ToString(ptr);
// Rust側で確保したメモリのポインタを取得
const result_ptr = ccall("get_result_address", "number", [], []);
const error_ptr = ccall("get_error_msg_address", "number", [], []);

// Rust 側で確保したフォーマット文字列の所有権を返す
ccall("free_format_string", null, ["number"], [ptr]);
// Module.UTF8ToString() でポインタを js の string に変換
const res = UTF8ToString(result_ptr);
const err = UTF8ToString(error_ptr);

dst_editor.setValue(res);
document.getElementById("error_msg").innerText = err;

src_editor.updateOptions({ tabSize: tab_size });
dst_editor.updateOptions({ tabSize: tab_size });
Expand Down

0 comments on commit 9d377fb

Please sign in to comment.