diff --git a/.gitignore b/.gitignore index a9cd6a44589..4da3a8bbda2 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ # Generated by Cargo # will have compiled files and executables **/target/ +**/**/target/ # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html diff --git a/passing-data/example-rust-wasm-crate/strings-wasm-is-cool/src/lib.rs b/passing-data/example-rust-wasm-crate/strings-wasm-is-cool/src/lib.rs index 206e0947cc9..e78fa4ce59e 100644 --- a/passing-data/example-rust-wasm-crate/strings-wasm-is-cool/src/lib.rs +++ b/passing-data/example-rust-wasm-crate/strings-wasm-is-cool/src/lib.rs @@ -1,4 +1,3 @@ - // Import the standard string library use std::str; @@ -13,7 +12,8 @@ static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; // Create a static mutable byte buffer. // We will use for passing memory between our host and wasm. -// NOTE: global `static mut` means we will have "unsafe" code +// NOTE: global `static mut` means we have to access it with unsafe +// and manually ensure that only one mutable reference exists to it at a time // but for passing memory between a host and wasm should be fine. const WASM_MEMORY_BUFFER_SIZE: usize = 1024; static mut WASM_MEMORY_BUFFER: [u8; WASM_MEMORY_BUFFER_SIZE] = [0; WASM_MEMORY_BUFFER_SIZE]; @@ -22,35 +22,24 @@ static mut WASM_MEMORY_BUFFER: [u8; WASM_MEMORY_BUFFER_SIZE] = [0; WASM_MEMORY_B // in wasm memory #[wasm_bindgen] pub fn get_wasm_memory_buffer_pointer() -> *const u8 { - let pointer: *const u8; - unsafe { - pointer = WASM_MEMORY_BUFFER.as_ptr(); - } - - return pointer; + unsafe { WASM_MEMORY_BUFFER.as_ptr() } } // Function to get the string from the buffer and add the text to it #[wasm_bindgen] pub fn add_wasm_is_cool(passed_string_length: usize) -> usize { - // Let's get the passed string from our passed bytes - let mut passed_string = ""; - unsafe { - passed_string = str::from_utf8(&WASM_MEMORY_BUFFER[0..passed_string_length]).unwrap(); - } + let passed_string = + unsafe { str::from_utf8(&WASM_MEMORY_BUFFER[..passed_string_length]).unwrap() }; // Let's add our phrase to the passed string let new_string = format!("{} Wasm is cool!", passed_string); // Let's write the new string back to our buffer - let new_string_bytes = new_string.as_bytes(); - for i in 0..new_string_bytes.len() { - unsafe { - WASM_MEMORY_BUFFER[i] = new_string_bytes[i]; - } + unsafe { + WASM_MEMORY_BUFFER[..new_string.len()].copy_from_slice(new_string.as_bytes()); } - // Return the length of the new string for the host to fetch it out of memory - return new_string.len(); + // Return the length of the new string for the host to fetch it out of memory + new_string.len() } diff --git a/passing-data/src/main.rs b/passing-data/src/main.rs index d69413b03ac..b44a766da45 100644 --- a/passing-data/src/main.rs +++ b/passing-data/src/main.rs @@ -1,39 +1,40 @@ // Import the Filesystem so we can read our .wasm file -use std::io::prelude::*; use std::fs::File; +use std::io::prelude::*; // Import the wasmer runtime so we can use it -use wasmer_runtime::{ - instantiate, - imports, - error, - Func -}; +use wasmer_runtime::{error, imports, instantiate, Func}; // Import some helpers for handling Pointers into Wasm Memory -use wasmer_runtime_core::memory::ptr::{WasmPtr, Array}; +use wasmer_runtime_core::memory::ptr::{Array, WasmPtr}; + +// Create an absolute path to the Wasm file +const WASM_FILE_LOCATION: &str = concat!( + env!("CARGO_MANIFEST_DIR"), + "/example-rust-wasm-crate/strings-wasm-is-cool/pkg/strings_wasm_is_cool_bg.wasm" +); // Our entry point to our application fn main() -> error::Result<()> { - // Let's read in our .wasm file as bytes // Let's open the file. // The file path may be different depending where you run `cargo run`, and where you place the file. - let mut file = File::open("./example-rust-wasm-crate/strings-wasm-is-cool/pkg/strings_wasm_is_cool_bg.wasm").expect("Incorrect file path to wasm module."); + let mut file = File::open(WASM_FILE_LOCATION).expect("Incorrect file path to wasm module."); // Let's read the file into a Vec let mut wasm_vec = Vec::new(); - file.read_to_end(&mut wasm_vec).expect("Error reading the wasm file"); + file.read_to_end(&mut wasm_vec) + .expect("Error reading the wasm file"); - // Let's get our byte slice ( [u8] ) from our wasm_vec. + // Let's get our byte slice ( &[u8] ) from our wasm_vec. let wasm_bytes = wasm_vec.as_slice(); // Now that we have the wasm file as bytes, let's run it with the wasmer runtime // Our import object, that allows exposing functions to our wasm module. // We're not importing anything, so make an empty import object. - let import_object = imports!{}; + let import_object = imports! {}; // Let's create an instance of wasm module running in the wasmer-runtime let instance = instantiate(wasm_bytes, &import_object)?; @@ -42,34 +43,43 @@ fn main() -> error::Result<()> { let wasm_instance_context = instance.context(); let wasm_instance_memory = wasm_instance_context.memory(0); - // Let's get the pointer to the buffer defined by the wasm module in the wasm memory - let get_wasm_memory_buffer_pointer: Func<(), i32> = - instance + // Let's get the pointer to the buffer defined by the wasm module in the wasm memory. + // We use the type system and the power of generics to get a function we can call + // directly with a type signature of no arguments and returning 1 u32 + let get_wasm_memory_buffer_pointer: Func<(), u32> = instance .func("get_wasm_memory_buffer_pointer") .expect("get_wasm_memory_buffer_pointer"); - let response = get_wasm_memory_buffer_pointer.call().unwrap() as u32; + let response = get_wasm_memory_buffer_pointer.call().unwrap(); + // Let's create a WasmPtr which is a thin wrapper around u32 to ergonomically access memory let wasm_buffer_pointer: WasmPtr = WasmPtr::new(response); // Let's write a string to the wasm memory let original_string = "Did you know"; println!("The original string is: {}", original_string); - let memory_writer = wasm_buffer_pointer.deref(wasm_instance_memory, 0, original_string.len() as u32).unwrap(); + // We deref our WasmPtr to get a &[Cell] + let memory_writer = wasm_buffer_pointer + .deref(wasm_instance_memory, 0, original_string.len() as u32) + .unwrap(); for (i, b) in original_string.bytes().enumerate() { memory_writer[i].set(b); } // Let's call the exported function that concatenates a phrase to our string. - let add_wasm_is_cool: Func = instance.func("add_wasm_is_cool").expect("Wasm is cool export"); + let add_wasm_is_cool: Func = instance + .func("add_wasm_is_cool") + .expect("Wasm is cool export"); let new_string_length = add_wasm_is_cool.call(original_string.len() as u32).unwrap(); - // Get our pointer again, since memory may have shifted around - let new_pointer_response = get_wasm_memory_buffer_pointer.call().unwrap() as u32; + // Get our pointer again, since memory may have shifted around + let new_pointer_response = get_wasm_memory_buffer_pointer.call().unwrap(); let new_wasm_buffer_pointer: WasmPtr = WasmPtr::new(new_pointer_response); // Read the string from that new pointer. - let new_string = new_wasm_buffer_pointer.get_utf8_string(wasm_instance_memory, new_string_length as u32).unwrap(); + let new_string = new_wasm_buffer_pointer + .get_utf8_string(wasm_instance_memory, new_string_length) + .unwrap(); println!("The new string is: {}", new_string); - + // Asserting that the returned value from the function is our expected value. assert_eq!(new_string, "Did you know Wasm is cool!");