Last active
April 18, 2019 02:43
-
-
Save shritesh/1f6f4b6843e72df3aaa880a1ff786b93 to your computer and use it in GitHub Desktop.
LeftPad in JS With Zig and WASM
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require('fs'); | |
const source = fs.readFileSync("./left_pad.wasm"); | |
const sourceArray = new Uint8Array(source); | |
WebAssembly.instantiate(sourceArray, {}).then(result => { | |
const leftPad = left_pad.bind(result.instance.exports); | |
const paddedStr = leftPad("hello zig", 20, '*'); | |
console.log(paddedStr); | |
}); | |
// This is intentionally verbose | |
const left_pad = function(str, len, char) { | |
// convert str to Uint8Array | |
const textEncoder = new TextEncoder(); | |
const strArray = textEncoder.encode(str); | |
// get memory from wasm | |
// assume first memory locations are for return values, the rest are for params | |
const return_len = (32 / 8) + (32 / 8); // u32, u32 | |
const str_len = strArray.length; | |
const ptr = this._wasm_alloc(return_len + str_len); | |
if (ptr === 0) { | |
throw "Cannot allocate memory"; | |
} | |
// copy strArray to wasm | |
var memoryu8 = new Uint8Array(this.memory.buffer); | |
for (let i = 0; i < str_len; ++i) { | |
memoryu8[ptr + return_len + i] = strArray[i]; | |
} | |
// call function | |
const succeed = this.left_pad_extern(ptr + return_len, str_len, len, char.codePointAt(0), ptr, ptr + (32/ 8)); | |
// read result into Uint32Array() | |
const return_slice = new Uint32Array(this.memory.buffer.slice(ptr, ptr + return_len)); | |
const return_val_ptr = return_slice[0]; | |
const return_val_len = return_slice[1]; | |
// dealloc function params | |
this._wasm_dealloc(ptr, return_len + str_len); | |
// throw if function returned error | |
if (!succeed) { | |
throw "WASM Call returned error" | |
} | |
// get the result | |
const result = new Uint8Array(this.memory.buffer.slice(return_val_ptr, return_val_ptr + return_val_len)); | |
// dealloc result | |
this._wasm_dealloc(return_val_ptr, return_val_len); | |
// decode result | |
const textDecoder = new TextDecoder(); | |
// return result | |
return textDecoder.decode(result); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const std = @import("std"); | |
const Allocator = std.mem.Allocator; | |
/// Returns a `len`-length u8 slice with `str` padded by `char` in the front | |
/// Caller must free | |
pub fn left_pad(allocator: *Allocator, str: []const u8, len: usize, char: u8) ![]u8 { | |
if (len < str.len) { | |
return error.InvalidLength; | |
} | |
const buf = try allocator.alloc(u8, len); | |
errdefer allocator.free(buf); | |
const pad = len - str.len; | |
var i: usize = 0; | |
while (i < len) : (i += 1) { | |
buf[i] = if (i < pad) char else str[i - pad]; | |
} | |
return buf; | |
} | |
export fn left_pad_extern( | |
input_ptr: [*]const u8, | |
input_len: usize, | |
len: usize, | |
char: u8, | |
output_ptr: *[*]u8, | |
output_size: *usize, | |
) bool { | |
const input = input_ptr[0..input_len]; | |
var output = left_pad(std.heap.wasm_allocator, input, len, char) catch |err| return false; | |
output_ptr.* = output.ptr; | |
output_size.* = output.len; | |
return true; | |
} | |
export fn _wasm_alloc(len: usize) u32 { | |
var buf = std.heap.wasm_allocator.alloc(u8, len) catch |err| return 0; | |
return @ptrToInt(buf.ptr); | |
} | |
export fn _wasm_dealloc(ptr: [*]const u8, len: usize) void { | |
std.heap.wasm_allocator.free(ptr[0..len]); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment