diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index f7a00cb..5dbaffe 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -12,7 +12,8 @@ extism-pdk = "1" once_cell = "1.16" anyhow = { workspace = true } quickjs-wasm-rs = "3" -chrono = { version = "0.4", default_features = false, features = ["clock"]} +chrono = { version = "0.4", default_features = false, features = ["clock"] } +base64 = "0.22.1" [lib] crate_type = ["cdylib"] diff --git a/crates/core/src/globals.rs b/crates/core/src/globals.rs index 494d3e8..4a7d8e4 100644 --- a/crates/core/src/globals.rs +++ b/crates/core/src/globals.rs @@ -155,11 +155,44 @@ fn build_host_object(context: &JSContextRef) -> anyhow::Result { Ok(JSValue::Bool(true)) }, )?; + + let to_base64 = context.wrap_callback( + |_ctx: &JSContextRef, _this: JSValueRef, args: &[JSValueRef]| { + let data = args.first().unwrap(); + if !data.is_array_buffer() { + return Err(anyhow!("expected array buffer")); + } + + use base64::prelude::*; + let bytes = data.as_bytes()?; + let as_string = BASE64_STANDARD.encode(bytes); + + Ok(JSValue::String(as_string)) + }, + )?; + + let from_base64 = context.wrap_callback( + |_ctx: &JSContextRef, _this: JSValueRef, args: &[JSValueRef]| { + let data = args.first().unwrap(); + if !data.is_str() { + return Err(anyhow!("expected string")); + } + + use base64::prelude::*; + let string = data.as_str()?; + let bytes = BASE64_STANDARD.decode(string)?; + + Ok(JSValue::ArrayBuffer(bytes)) + }, + )?; + let host_object = context.object_value()?; host_object.set_property("inputBytes", host_input_bytes)?; host_object.set_property("inputString", host_input_string)?; host_object.set_property("outputBytes", host_output_bytes)?; host_object.set_property("outputString", host_output_string)?; + host_object.set_property("arrayBufferToBase64", to_base64)?; + host_object.set_property("base64ToArrayBuffer", from_base64)?; Ok(host_object) } diff --git a/crates/core/src/prelude/src/host.ts b/crates/core/src/prelude/src/host.ts index 027413e..064af6f 100644 --- a/crates/core/src/prelude/src/host.ts +++ b/crates/core/src/prelude/src/host.ts @@ -12,12 +12,14 @@ declare global { outputBytes(output: ArrayBufferLike): boolean; outputString(output: string): boolean; getFunctions(): import("extism:host").user; + arrayBufferToBase64(input: ArrayBuffer): string; + base64ToArrayBuffer(input: string): ArrayBuffer; } var Host: Host; } -Host.getFunctions = function () { +Host.getFunctions = function() { function createInvoke(id: number, results: number) { if (results === 0) { return Host.invokeFunc0.bind(null, id); @@ -32,4 +34,4 @@ Host.getFunctions = function () { }, {}); }; -export {}; +export { };