Skip to content

Commit

Permalink
make rust callback more ergonomic
Browse files Browse the repository at this point in the history
  • Loading branch information
JanProvaznik committed Jul 30, 2024
1 parent 0f84b48 commit 7ff8260
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 44 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ obj/
.vs
Playground/
/MSBuildWasmLocal.sln
/examples/go
39 changes: 32 additions & 7 deletions examples/rust_concat2files/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ use std::ffi::CString;
use std::os::raw::c_char;

#[repr(C)] #[allow(dead_code)]
enum MessageImportance {
pub enum MessageImportance {
High,
Normal,
Low
}

#[repr(C)]
#[repr(C)] #[allow(dead_code)]
pub enum TaskResult {
Success,
Failure
Expand All @@ -22,11 +22,40 @@ extern "C" {
fn LogMessage(messageImportance: MessageImportance, message: *const c_char, message_length: usize);
}

#[allow(dead_code)]
fn log_message(messageImportance: MessageImportance, message: &str) {
let c_message = CString::new(message).unwrap();
unsafe {
LogMessage(messageImportance, c_message.as_ptr(), c_message.to_bytes().len());
}
}
#[allow(dead_code)]
fn log_error(message: &str) {
let c_message = CString::new(message).unwrap();
unsafe {
LogError(c_message.as_ptr(), c_message.to_bytes().len());
}
}
#[allow(dead_code)]
fn log_warning(message: &str) {
let c_message = CString::new(message).unwrap();
unsafe {
LogWarning(c_message.as_ptr(), c_message.to_bytes().len());
}
}

#[link(wasm_import_module = "msbuild-taskinfo")]
extern "C" {
fn TaskInfo(task_info_json: *const c_char, task_info_length: usize); // this is a ptr to a json string
}

fn task_info(task_info_json: &str) {
let c_message = CString::new(task_info_json).unwrap();
unsafe {
TaskInfo(c_message.as_ptr(), c_message.to_bytes().len());
}
}



#[no_mangle] #[allow(non_snake_case)]
Expand Down Expand Up @@ -68,9 +97,5 @@ pub fn Execute() -> TaskResult
#[no_mangle] #[allow(non_snake_case)]
pub fn GetTaskInfo()
{
let c_string = CString::new(r#"{"Properties":{"InputFile1":{"type":"ITaskItem","required":true,"output":false},"InputFile2":{"type":"ITaskItem","required":true,"output":false},"OutputFile":{"type":"ITaskItem","required":false,"output":true}}}"#).unwrap();
unsafe
{
TaskInfo(c_string.as_ptr(), c_string.to_bytes().len());
}
task_info(r#"{"Properties":{"InputFile1":{"type":"ITaskItem","required":true,"output":false},"InputFile2":{"type":"ITaskItem","required":true,"output":false},"OutputFile":{"type":"ITaskItem","required":false,"output":true}}}"#);
}
49 changes: 35 additions & 14 deletions examples/rust_mergedirectories/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@ use std::io;
use serde_json::Value;
use serde::Deserialize;

#[repr(C)]
#[allow(dead_code)]
enum MessageImportance {
#[repr(C)] #[allow(dead_code)]
pub enum MessageImportance {
High,
Normal,
Low,
}

#[repr(C)]
#[repr(C)] #[allow(dead_code)]
pub enum TaskResult {
Success,
Failure,
Expand All @@ -28,11 +27,40 @@ extern "C" {
fn LogMessage(messageImportance: MessageImportance, message: *const c_char, message_length: usize);
}

#[allow(dead_code)]
fn log_message(messageImportance: MessageImportance, message: &str) {
let c_message = CString::new(message).unwrap();
unsafe {
LogMessage(messageImportance, c_message.as_ptr(), c_message.to_bytes().len());
}
}
#[allow(dead_code)]
fn log_error(message: &str) {
let c_message = CString::new(message).unwrap();
unsafe {
LogError(c_message.as_ptr(), c_message.to_bytes().len());
}
}
#[allow(dead_code)]
fn log_warning(message: &str) {
let c_message = CString::new(message).unwrap();
unsafe {
LogWarning(c_message.as_ptr(), c_message.to_bytes().len());
}
}

#[link(wasm_import_module = "msbuild-taskinfo")]
extern "C" {
fn TaskInfo(task_info_json: *const c_char, task_info_length: usize); // this is a ptr to a json string
}

fn task_info(task_info_json: &str) {
let c_message = CString::new(task_info_json).unwrap();
unsafe {
TaskInfo(c_message.as_ptr(), c_message.to_bytes().len());
}
}

#[derive(serde::Deserialize)]
struct Properties {
Dirs: Vec<Value>,
Expand Down Expand Up @@ -61,25 +89,18 @@ pub fn Execute() -> TaskResult {
.collect();
merge_directories(&wasm_paths, "output_dir").unwrap();

let out_json_str = CString::new(r#"{"MergedDir":{"ItemSpec":"output_dir","WasmPath":"output_dir"}}"#).unwrap();
unsafe {
for path in wasm_paths {
let message = CString::new(format!("WasmPath: {}", path)).unwrap();
LogWarning(message.as_ptr(), message.to_bytes().len());
}
log_warning(&format!("WasmPath: {}", path));
}

println!("{}", out_json_str.to_str().unwrap());
println!("{}", r#"{"MergedDir":{"ItemSpec":"output_dir","WasmPath":"output_dir"}}"#);
return TaskResult::Success;
}

#[no_mangle]
#[allow(non_snake_case)]
pub fn GetTaskInfo() {
let c_string = CString::new(r#"{"Properties":{"Dirs":{"type":"ITaskItem[]","required":true,"output":false},"MergedDir":{"type":"ITaskItem","required":false,"output":true},"MergedName":{"type":"string","required":false,"output":false}}}"#).unwrap();
unsafe {
TaskInfo(c_string.as_ptr(), c_string.to_bytes().len());
}
task_info(r#"{"Properties":{"Dirs":{"type":"ITaskItem[]","required":true,"output":false},"MergedDir":{"type":"ITaskItem","required":false,"output":true},"MergedName":{"type":"string","required":false,"output":false}}}"#);
}

fn merge_directories(paths: &[String], output_name: &str) -> io::Result<()> {
Expand Down
63 changes: 40 additions & 23 deletions examples/rust_template/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ use std::ffi::CString;
use std::os::raw::c_char;

#[repr(C)] #[allow(dead_code)]
enum MessageImportance {
pub enum MessageImportance {
High,
Normal,
Low
}

#[repr(C)]
#[repr(C)] #[allow(dead_code)]
pub enum TaskResult {
Success,
Failure
Expand All @@ -22,11 +22,39 @@ extern "C" {
fn LogMessage(messageImportance: MessageImportance, message: *const c_char, message_length: usize);
}

#[allow(dead_code)]
fn log_message(messageImportance: MessageImportance, message: &str) {
let c_message = CString::new(message).unwrap();
unsafe {
LogMessage(messageImportance, c_message.as_ptr(), c_message.to_bytes().len());
}
}
#[allow(dead_code)]
fn log_error(message: &str) {
let c_message = CString::new(message).unwrap();
unsafe {
LogError(c_message.as_ptr(), c_message.to_bytes().len());
}
}
#[allow(dead_code)]
fn log_warning(message: &str) {
let c_message = CString::new(message).unwrap();
unsafe {
LogWarning(c_message.as_ptr(), c_message.to_bytes().len());
}
}

#[link(wasm_import_module = "msbuild-taskinfo")]
extern "C" {
fn TaskInfo(task_info_json: *const c_char, task_info_length: usize); // this is a ptr to a json string
}

fn task_info(task_info_json: &str) {
let c_message = CString::new(task_info_json).unwrap();
unsafe {
TaskInfo(c_message.as_ptr(), c_message.to_bytes().len());
}
}

#[no_mangle] #[allow(non_snake_case)]
pub fn Execute() -> TaskResult
Expand All @@ -35,33 +63,22 @@ pub fn Execute() -> TaskResult
let mut input = String::new();
std::io::stdin().read_line(&mut input).unwrap();

// let errorMessage = CString::new("Error message from Wasm").unwrap(); // we don't want the template task failing

// log_error("Error message from Wasm"); // we don't want the template task failing
// show what the template task got on input
let warning_message= CString::new(input).unwrap();
let message1= CString::new("High priority message from Wasm").unwrap();
let message2 = CString::new("Normal priority message from Wasm").unwrap();
let message3 = CString::new("Low priority message from Wasm").unwrap();
let out_json_str = CString::new(r#"{"TestOutputProperty":"This is the output property value from WASM task"}"#).unwrap();
unsafe
{
// LogError(errorMessage.as_ptr(), errorMessage.to_bytes().len());
LogWarning(warning_message.as_ptr(), warning_message.to_bytes().len());
LogMessage(MessageImportance::High, message1.as_ptr(), message1.to_bytes().len());
LogMessage(MessageImportance::Normal, message2.as_ptr(), message2.to_bytes().len());
LogMessage(MessageImportance::Low, message3.as_ptr(), message3.to_bytes().len());
// task output properties in stdout
println!("{}", out_json_str.to_str().unwrap());
}
log_warning(&input);
log_message(MessageImportance::High, "High priority message from Wasm");
log_message(MessageImportance::Normal, "Normal priority message from Wasm");
log_message(MessageImportance::Low, "Low priority message from Wasm");


println!("{}",r#"{"TestOutputProperty":"This is the output property value from WASM task"}"#);

return TaskResult::Success;
}

#[no_mangle] #[allow(non_snake_case)]
pub fn GetTaskInfo()
{
let c_string = CString::new(r#"{"Properties":{"TestNormalProperty":{"type":"string","required":false,"output":false},"TestOutputProperty":{"type":"string","required":false,"output":true},"TestRequiredProperty":{"type":"string","required":true,"output":false},"TestBoolProperty":{"type":"bool","required":false,"output":false}}}"#).unwrap();
unsafe
{
TaskInfo(c_string.as_ptr(), c_string.to_bytes().len());
}
task_info(r#"{"Properties":{"TestNormalProperty":{"type":"string","required":false,"output":false},"TestOutputProperty":{"type":"string","required":false,"output":true},"TestRequiredProperty":{"type":"string","required":true,"output":false},"TestBoolProperty":{"type":"bool","required":false,"output":false}}}"#);
}

0 comments on commit 7ff8260

Please sign in to comment.