PkmnLib/src/ScriptResolving/WASM/InterfaceMethods/CoreMethods.cpp

87 lines
4.4 KiB
C++

#include "CoreMethods.hpp"
#include <cstring>
#include "../WebAssemblyScriptResolver.hpp"
#include "WasmHelperFile.hpp"
#include "wasm.h"
wasm_func_t* CreateErrorFunc(wasm_store_t* store, WebAssemblyScriptResolver* resolver) {
// This is probably the most horrific function we need to expose. As we do not want the scripting library to be
// responsible for string formatting for size reasons, we pass a lot of data separately. This includes several
// strings.
return WasmHelpers::CreateFunc<void, i32, i32, i32, i32, i32, i32>(
store, resolver, [](void* env, const wasm_val_vec_t* args, wasm_val_vec_t*) -> wasm_trap_t* {
auto msg = args->data[0].of.i32;
auto msg_len = args->data[1].of.i32;
auto file = args->data[2].of.i32;
auto file_len = args->data[3].of.i32;
auto line = args->data[4].of.i32;
auto position = args->data[5].of.i32;
auto* resolver = (WebAssemblyScriptResolver*)env;
auto* msgPointer = wasm_memory_data(resolver->GetMemory()) + msg;
auto* filePointer = wasm_memory_data(resolver->GetMemory()) + file;
auto msgString = std::string_view(msgPointer, msg_len);
auto fileString = std::string_view(filePointer, file_len);
std::stringstream fullMessage;
fullMessage << "WASM Error with message: " << msgString << std::endl
<< "in file: " << fileString << ". Line: " << line << ":" << position;
wasm_message_t message;
wasm_name_new_from_string_nt(&message, fullMessage.str().c_str());
wasm_trap_t* trap = wasm_trap_new(resolver->GetStore(), &message);
wasm_name_delete(&message);
return trap;
});
}
wasm_func_t* CreatePrintFunc(wasm_store_t* store, WebAssemblyScriptResolver* resolver) {
return WasmHelpers::CreateFunc<void, i32, i32>(
store, resolver, [](void* env, const wasm_val_vec_t* args, wasm_val_vec_t*) -> wasm_trap_t* {
auto msg = args->data[0].of.i32;
auto msg_len = args->data[1].of.i32;
auto resolver = (WebAssemblyScriptResolver*)env;
auto* msgPointer = wasm_memory_data(resolver->GetMemory()) + msg;
auto msgString = std::string_view(msgPointer, msg_len);
std::cout << msgString << std::endl;
return nullptr;
});
;
}
wasm_func_t* ConstString_GetHash(wasm_store_t* store, WebAssemblyScriptResolver* resolver) {
return WasmHelpers::CreateFunc2<u32, const ArbUt::StringView*>(
store, resolver,
std::function<u32(WebAssemblyScriptResolver*, const ArbUt::StringView*)>(
[](WebAssemblyScriptResolver*, const ArbUt::StringView* sv) -> u32 { return sv->GetHash(); }));
}
wasm_func_t* ConstString_GetStr(wasm_store_t* store, WebAssemblyScriptResolver* resolver) {
return WasmHelpers::CreateFunc<i32, const ArbUt::StringView*>(
store, resolver, [](void* env, const wasm_val_vec_t* args, wasm_val_vec_t* returns) -> wasm_trap_t* {
auto resolver = (WebAssemblyScriptResolver*)env;
auto& constString = *(ArbUt::StringView*)args->data[0].of.i64;
// To allow webassembly to access the C String, we need to allocate it inside it's memory.
// Length + 1 to make room for the '\0'
auto stringPointer = resolver->AllocateMemory(constString.Length() + 1, std::alignment_of<const char>());
// After we have the pointer to the memory allocated for the string, copy the string with specified length
// to it, then suffix it with the null byte to end it.
strncpy(reinterpret_cast<char*>(stringPointer.first), constString.c_str(), constString.Length());
stringPointer.first[constString.Length()] = '\0';
returns->data[0] = WASM_I32_VAL(stringPointer.second);
return nullptr;
});
}
void WebAssemblyCoreMethods::Register(wasm_store_t* store, ArbUt::Dictionary<std::string, wasm_func_t*>& externs,
WebAssemblyScriptResolver* resolver) {
externs.Insert("_error", CreateErrorFunc(store, resolver));
externs.Insert("_print", CreatePrintFunc(store, resolver));
externs.Insert("arbutils_const_string_get_hash", ConstString_GetHash(store, resolver));
externs.Insert("arbutils_const_string_get_str", ConstString_GetStr(store, resolver));
}