mirror of
https://github.com/extism/extism.git
synced 2026-01-09 22:07:57 -05:00
refactor!: Use extism:host/env namespace for extism functions and extism:host/user for user-defined host functions (#511)
See #504 Removes CI for the in-repo SDKs, we can remove the actual code closer to the 1.0 release. --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: zshipko <zshipko@users.noreply.github.com>
This commit is contained in:
8
.github/workflows/browser-ci.yml
vendored
8
.github/workflows/browser-ci.yml
vendored
@@ -1,12 +1,4 @@
|
|||||||
on:
|
on:
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- .github/actions/extism/**
|
|
||||||
- .github/workflows/ci-node.yml
|
|
||||||
- manifest/**
|
|
||||||
- runtime/**
|
|
||||||
- libextism/**
|
|
||||||
- browser/**
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
name: Browser CI
|
name: Browser CI
|
||||||
|
|||||||
8
.github/workflows/ci-cpp.yml
vendored
8
.github/workflows/ci-cpp.yml
vendored
@@ -1,12 +1,4 @@
|
|||||||
on:
|
on:
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- .github/actions/extism/**
|
|
||||||
- .github/workflows/ci-cpp.yml
|
|
||||||
- manifest/**
|
|
||||||
- runtime/**
|
|
||||||
- libextism/**
|
|
||||||
- cpp/**
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
name: C++ CI
|
name: C++ CI
|
||||||
|
|||||||
8
.github/workflows/ci-d.yml
vendored
8
.github/workflows/ci-d.yml
vendored
@@ -1,12 +1,4 @@
|
|||||||
on:
|
on:
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- .github/actions/extism/**
|
|
||||||
- .github/workflows/ci-d.yml
|
|
||||||
- manifest/**
|
|
||||||
- runtime/**
|
|
||||||
- libextism/**
|
|
||||||
- d/**
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
name: D CI
|
name: D CI
|
||||||
|
|||||||
8
.github/workflows/ci-dotnet.yml
vendored
8
.github/workflows/ci-dotnet.yml
vendored
@@ -1,12 +1,4 @@
|
|||||||
on:
|
on:
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- .github/actions/extism/**
|
|
||||||
- .github/workflows/ci-dotnet.yml
|
|
||||||
- manifest/**
|
|
||||||
- runtime/**
|
|
||||||
- libextism/**
|
|
||||||
- dotnet/**
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
name: .NET CI
|
name: .NET CI
|
||||||
|
|||||||
8
.github/workflows/ci-elixir.yml
vendored
8
.github/workflows/ci-elixir.yml
vendored
@@ -1,12 +1,4 @@
|
|||||||
on:
|
on:
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- .github/actions/extism/**
|
|
||||||
- .github/workflows/ci-elixir.yml
|
|
||||||
- manifest/**
|
|
||||||
- runtime/**
|
|
||||||
- rust/**
|
|
||||||
- elixir/**
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
name: Elixir CI
|
name: Elixir CI
|
||||||
|
|||||||
12
.github/workflows/ci-go.yml
vendored
12
.github/workflows/ci-go.yml
vendored
@@ -1,16 +1,4 @@
|
|||||||
on:
|
on:
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- .github/actions/extism/**
|
|
||||||
- .github/workflows/ci-go.yml
|
|
||||||
- manifest/**
|
|
||||||
- runtime/**
|
|
||||||
- libextism/**
|
|
||||||
- extism.go
|
|
||||||
- extism_test.go
|
|
||||||
- go.mod
|
|
||||||
- libextism.pc
|
|
||||||
- go/**
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
name: Go CI
|
name: Go CI
|
||||||
|
|||||||
8
.github/workflows/ci-haskell.yml
vendored
8
.github/workflows/ci-haskell.yml
vendored
@@ -1,12 +1,4 @@
|
|||||||
on:
|
on:
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- .github/actions/extism/**
|
|
||||||
- .github/workflows/ci-haskell.yml
|
|
||||||
- manifest/**
|
|
||||||
- runtime/**
|
|
||||||
- libextism/**
|
|
||||||
- haskell/**
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
name: Haskell CI
|
name: Haskell CI
|
||||||
|
|||||||
8
.github/workflows/ci-java.yml
vendored
8
.github/workflows/ci-java.yml
vendored
@@ -1,12 +1,4 @@
|
|||||||
on:
|
on:
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- .github/actions/extism/**
|
|
||||||
- .github/workflows/ci-java.yml
|
|
||||||
- manifest/**
|
|
||||||
- runtime/**
|
|
||||||
- libextism/**
|
|
||||||
- java/**
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
name: Java CI
|
name: Java CI
|
||||||
|
|||||||
8
.github/workflows/ci-node.yml
vendored
8
.github/workflows/ci-node.yml
vendored
@@ -1,12 +1,4 @@
|
|||||||
on:
|
on:
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- .github/actions/extism/**
|
|
||||||
- .github/workflows/ci-node.yml
|
|
||||||
- manifest/**
|
|
||||||
- runtime/**
|
|
||||||
- libextism/**
|
|
||||||
- node/**
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
name: Node CI
|
name: Node CI
|
||||||
|
|||||||
10
.github/workflows/ci-ocaml.yml
vendored
10
.github/workflows/ci-ocaml.yml
vendored
@@ -1,14 +1,4 @@
|
|||||||
on:
|
on:
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- .github/actions/extism/**
|
|
||||||
- .github/workflows/ci-ocaml.yml
|
|
||||||
- manifest/**
|
|
||||||
- runtime/**
|
|
||||||
- libextism/**
|
|
||||||
- ocaml/**
|
|
||||||
- dune-project
|
|
||||||
- extism.opam
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
name: OCaml CI
|
name: OCaml CI
|
||||||
|
|||||||
10
.github/workflows/ci-php.yml
vendored
10
.github/workflows/ci-php.yml
vendored
@@ -1,14 +1,4 @@
|
|||||||
on:
|
on:
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- .github/actions/extism/**
|
|
||||||
- .github/workflows/ci-php.yml
|
|
||||||
- manifest/**
|
|
||||||
- runtime/**
|
|
||||||
- libextism/**
|
|
||||||
- php/**
|
|
||||||
- composer.json
|
|
||||||
- composer.lock
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
name: PHP CI
|
name: PHP CI
|
||||||
|
|||||||
8
.github/workflows/ci-python.yml
vendored
8
.github/workflows/ci-python.yml
vendored
@@ -1,12 +1,4 @@
|
|||||||
on:
|
on:
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- .github/actions/extism/**
|
|
||||||
- .github/workflows/ci-python.yml
|
|
||||||
- manifest/**
|
|
||||||
- runtime/**
|
|
||||||
- libextism/**
|
|
||||||
- python/**
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
name: Python CI
|
name: Python CI
|
||||||
|
|||||||
8
.github/workflows/ci-ruby.yml
vendored
8
.github/workflows/ci-ruby.yml
vendored
@@ -1,12 +1,4 @@
|
|||||||
on:
|
on:
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- .github/actions/extism/**
|
|
||||||
- .github/workflows/ci-ruby.yml
|
|
||||||
- manifest/**
|
|
||||||
- runtime/**
|
|
||||||
- libextism/**
|
|
||||||
- ruby/**
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
name: Ruby CI
|
name: Ruby CI
|
||||||
|
|||||||
8
.github/workflows/ci-zig.yml
vendored
8
.github/workflows/ci-zig.yml
vendored
@@ -1,12 +1,4 @@
|
|||||||
on:
|
on:
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- .github/actions/extism/**
|
|
||||||
- .github/workflows/ci-zig.yml
|
|
||||||
- manifest/**
|
|
||||||
- runtime/**
|
|
||||||
- libextism/**
|
|
||||||
- zig/**
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
name: Zig CI
|
name: Zig CI
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -44,3 +44,5 @@ java/*.log
|
|||||||
java/.idea
|
java/.idea
|
||||||
java/.DS_Store
|
java/.DS_Store
|
||||||
extism-maturin/src/extism.h
|
extism-maturin/src/extism.h
|
||||||
|
runtime/*.log
|
||||||
|
libextism/example
|
||||||
|
|||||||
Binary file not shown.
11
c/Makefile
11
c/Makefile
@@ -1,11 +1,2 @@
|
|||||||
.PHONY: build
|
|
||||||
build:
|
build:
|
||||||
$(CC) -g -o main main.c -lextism -L .
|
clang -g -o main main.c -lextism -L .
|
||||||
|
|
||||||
.PHONY: static
|
|
||||||
static:
|
|
||||||
$(CC) -g -o main main.c -l:libextism.a -lm -L .
|
|
||||||
|
|
||||||
.PHONY: clean
|
|
||||||
clean:
|
|
||||||
rm -f main
|
|
||||||
@@ -111,7 +111,7 @@ impl<'a, T: prost::Message> ToBytes<'a> for Protobuf<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "protobuf")]
|
#[cfg(feature = "protobuf")]
|
||||||
impl<'a, T: Default + prost::Message> FromBytesOwned for Protobuf<T> {
|
impl<T: Default + prost::Message> FromBytesOwned for Protobuf<T> {
|
||||||
fn from_bytes_owned(data: &[u8]) -> Result<Self, Error> {
|
fn from_bytes_owned(data: &[u8]) -> Result<Self, Error> {
|
||||||
Ok(Protobuf(T::decode(data)?))
|
Ok(Protobuf(T::decode(data)?))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ impl<'a, T: FromBytesOwned> FromBytes<'a> for T {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FromBytesOwned for Box<[u8]> {
|
impl FromBytesOwned for Box<[u8]> {
|
||||||
fn from_bytes_owned(data: &[u8]) -> Result<Self, Error> {
|
fn from_bytes_owned(data: &[u8]) -> Result<Self, Error> {
|
||||||
Ok(data.to_vec().into_boxed_slice())
|
Ok(data.to_vec().into_boxed_slice())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
# Elixir Host SDK
|
# Elixir Host SDK
|
||||||
|
|
||||||
This contains the `0.x` version of the SDK. Development of this library has moved to [this repo](https://github.com/extism/elixir-sdk#readme).
|
This contains the `0.x` version of the SDK. Development of this library has moved to [this repo](https://github.com/extism/elixir-sdk#readme).
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
%{
|
%{
|
||||||
"earmark_parser": {:hex, :earmark_parser, "1.4.37", "2ad73550e27c8946648b06905a57e4d454e4d7229c2dafa72a0348c99d8be5f7", [:mix], [], "hexpm", "6b19783f2802f039806f375610faa22da130b8edc21209d0bff47918bb48360e"},
|
"earmark_parser": {:hex, :earmark_parser, "1.4.37", "2ad73550e27c8946648b06905a57e4d454e4d7229c2dafa72a0348c99d8be5f7", [:mix], [], "hexpm", "6b19783f2802f039806f375610faa22da130b8edc21209d0bff47918bb48360e"},
|
||||||
"ex_doc": {:hex, :ex_doc, "0.30.9", "d691453495c47434c0f2052b08dd91cc32bc4e1a218f86884563448ee2502dd2", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "d7aaaf21e95dc5cddabf89063327e96867d00013963eadf2c6ad135506a8bc10"},
|
"ex_doc": {:hex, :ex_doc, "0.30.7", "dc7247091aec738ab781f71cbebfc07979d1040c98c7ee67dbde99b7829b743d", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "868ff1c7a44c462741853840d1e7ef19a07906e7467cb8da070c158ea6a42a51"},
|
||||||
"jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"},
|
"jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"},
|
||||||
"json": {:hex, :json, "1.4.1", "8648f04a9439765ad449bc56a3ff7d8b11dd44ff08ffcdefc4329f7c93843dfa", [:mix], [], "hexpm", "9abf218dbe4ea4fcb875e087d5f904ef263d012ee5ed21d46e9dbca63f053d16"},
|
"json": {:hex, :json, "1.4.1", "8648f04a9439765ad449bc56a3ff7d8b11dd44ff08ffcdefc4329f7c93843dfa", [:mix], [], "hexpm", "9abf218dbe4ea4fcb875e087d5f904ef263d012ee5ed21d46e9dbca63f053d16"},
|
||||||
"makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"},
|
"makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"},
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
# Java Host SDK
|
# Java Host SDK
|
||||||
|
|
||||||
This contains the `0.x` version of the SDK. Development of this library has moved to [this repo](https://github.com/extism/java-sdk#readme).
|
This contains the `0.x` version of the SDK. Development of this library has moved to [this repo](https://github.com/extism/java-sdk#readme).
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -4,7 +4,6 @@
|
|||||||
//! - An allocator for managing that memory
|
//! - An allocator for managing that memory
|
||||||
//! - Input/output handling
|
//! - Input/output handling
|
||||||
//! - Error message handling
|
//! - Error message handling
|
||||||
//! - Backward compatible `extism_*` functions
|
|
||||||
//!
|
//!
|
||||||
//! ## Allocator
|
//! ## Allocator
|
||||||
//!
|
//!
|
||||||
@@ -17,14 +16,14 @@
|
|||||||
//! ## Input/Output
|
//! ## Input/Output
|
||||||
//!
|
//!
|
||||||
//! Input and output are just allocated blocks of memory that are marked as either input or output using
|
//! Input and output are just allocated blocks of memory that are marked as either input or output using
|
||||||
//! the `extism_input_set` or `extism_output_set` functions. The MemoryRoot field `input_offset` contains
|
//! the `input_set` or `output_set` functions. The MemoryRoot field `input_offset` contains
|
||||||
//! the offset in memory to the input data and `input_length` contains the size of the input data. `output_offset`
|
//! the offset in memory to the input data and `input_length` contains the size of the input data. `output_offset`
|
||||||
//! and `output_length` are used for the output data.
|
//! and `output_length` are used for the output data.
|
||||||
//!
|
//!
|
||||||
//! ## Error handling
|
//! ## Error handling
|
||||||
//!
|
//!
|
||||||
//! The `error` field is used to track the current error message. If it is set to `0` then there is no error.
|
//! The `error` field is used to track the current error message. If it is set to `0` then there is no error.
|
||||||
//! The length of the error message can be retreived using `extism_length`.
|
//! The length of the error message can be retreived using `length`.
|
||||||
//!
|
//!
|
||||||
//! ## Memory offsets
|
//! ## Memory offsets
|
||||||
//! An offset of `0` is similar to a `NULL` pointer in C - it implies an allocation failure or memory error
|
//! An offset of `0` is similar to a `NULL` pointer in C - it implies an allocation failure or memory error
|
||||||
@@ -140,10 +139,8 @@ impl MemoryRoot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that at least one page is allocated to store the `MemoryRoot` data
|
// Ensure that at least one page is allocated to store the `MemoryRoot` data
|
||||||
if core::arch::wasm32::memory_size(0) == 0 {
|
if core::arch::wasm32::memory_size(0) == 0 && core::arch::wasm32::memory_grow(0, 1) == usize::MAX {
|
||||||
if core::arch::wasm32::memory_grow(0, 1) == usize::MAX {
|
core::arch::wasm32::unreachable()
|
||||||
core::arch::wasm32::unreachable()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
root.input_offset = 0;
|
root.input_offset = 0;
|
||||||
@@ -331,7 +328,7 @@ impl MemoryBlock {
|
|||||||
|
|
||||||
/// Allocate a block of memory and return the offset
|
/// Allocate a block of memory and return the offset
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn extism_alloc(n: Length) -> Pointer {
|
pub unsafe fn alloc(n: Length) -> Pointer {
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -345,7 +342,7 @@ pub unsafe fn extism_alloc(n: Length) -> Pointer {
|
|||||||
|
|
||||||
/// Free allocated memory
|
/// Free allocated memory
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn extism_free(p: Pointer) {
|
pub unsafe fn free(p: Pointer) {
|
||||||
if p == 0 {
|
if p == 0 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -364,7 +361,7 @@ pub unsafe fn extism_free(p: Pointer) {
|
|||||||
|
|
||||||
/// Get the length of an allocated memory block
|
/// Get the length of an allocated memory block
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn extism_length(p: Pointer) -> Length {
|
pub unsafe fn length(p: Pointer) -> Length {
|
||||||
if p == 0 {
|
if p == 0 {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -377,7 +374,7 @@ pub unsafe fn extism_length(p: Pointer) -> Length {
|
|||||||
|
|
||||||
/// Load a byte from Extism-managed memory
|
/// Load a byte from Extism-managed memory
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn extism_load_u8(p: Pointer) -> u8 {
|
pub unsafe fn load_u8(p: Pointer) -> u8 {
|
||||||
#[cfg(feature = "bounds-checking")]
|
#[cfg(feature = "bounds-checking")]
|
||||||
if !MemoryRoot::pointer_in_bounds_fast(p) {
|
if !MemoryRoot::pointer_in_bounds_fast(p) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -387,7 +384,7 @@ pub unsafe fn extism_load_u8(p: Pointer) -> u8 {
|
|||||||
|
|
||||||
/// Load a u64 from Extism-managed memory
|
/// Load a u64 from Extism-managed memory
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn extism_load_u64(p: Pointer) -> u64 {
|
pub unsafe fn load_u64(p: Pointer) -> u64 {
|
||||||
#[cfg(feature = "bounds-checking")]
|
#[cfg(feature = "bounds-checking")]
|
||||||
if !MemoryRoot::pointer_in_bounds_fast(p + core::mem::size_of::<u64>() as u64 - 1) {
|
if !MemoryRoot::pointer_in_bounds_fast(p + core::mem::size_of::<u64>() as u64 - 1) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -397,7 +394,7 @@ pub unsafe fn extism_load_u64(p: Pointer) -> u64 {
|
|||||||
|
|
||||||
/// Load a byte from the input data
|
/// Load a byte from the input data
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn extism_input_load_u8(p: Pointer) -> u8 {
|
pub unsafe fn input_load_u8(p: Pointer) -> u8 {
|
||||||
let root = MemoryRoot::new();
|
let root = MemoryRoot::new();
|
||||||
#[cfg(feature = "bounds-checking")]
|
#[cfg(feature = "bounds-checking")]
|
||||||
if p >= root.input_length {
|
if p >= root.input_length {
|
||||||
@@ -408,7 +405,7 @@ pub unsafe fn extism_input_load_u8(p: Pointer) -> u8 {
|
|||||||
|
|
||||||
/// Load a u64 from the input data
|
/// Load a u64 from the input data
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn extism_input_load_u64(p: Pointer) -> u64 {
|
pub unsafe fn input_load_u64(p: Pointer) -> u64 {
|
||||||
let root = MemoryRoot::new();
|
let root = MemoryRoot::new();
|
||||||
#[cfg(feature = "bounds-checking")]
|
#[cfg(feature = "bounds-checking")]
|
||||||
if p + core::mem::size_of::<u64>() as Pointer > root.input_length {
|
if p + core::mem::size_of::<u64>() as Pointer > root.input_length {
|
||||||
@@ -419,7 +416,7 @@ pub unsafe fn extism_input_load_u64(p: Pointer) -> u64 {
|
|||||||
|
|
||||||
/// Write a byte in Extism-managed memory
|
/// Write a byte in Extism-managed memory
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn extism_store_u8(p: Pointer, x: u8) {
|
pub unsafe fn store_u8(p: Pointer, x: u8) {
|
||||||
#[cfg(feature = "bounds-checking")]
|
#[cfg(feature = "bounds-checking")]
|
||||||
if !MemoryRoot::pointer_in_bounds_fast(p) {
|
if !MemoryRoot::pointer_in_bounds_fast(p) {
|
||||||
return;
|
return;
|
||||||
@@ -429,7 +426,7 @@ pub unsafe fn extism_store_u8(p: Pointer, x: u8) {
|
|||||||
|
|
||||||
/// Write a u64 in Extism-managed memory
|
/// Write a u64 in Extism-managed memory
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn extism_store_u64(p: Pointer, x: u64) {
|
pub unsafe fn store_u64(p: Pointer, x: u64) {
|
||||||
#[cfg(feature = "bounds-checking")]
|
#[cfg(feature = "bounds-checking")]
|
||||||
if !MemoryRoot::pointer_in_bounds_fast(p + core::mem::size_of::<u64>() as u64 - 1) {
|
if !MemoryRoot::pointer_in_bounds_fast(p + core::mem::size_of::<u64>() as u64 - 1) {
|
||||||
return;
|
return;
|
||||||
@@ -439,7 +436,7 @@ pub unsafe fn extism_store_u64(p: Pointer, x: u64) {
|
|||||||
|
|
||||||
/// Set the range of the input data in memory
|
/// Set the range of the input data in memory
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn extism_input_set(p: Pointer, len: Length) {
|
pub unsafe fn input_set(p: Pointer, len: Length) {
|
||||||
let root = MemoryRoot::new();
|
let root = MemoryRoot::new();
|
||||||
#[cfg(feature = "bounds-checking")]
|
#[cfg(feature = "bounds-checking")]
|
||||||
{
|
{
|
||||||
@@ -453,7 +450,7 @@ pub unsafe fn extism_input_set(p: Pointer, len: Length) {
|
|||||||
|
|
||||||
/// Set the range of the output data in memory
|
/// Set the range of the output data in memory
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn extism_output_set(p: Pointer, len: Length) {
|
pub unsafe fn output_set(p: Pointer, len: Length) {
|
||||||
let root = MemoryRoot::new();
|
let root = MemoryRoot::new();
|
||||||
#[cfg(feature = "bounds-checking")]
|
#[cfg(feature = "bounds-checking")]
|
||||||
{
|
{
|
||||||
@@ -467,37 +464,37 @@ pub unsafe fn extism_output_set(p: Pointer, len: Length) {
|
|||||||
|
|
||||||
/// Get the input length
|
/// Get the input length
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn extism_input_length() -> Length {
|
pub fn input_length() -> Length {
|
||||||
unsafe { MemoryRoot::new().input_length }
|
unsafe { MemoryRoot::new().input_length }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the input offset in Exitsm-managed memory
|
/// Get the input offset in Exitsm-managed memory
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn extism_input_offset() -> Length {
|
pub fn input_offset() -> Length {
|
||||||
unsafe { MemoryRoot::new().input_offset }
|
unsafe { MemoryRoot::new().input_offset }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the output length
|
/// Get the output length
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn extism_output_length() -> Length {
|
pub fn output_length() -> Length {
|
||||||
unsafe { MemoryRoot::new().output_length }
|
unsafe { MemoryRoot::new().output_length }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the output offset in Extism-managed memory
|
/// Get the output offset in Extism-managed memory
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn extism_output_offset() -> Length {
|
pub unsafe fn output_offset() -> Length {
|
||||||
MemoryRoot::new().output_offset
|
MemoryRoot::new().output_offset
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reset the allocator
|
/// Reset the allocator
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn extism_reset() {
|
pub unsafe fn reset() {
|
||||||
MemoryRoot::new().reset()
|
MemoryRoot::new().reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the error message offset
|
/// Set the error message offset
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn extism_error_set(ptr: Pointer) {
|
pub unsafe fn error_set(ptr: Pointer) {
|
||||||
let root = MemoryRoot::new();
|
let root = MemoryRoot::new();
|
||||||
|
|
||||||
// Allow ERROR to be set to 0
|
// Allow ERROR to be set to 0
|
||||||
@@ -515,12 +512,12 @@ pub unsafe fn extism_error_set(ptr: Pointer) {
|
|||||||
|
|
||||||
/// Get the error message offset, if it's `0` then no error has been set
|
/// Get the error message offset, if it's `0` then no error has been set
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn extism_error_get() -> Pointer {
|
pub unsafe fn error_get() -> Pointer {
|
||||||
MemoryRoot::new().error.load(Ordering::SeqCst)
|
MemoryRoot::new().error.load(Ordering::SeqCst)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the position of the allocator, this can be used as an indication of how many bytes are currently in-use
|
/// Get the position of the allocator, this can be used as an indication of how many bytes are currently in-use
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn extism_memory_bytes() -> Length {
|
pub unsafe fn memory_bytes() -> Length {
|
||||||
MemoryRoot::new().position.load(Ordering::Acquire)
|
MemoryRoot::new().length.load(Ordering::Acquire)
|
||||||
}
|
}
|
||||||
|
|||||||
11
libextism/Makefile
Normal file
11
libextism/Makefile
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
.PHONY: build
|
||||||
|
build:
|
||||||
|
$(CC) -g -o example example.c -lextism
|
||||||
|
|
||||||
|
.PHONY: static
|
||||||
|
static:
|
||||||
|
$(CC) -g -o example example.c -l:libextism.a -lm
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
rm -f main
|
||||||
@@ -24,7 +24,7 @@ void hello_world(ExtismCurrentPlugin *plugin, const ExtismVal *inputs,
|
|||||||
outputs[0].v.i64 = inputs[0].v.i64;
|
outputs[0].v.i64 = inputs[0].v.i64;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_data(void *x) { puts("FREE"); }
|
void free_data(void *x) { puts("Freeing userdata"); }
|
||||||
|
|
||||||
uint8_t *read_file(const char *filename, size_t *len) {
|
uint8_t *read_file(const char *filename, size_t *len) {
|
||||||
|
|
||||||
@@ -79,9 +79,7 @@ int main(int argc, char *argv[]) {
|
|||||||
const uint8_t *output = extism_plugin_output_data(plugin);
|
const uint8_t *output = extism_plugin_output_data(plugin);
|
||||||
write(STDOUT_FILENO, output, out_len);
|
write(STDOUT_FILENO, output, out_len);
|
||||||
write(STDOUT_FILENO, "\n", 1);
|
write(STDOUT_FILENO, "\n", 1);
|
||||||
puts("Freeing plugin");
|
|
||||||
extism_plugin_free(plugin);
|
extism_plugin_free(plugin);
|
||||||
puts("Freeing function");
|
|
||||||
extism_function_free(f);
|
extism_function_free(f);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -252,7 +252,7 @@ impl Manifest {
|
|||||||
/// Set MemoryOptions::memory_max
|
/// Set MemoryOptions::memory_max
|
||||||
pub fn with_memory_max(mut self, max: u32) -> Self {
|
pub fn with_memory_max(mut self, max: u32) -> Self {
|
||||||
self.memory.max_pages = Some(max);
|
self.memory.max_pages = Some(max);
|
||||||
return self;
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a hostname to `allowed_hosts`
|
/// Add a hostname to `allowed_hosts`
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -1,4 +1,3 @@
|
|||||||
# Python Host SDK
|
# Python Host SDK
|
||||||
|
|
||||||
This contains the `0.x` version of the SDK. Development of this library has moved to [this repo](https://github.com/extism/python-sdk#readme).
|
This contains the `0.x` version of the SDK. Development of this library has moved to [this repo](https://github.com/extism/python-sdk#readme).
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use criterion::{criterion_group, criterion_main, Criterion};
|
use criterion::{criterion_group, criterion_main, Criterion};
|
||||||
use extism::*;
|
use extism::*;
|
||||||
|
use extism_convert::Json;
|
||||||
|
|
||||||
const COUNT_VOWELS: &[u8] = include_bytes!("../../wasm/code.wasm");
|
const COUNT_VOWELS: &[u8] = include_bytes!("../../wasm/code.wasm");
|
||||||
const REFLECT: &[u8] = include_bytes!("../../wasm/reflect.wasm");
|
const REFLECT: &[u8] = include_bytes!("../../wasm/reflect.wasm");
|
||||||
@@ -8,7 +9,6 @@ host_fn!(hello_world (a: String) -> String { Ok(a) });
|
|||||||
|
|
||||||
pub fn basic(c: &mut Criterion) {
|
pub fn basic(c: &mut Criterion) {
|
||||||
let mut g = c.benchmark_group("basic");
|
let mut g = c.benchmark_group("basic");
|
||||||
g.sample_size(300);
|
|
||||||
g.measurement_time(std::time::Duration::from_secs(6));
|
g.measurement_time(std::time::Duration::from_secs(6));
|
||||||
g.bench_function("basic", |b| {
|
g.bench_function("basic", |b| {
|
||||||
let data = "a".repeat(4096);
|
let data = "a".repeat(4096);
|
||||||
@@ -23,7 +23,6 @@ pub fn create_plugin(c: &mut Criterion) {
|
|||||||
let mut g = c.benchmark_group("create");
|
let mut g = c.benchmark_group("create");
|
||||||
g.noise_threshold(1.0);
|
g.noise_threshold(1.0);
|
||||||
g.significance_level(0.2);
|
g.significance_level(0.2);
|
||||||
g.sample_size(300);
|
|
||||||
g.bench_function("create_plugin", |b| {
|
g.bench_function("create_plugin", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let _plugin = PluginBuilder::new_with_module(COUNT_VOWELS)
|
let _plugin = PluginBuilder::new_with_module(COUNT_VOWELS)
|
||||||
@@ -34,6 +33,10 @@ pub fn create_plugin(c: &mut Criterion) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Deserialize, PartialEq)]
|
||||||
|
struct Count {
|
||||||
|
count: u32,
|
||||||
|
}
|
||||||
pub fn count_vowels(c: &mut Criterion) {
|
pub fn count_vowels(c: &mut Criterion) {
|
||||||
let mut g = c.benchmark_group("count_vowels");
|
let mut g = c.benchmark_group("count_vowels");
|
||||||
g.sample_size(500);
|
g.sample_size(500);
|
||||||
@@ -45,8 +48,11 @@ pub fn count_vowels(c: &mut Criterion) {
|
|||||||
g.bench_function("count_vowels(4096)", |b| {
|
g.bench_function("count_vowels(4096)", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
"{\"count\": 4096}",
|
Count { count: 4096 },
|
||||||
plugin.call::<_, &str>("count_vowels", &data).unwrap()
|
plugin
|
||||||
|
.call::<_, Json<Count>>("count_vowels", &data)
|
||||||
|
.unwrap()
|
||||||
|
.0
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ impl CurrentPlugin {
|
|||||||
pub fn memory_bytes(&mut self, handle: MemoryHandle) -> Result<&mut [u8], Error> {
|
pub fn memory_bytes(&mut self, handle: MemoryHandle) -> Result<&mut [u8], Error> {
|
||||||
let (linker, mut store) = self.linker_and_store();
|
let (linker, mut store) = self.linker_and_store();
|
||||||
let mem = linker
|
let mem = linker
|
||||||
.get(&mut store, "env", "memory")
|
.get(&mut store, EXTISM_ENV_MODULE, "memory")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into_memory()
|
.into_memory()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -145,7 +145,7 @@ impl CurrentPlugin {
|
|||||||
}
|
}
|
||||||
let (linker, mut store) = self.linker_and_store();
|
let (linker, mut store) = self.linker_and_store();
|
||||||
let output = &mut [Val::I64(0)];
|
let output = &mut [Val::I64(0)];
|
||||||
if let Some(f) = linker.get(&mut store, "env", "extism_alloc") {
|
if let Some(f) = linker.get(&mut store, EXTISM_ENV_MODULE, "alloc") {
|
||||||
f.into_func()
|
f.into_func()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.call(&mut store, &[Val::I64(n as i64)], output)?;
|
.call(&mut store, &[Val::I64(n as i64)], output)?;
|
||||||
@@ -167,7 +167,7 @@ impl CurrentPlugin {
|
|||||||
pub fn memory_free(&mut self, handle: MemoryHandle) -> Result<(), Error> {
|
pub fn memory_free(&mut self, handle: MemoryHandle) -> Result<(), Error> {
|
||||||
let (linker, mut store) = self.linker_and_store();
|
let (linker, mut store) = self.linker_and_store();
|
||||||
linker
|
linker
|
||||||
.get(&mut store, "env", "extism_free")
|
.get(&mut store, EXTISM_ENV_MODULE, "free")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into_func()
|
.into_func()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -179,7 +179,7 @@ impl CurrentPlugin {
|
|||||||
let (linker, mut store) = self.linker_and_store();
|
let (linker, mut store) = self.linker_and_store();
|
||||||
let output = &mut [Val::I64(0)];
|
let output = &mut [Val::I64(0)];
|
||||||
linker
|
linker
|
||||||
.get(&mut store, "env", "extism_length")
|
.get(&mut store, EXTISM_ENV_MODULE, "length")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into_func()
|
.into_func()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -269,7 +269,9 @@ impl CurrentPlugin {
|
|||||||
/// Get extism memory
|
/// Get extism memory
|
||||||
pub(crate) fn memory(&mut self) -> Option<wasmtime::Memory> {
|
pub(crate) fn memory(&mut self) -> Option<wasmtime::Memory> {
|
||||||
let (linker, mut store) = self.linker_and_store();
|
let (linker, mut store) = self.linker_and_store();
|
||||||
linker.get(&mut store, "env", "memory")?.into_memory()
|
linker
|
||||||
|
.get(&mut store, EXTISM_ENV_MODULE, "memory")?
|
||||||
|
.into_memory()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a `MemoryHandle` from a `Val` reference - this can be used to convert a host function's
|
/// Get a `MemoryHandle` from a `Val` reference - this can be used to convert a host function's
|
||||||
@@ -296,7 +298,7 @@ impl CurrentPlugin {
|
|||||||
pub fn clear_error(&mut self) {
|
pub fn clear_error(&mut self) {
|
||||||
trace!("CurrentPlugin::clear_error");
|
trace!("CurrentPlugin::clear_error");
|
||||||
let (linker, mut store) = self.linker_and_store();
|
let (linker, mut store) = self.linker_and_store();
|
||||||
if let Some(f) = linker.get(&mut store, "env", "extism_error_set") {
|
if let Some(f) = linker.get(&mut store, EXTISM_ENV_MODULE, "error_set") {
|
||||||
f.into_func()
|
f.into_func()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.call(&mut store, &[Val::I64(0)], &mut [])
|
.call(&mut store, &[Val::I64(0)], &mut [])
|
||||||
@@ -327,7 +329,7 @@ impl CurrentPlugin {
|
|||||||
debug!("Set error: {:?}", s);
|
debug!("Set error: {:?}", s);
|
||||||
let handle = self.current_plugin_mut().memory_new(s)?;
|
let handle = self.current_plugin_mut().memory_new(s)?;
|
||||||
let (linker, mut store) = self.linker_and_store();
|
let (linker, mut store) = self.linker_and_store();
|
||||||
if let Some(f) = linker.get(&mut store, "env", "extism_error_set") {
|
if let Some(f) = linker.get(&mut store, EXTISM_ENV_MODULE, "error_set") {
|
||||||
f.into_func().unwrap().call(
|
f.into_func().unwrap().call(
|
||||||
&mut store,
|
&mut store,
|
||||||
&[Val::I64(handle.offset() as i64)],
|
&[Val::I64(handle.offset() as i64)],
|
||||||
@@ -335,16 +337,16 @@ impl CurrentPlugin {
|
|||||||
)?;
|
)?;
|
||||||
Ok((handle.offset(), s.len() as u64))
|
Ok((handle.offset(), s.len() as u64))
|
||||||
} else {
|
} else {
|
||||||
anyhow::bail!("extism_error_set not found");
|
anyhow::bail!("extism:host/env::error_set not found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_error_position(&mut self) -> (u64, u64) {
|
pub(crate) fn get_error_position(&mut self) -> (u64, u64) {
|
||||||
let (linker, mut store) = self.linker_and_store();
|
let (linker, mut store) = self.linker_and_store();
|
||||||
let output = &mut [Val::I64(0)];
|
let output = &mut [Val::I64(0)];
|
||||||
if let Some(f) = linker.get(&mut store, "env", "extism_error_get") {
|
if let Some(f) = linker.get(&mut store, EXTISM_ENV_MODULE, "error_get") {
|
||||||
if let Err(e) = f.into_func().unwrap().call(&mut store, &[], output) {
|
if let Err(e) = f.into_func().unwrap().call(&mut store, &[], output) {
|
||||||
error!("unable to call extism_error_get: {:?}", e);
|
error!("unable to call extism:host/env::error_get: {:?}", e);
|
||||||
return (0, 0);
|
return (0, 0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Binary file not shown.
@@ -22,7 +22,7 @@ pub use current_plugin::CurrentPlugin;
|
|||||||
pub use extism_convert::{FromBytes, FromBytesOwned, ToBytes};
|
pub use extism_convert::{FromBytes, FromBytesOwned, ToBytes};
|
||||||
pub use extism_manifest::{Manifest, Wasm};
|
pub use extism_manifest::{Manifest, Wasm};
|
||||||
pub use function::{Function, UserData, Val, ValType};
|
pub use function::{Function, UserData, Val, ValType};
|
||||||
pub use plugin::{CancelHandle, Plugin};
|
pub use plugin::{CancelHandle, Plugin, EXTISM_ENV_MODULE, EXTISM_USER_MODULE};
|
||||||
pub use plugin_builder::PluginBuilder;
|
pub use plugin_builder::PluginBuilder;
|
||||||
|
|
||||||
pub(crate) use internal::{Internal, Wasi};
|
pub(crate) use internal::{Internal, Wasi};
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ fn hex(data: &[u8]) -> String {
|
|||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
fn cache_add_file(hash: &str, data: &[u8]) -> Result<(), Error> {
|
fn cache_add_file(hash: &str, data: &[u8]) -> Result<(), Error> {
|
||||||
let cache_dir = std::env::temp_dir().join("exitsm-cache");
|
let cache_dir = std::env::temp_dir().join("extism-cache");
|
||||||
let _ = std::fs::create_dir(&cache_dir);
|
let _ = std::fs::create_dir(&cache_dir);
|
||||||
let file = cache_dir.join(hash);
|
let file = cache_dir.join(hash);
|
||||||
if file.exists() {
|
if file.exists() {
|
||||||
@@ -27,7 +27,7 @@ fn cache_add_file(hash: &str, data: &[u8]) -> Result<(), Error> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn cache_get_file(hash: &str) -> Result<Option<Vec<u8>>, Error> {
|
fn cache_get_file(hash: &str) -> Result<Option<Vec<u8>>, Error> {
|
||||||
let cache_dir = std::env::temp_dir().join("exitsm-cache");
|
let cache_dir = std::env::temp_dir().join("extism-cache");
|
||||||
let file = cache_dir.join(hash);
|
let file = cache_dir.join(hash);
|
||||||
if file.exists() {
|
if file.exists() {
|
||||||
let r = std::fs::read(file)?;
|
let r = std::fs::read(file)?;
|
||||||
@@ -172,20 +172,20 @@ pub(crate) fn load(
|
|||||||
if let Ok(s) = std::str::from_utf8(data) {
|
if let Ok(s) = std::str::from_utf8(data) {
|
||||||
if let Ok(t) = toml::from_str::<extism_manifest::Manifest>(s) {
|
if let Ok(t) = toml::from_str::<extism_manifest::Manifest>(s) {
|
||||||
let mut m = modules(&t, engine)?;
|
let mut m = modules(&t, engine)?;
|
||||||
m.insert("env".to_string(), extism_module);
|
m.insert(EXTISM_ENV_MODULE.to_string(), extism_module);
|
||||||
return Ok((t, m));
|
return Ok((t, m));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let t = serde_json::from_slice::<extism_manifest::Manifest>(data)?;
|
let t = serde_json::from_slice::<extism_manifest::Manifest>(data)?;
|
||||||
let mut m = modules(&t, engine)?;
|
let mut m = modules(&t, engine)?;
|
||||||
m.insert("env".to_string(), extism_module);
|
m.insert(EXTISM_ENV_MODULE.to_string(), extism_module);
|
||||||
return Ok((t, m));
|
return Ok((t, m));
|
||||||
}
|
}
|
||||||
|
|
||||||
let m = Module::new(engine, data)?;
|
let m = Module::new(engine, data)?;
|
||||||
let mut modules = BTreeMap::new();
|
let mut modules = BTreeMap::new();
|
||||||
modules.insert("env".to_string(), extism_module);
|
modules.insert(EXTISM_ENV_MODULE.to_string(), extism_module);
|
||||||
modules.insert("main".to_string(), m);
|
modules.insert("main".to_string(), m);
|
||||||
Ok((Default::default(), modules))
|
Ok((Default::default(), modules))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ use std::collections::BTreeMap;
|
|||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
|
pub const EXTISM_ENV_MODULE: &str = "extism:host/env";
|
||||||
|
pub const EXTISM_USER_MODULE: &str = "extism:host/user";
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
pub(crate) struct Output {
|
pub(crate) struct Output {
|
||||||
pub(crate) offset: u64,
|
pub(crate) offset: u64,
|
||||||
@@ -105,8 +108,6 @@ impl Internal for Plugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const EXPORT_MODULE_NAME: &str = "env";
|
|
||||||
|
|
||||||
fn profiling_strategy() -> ProfilingStrategy {
|
fn profiling_strategy() -> ProfilingStrategy {
|
||||||
match std::env::var("EXTISM_PROFILE").as_deref() {
|
match std::env::var("EXTISM_PROFILE").as_deref() {
|
||||||
Ok("perf") => ProfilingStrategy::PerfMap,
|
Ok("perf") => ProfilingStrategy::PerfMap,
|
||||||
@@ -198,52 +199,40 @@ impl Plugin {
|
|||||||
(entry.0.as_str(), entry.1)
|
(entry.0.as_str(), entry.1)
|
||||||
});
|
});
|
||||||
|
|
||||||
// Define PDK functions
|
|
||||||
macro_rules! define_funcs {
|
|
||||||
($m:expr, { $($name:ident($($args:expr),*) $(-> $($r:expr),*)?);* $(;)?}) => {
|
|
||||||
match $m {
|
|
||||||
$(
|
|
||||||
concat!("extism_", stringify!($name)) => {
|
|
||||||
let t = FuncType::new([$($args),*], [$($($r),*)?]);
|
|
||||||
linker.func_new(EXPORT_MODULE_NAME, concat!("extism_", stringify!($name)), t, pdk::$name)?;
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
_ => ()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add builtins
|
|
||||||
for (name, module) in modules.iter() {
|
for (name, module) in modules.iter() {
|
||||||
if name != main_name {
|
if name != main_name {
|
||||||
linker.module(&mut store, name, module)?;
|
linker.module(&mut store, name, module)?;
|
||||||
}
|
}
|
||||||
for import in module.imports() {
|
|
||||||
let module_name = import.module();
|
|
||||||
let name = import.name();
|
|
||||||
use wasmtime::ValType::*;
|
|
||||||
|
|
||||||
if module_name == EXPORT_MODULE_NAME {
|
|
||||||
define_funcs!(name, {
|
|
||||||
config_get(I64) -> I64;
|
|
||||||
var_get(I64) -> I64;
|
|
||||||
var_set(I64, I64);
|
|
||||||
http_request(I64, I64) -> I64;
|
|
||||||
http_status_code() -> I32;
|
|
||||||
log_warn(I64);
|
|
||||||
log_info(I64);
|
|
||||||
log_debug(I64);
|
|
||||||
log_error(I64);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut imports: Vec<_> = imports.into_iter().collect();
|
let mut imports: Vec<_> = imports.into_iter().collect();
|
||||||
|
// Define PDK functions
|
||||||
|
macro_rules! add_funcs {
|
||||||
|
($($name:ident($($args:expr),*) $(-> $($r:expr),*)?);* $(;)?) => {
|
||||||
|
$(
|
||||||
|
let t = FuncType::new([$($args),*], [$($($r),*)?]);
|
||||||
|
linker.func_new(EXTISM_ENV_MODULE, stringify!($name), t, pdk::$name)?;
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add builtins
|
||||||
|
use wasmtime::ValType::*;
|
||||||
|
add_funcs!(
|
||||||
|
config_get(I64) -> I64;
|
||||||
|
var_get(I64) -> I64;
|
||||||
|
var_set(I64, I64);
|
||||||
|
http_request(I64, I64) -> I64;
|
||||||
|
http_status_code() -> I32;
|
||||||
|
log_warn(I64);
|
||||||
|
log_info(I64);
|
||||||
|
log_debug(I64);
|
||||||
|
log_error(I64);
|
||||||
|
);
|
||||||
|
|
||||||
for f in &mut imports {
|
for f in &mut imports {
|
||||||
let name = f.name().to_string();
|
let name = f.name().to_string();
|
||||||
let ns = f.namespace().unwrap_or(EXPORT_MODULE_NAME);
|
let ns = f.namespace().unwrap_or(EXTISM_USER_MODULE);
|
||||||
unsafe {
|
unsafe {
|
||||||
linker.func_new(ns, &name, f.ty().clone(), &*(f.f.as_ref() as *const _))?;
|
linker.func_new(ns, &name, f.ty().clone(), &*(f.f.as_ref() as *const _))?;
|
||||||
}
|
}
|
||||||
@@ -392,15 +381,18 @@ impl Plugin {
|
|||||||
let bytes = unsafe { std::slice::from_raw_parts(input, len) };
|
let bytes = unsafe { std::slice::from_raw_parts(input, len) };
|
||||||
trace!("Input size: {}", bytes.len());
|
trace!("Input size: {}", bytes.len());
|
||||||
|
|
||||||
if let Some(f) = self.linker.get(&mut self.store, "env", "extism_reset") {
|
if let Some(f) = self.linker.get(&mut self.store, EXTISM_ENV_MODULE, "reset") {
|
||||||
f.into_func().unwrap().call(&mut self.store, &[], &mut [])?;
|
f.into_func().unwrap().call(&mut self.store, &[], &mut [])?;
|
||||||
} else {
|
} else {
|
||||||
error!("Call to extism_reset failed");
|
error!("Call to extism:host/env::reset failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
let handle = self.current_plugin_mut().memory_new(bytes)?;
|
let handle = self.current_plugin_mut().memory_new(bytes)?;
|
||||||
|
|
||||||
if let Some(f) = self.linker.get(&mut self.store, "env", "extism_input_set") {
|
if let Some(f) = self
|
||||||
|
.linker
|
||||||
|
.get(&mut self.store, EXTISM_ENV_MODULE, "input_set")
|
||||||
|
{
|
||||||
f.into_func().unwrap().call(
|
f.into_func().unwrap().call(
|
||||||
&mut self.store,
|
&mut self.store,
|
||||||
&[Val::I64(handle.offset() as i64), Val::I64(len as i64)],
|
&[Val::I64(handle.offset() as i64), Val::I64(len as i64)],
|
||||||
@@ -508,14 +500,14 @@ impl Plugin {
|
|||||||
let out_len = &mut [Val::I64(0)];
|
let out_len = &mut [Val::I64(0)];
|
||||||
let mut store = &mut self.store;
|
let mut store = &mut self.store;
|
||||||
self.linker
|
self.linker
|
||||||
.get(&mut store, "env", "extism_output_offset")
|
.get(&mut store, EXTISM_ENV_MODULE, "output_offset")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into_func()
|
.into_func()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.call(&mut store, &[], out)
|
.call(&mut store, &[], out)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
self.linker
|
self.linker
|
||||||
.get(&mut store, "env", "extism_output_length")
|
.get(&mut store, EXTISM_ENV_MODULE, "output_length")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into_func()
|
.into_func()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -635,16 +627,7 @@ impl Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
Ok(()) => {
|
Ok(()) => Ok(0),
|
||||||
// If `results` is empty and the return value wasn't a WASI exit code then
|
|
||||||
// the call succeeded
|
|
||||||
if results.is_empty() {
|
|
||||||
return Ok(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return result to caller
|
|
||||||
Ok(0)
|
|
||||||
}
|
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if let Some(coredump) = e.downcast_ref::<wasmtime::WasmCoreDump>() {
|
if let Some(coredump) = e.downcast_ref::<wasmtime::WasmCoreDump>() {
|
||||||
if let Some(file) = self.debug_options.coredump.clone() {
|
if let Some(file) = self.debug_options.coredump.clone() {
|
||||||
@@ -749,13 +732,13 @@ impl Plugin {
|
|||||||
pub(crate) fn clear_error(&mut self) {
|
pub(crate) fn clear_error(&mut self) {
|
||||||
trace!("Clearing error on plugin {}", self.id);
|
trace!("Clearing error on plugin {}", self.id);
|
||||||
let (linker, mut store) = self.linker_and_store();
|
let (linker, mut store) = self.linker_and_store();
|
||||||
if let Some(f) = linker.get(&mut store, "env", "extism_error_set") {
|
if let Some(f) = linker.get(&mut store, EXTISM_ENV_MODULE, "error_set") {
|
||||||
f.into_func()
|
f.into_func()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.call(&mut store, &[Val::I64(0)], &mut [])
|
.call(&mut store, &[Val::I64(0)], &mut [])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
} else {
|
} else {
|
||||||
error!("Plugin::clear_error failed, extism_error_set not found")
|
error!("Plugin::clear_error failed, extism:host/env::error_set not found")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ const KERNEL: &[u8] = include_bytes!("../extism-runtime.wasm");
|
|||||||
fn extism_alloc<T>(mut store: &mut wasmtime::Store<T>, instance: &mut Instance, n: u64) -> u64 {
|
fn extism_alloc<T>(mut store: &mut wasmtime::Store<T>, instance: &mut Instance, n: u64) -> u64 {
|
||||||
let out_alloc = &mut [Val::I64(0)];
|
let out_alloc = &mut [Val::I64(0)];
|
||||||
instance
|
instance
|
||||||
.get_func(&mut store, "extism_alloc")
|
.get_func(&mut store, "alloc")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.call(&mut store, &[Val::I64(n as i64)], out_alloc)
|
.call(&mut store, &[Val::I64(n as i64)], out_alloc)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -15,7 +15,7 @@ fn extism_alloc<T>(mut store: &mut wasmtime::Store<T>, instance: &mut Instance,
|
|||||||
fn extism_length<T>(mut store: &mut wasmtime::Store<T>, instance: &mut Instance, p: u64) -> u64 {
|
fn extism_length<T>(mut store: &mut wasmtime::Store<T>, instance: &mut Instance, p: u64) -> u64 {
|
||||||
let out = &mut [Val::I64(0)];
|
let out = &mut [Val::I64(0)];
|
||||||
instance
|
instance
|
||||||
.get_func(&mut store, "extism_length")
|
.get_func(&mut store, "length")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.call(&mut store, &[Val::I64(p as i64)], out)
|
.call(&mut store, &[Val::I64(p as i64)], out)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -25,7 +25,7 @@ fn extism_length<T>(mut store: &mut wasmtime::Store<T>, instance: &mut Instance,
|
|||||||
fn extism_load_u8<T>(mut store: &mut wasmtime::Store<T>, instance: &mut Instance, p: u64) -> u8 {
|
fn extism_load_u8<T>(mut store: &mut wasmtime::Store<T>, instance: &mut Instance, p: u64) -> u8 {
|
||||||
let out = &mut [Val::I32(0)];
|
let out = &mut [Val::I32(0)];
|
||||||
instance
|
instance
|
||||||
.get_func(&mut store, "extism_load_u8")
|
.get_func(&mut store, "load_u8")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.call(&mut store, &[Val::I64(p as i64)], out)
|
.call(&mut store, &[Val::I64(p as i64)], out)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -35,7 +35,7 @@ fn extism_load_u8<T>(mut store: &mut wasmtime::Store<T>, instance: &mut Instance
|
|||||||
fn extism_load_u64<T>(mut store: &mut wasmtime::Store<T>, instance: &mut Instance, p: u64) -> u64 {
|
fn extism_load_u64<T>(mut store: &mut wasmtime::Store<T>, instance: &mut Instance, p: u64) -> u64 {
|
||||||
let out = &mut [Val::I32(0)];
|
let out = &mut [Val::I32(0)];
|
||||||
instance
|
instance
|
||||||
.get_func(&mut store, "extism_load_u64")
|
.get_func(&mut store, "load_u64")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.call(&mut store, &[Val::I64(p as i64)], out)
|
.call(&mut store, &[Val::I64(p as i64)], out)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -49,7 +49,7 @@ fn extism_input_load_u8<T>(
|
|||||||
) -> u8 {
|
) -> u8 {
|
||||||
let out = &mut [Val::I32(0)];
|
let out = &mut [Val::I32(0)];
|
||||||
instance
|
instance
|
||||||
.get_func(&mut store, "extism_input_load_u8")
|
.get_func(&mut store, "input_load_u8")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.call(&mut store, &[Val::I64(p as i64)], out)
|
.call(&mut store, &[Val::I64(p as i64)], out)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -63,7 +63,7 @@ fn extism_input_load_u64<T>(
|
|||||||
) -> u64 {
|
) -> u64 {
|
||||||
let out = &mut [Val::I32(0)];
|
let out = &mut [Val::I32(0)];
|
||||||
instance
|
instance
|
||||||
.get_func(&mut store, "extism_input_load_u64")
|
.get_func(&mut store, "input_load_u64")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.call(&mut store, &[Val::I64(p as i64)], out)
|
.call(&mut store, &[Val::I64(p as i64)], out)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -72,7 +72,7 @@ fn extism_input_load_u64<T>(
|
|||||||
|
|
||||||
fn extism_store_u8<T>(mut store: &mut wasmtime::Store<T>, instance: &mut Instance, p: u64, x: u8) {
|
fn extism_store_u8<T>(mut store: &mut wasmtime::Store<T>, instance: &mut Instance, p: u64, x: u8) {
|
||||||
instance
|
instance
|
||||||
.get_func(&mut store, "extism_store_u8")
|
.get_func(&mut store, "store_u8")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.call(
|
.call(
|
||||||
&mut store,
|
&mut store,
|
||||||
@@ -89,7 +89,7 @@ fn extism_store_u64<T>(
|
|||||||
x: u64,
|
x: u64,
|
||||||
) {
|
) {
|
||||||
instance
|
instance
|
||||||
.get_func(&mut store, "extism_store_u64")
|
.get_func(&mut store, "store_u64")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.call(
|
.call(
|
||||||
&mut store,
|
&mut store,
|
||||||
@@ -101,7 +101,7 @@ fn extism_store_u64<T>(
|
|||||||
|
|
||||||
fn extism_free<T>(mut store: &mut wasmtime::Store<T>, instance: &mut Instance, p: u64) {
|
fn extism_free<T>(mut store: &mut wasmtime::Store<T>, instance: &mut Instance, p: u64) {
|
||||||
instance
|
instance
|
||||||
.get_func(&mut store, "extism_free")
|
.get_func(&mut store, "free")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.call(&mut store, &[Val::I64(p as i64)], &mut [])
|
.call(&mut store, &[Val::I64(p as i64)], &mut [])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -109,7 +109,7 @@ fn extism_free<T>(mut store: &mut wasmtime::Store<T>, instance: &mut Instance, p
|
|||||||
|
|
||||||
fn extism_error_set<T>(mut store: &mut wasmtime::Store<T>, instance: &mut Instance, p: u64) {
|
fn extism_error_set<T>(mut store: &mut wasmtime::Store<T>, instance: &mut Instance, p: u64) {
|
||||||
instance
|
instance
|
||||||
.get_func(&mut store, "extism_error_set")
|
.get_func(&mut store, "error_set")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.call(&mut store, &[Val::I64(p as i64)], &mut [])
|
.call(&mut store, &[Val::I64(p as i64)], &mut [])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -118,7 +118,7 @@ fn extism_error_set<T>(mut store: &mut wasmtime::Store<T>, instance: &mut Instan
|
|||||||
fn extism_error_get<T>(mut store: &mut wasmtime::Store<T>, instance: &mut Instance) -> u64 {
|
fn extism_error_get<T>(mut store: &mut wasmtime::Store<T>, instance: &mut Instance) -> u64 {
|
||||||
let out = &mut [Val::I64(0)];
|
let out = &mut [Val::I64(0)];
|
||||||
instance
|
instance
|
||||||
.get_func(&mut store, "extism_error_get")
|
.get_func(&mut store, "error_get")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.call(&mut store, &[], out)
|
.call(&mut store, &[], out)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -128,7 +128,7 @@ fn extism_error_get<T>(mut store: &mut wasmtime::Store<T>, instance: &mut Instan
|
|||||||
|
|
||||||
fn extism_reset<T>(mut store: &mut wasmtime::Store<T>, instance: &mut Instance) {
|
fn extism_reset<T>(mut store: &mut wasmtime::Store<T>, instance: &mut Instance) {
|
||||||
instance
|
instance
|
||||||
.get_func(&mut store, "extism_reset")
|
.get_func(&mut store, "reset")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.call(&mut store, &[], &mut [])
|
.call(&mut store, &[], &mut [])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -141,7 +141,7 @@ fn extism_input_set<T>(
|
|||||||
l: u64,
|
l: u64,
|
||||||
) {
|
) {
|
||||||
instance
|
instance
|
||||||
.get_func(&mut store, "extism_input_set")
|
.get_func(&mut store, "input_set")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.call(
|
.call(
|
||||||
&mut store,
|
&mut store,
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ fn it_works() {
|
|||||||
UserData::default(),
|
UserData::default(),
|
||||||
hello_world,
|
hello_world,
|
||||||
)
|
)
|
||||||
.with_namespace("env");
|
.with_namespace(EXTISM_USER_MODULE);
|
||||||
let g = Function::new(
|
let g = Function::new(
|
||||||
"hello_world",
|
"hello_world",
|
||||||
[ValType::I64],
|
[ValType::I64],
|
||||||
@@ -188,7 +188,7 @@ fn test_cancel() {
|
|||||||
std::thread::sleep(std::time::Duration::from_secs(1));
|
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||||
assert!(handle.cancel().is_ok());
|
assert!(handle.cancel().is_ok());
|
||||||
});
|
});
|
||||||
let _output: Result<&[u8], Error> = plugin.call("infinite_loop", "abc123");
|
let _output: Result<&[u8], Error> = plugin.call("loop_forever", "abc123");
|
||||||
let end = std::time::Instant::now();
|
let end = std::time::Instant::now();
|
||||||
let time = end - start;
|
let time = end - start;
|
||||||
println!("Cancelled plugin ran for {:?}", time);
|
println!("Cancelled plugin ran for {:?}", time);
|
||||||
@@ -210,14 +210,15 @@ fn test_timeout() {
|
|||||||
let mut plugin = Plugin::new_with_manifest(&manifest, [f], true).unwrap();
|
let mut plugin = Plugin::new_with_manifest(&manifest, [f], true).unwrap();
|
||||||
|
|
||||||
let start = std::time::Instant::now();
|
let start = std::time::Instant::now();
|
||||||
let output: Result<&[u8], Error> = plugin.call("infinite_loop", "abc123");
|
let output: Result<&[u8], Error> = plugin.call("loop_forever", "abc123");
|
||||||
let end = std::time::Instant::now();
|
let end = std::time::Instant::now();
|
||||||
let time = end - start;
|
let time = end - start;
|
||||||
println!("Timed out plugin ran for {:?}", time);
|
let err = output.unwrap_err().root_cause().to_string();
|
||||||
let s = output.unwrap_err().root_cause().to_string();
|
println!(
|
||||||
println!("{}", s);
|
"Timed out plugin ran for {:?}, with error: {:?}",
|
||||||
assert!(s == "timeout");
|
time, &err
|
||||||
// std::io::stdout().write_all(output).unwrap();
|
);
|
||||||
|
assert!(err == "timeout");
|
||||||
}
|
}
|
||||||
|
|
||||||
typed_plugin!(TestTypedPluginGenerics {
|
typed_plugin!(TestTypedPluginGenerics {
|
||||||
@@ -400,7 +401,7 @@ fn test_extism_coredump() {
|
|||||||
.with_coredump("extism.core")
|
.with_coredump("extism.core")
|
||||||
.build()
|
.build()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let output: Result<&[u8], Error> = plugin.call("infinite_loop", "abc123");
|
let output: Result<&[u8], Error> = plugin.call("loop_forever", "abc123");
|
||||||
assert!(output.is_err());
|
assert!(output.is_err());
|
||||||
assert!(std::path::PathBuf::from("extism.core").exists());
|
assert!(std::path::PathBuf::from("extism.core").exists());
|
||||||
let _ = std::fs::remove_file("extism.core");
|
let _ = std::fs::remove_file("extism.core");
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ if __name__ == '__main__':
|
|||||||
# Check for missing SDK functions
|
# Check for missing SDK functions
|
||||||
sdks = [
|
sdks = [
|
||||||
Lang('cpp', 'hpp'),
|
Lang('cpp', 'hpp'),
|
||||||
Lang('d', 'd'),
|
|
||||||
Lang('go', 'go', path='..'),
|
Lang('go', 'go', path='..'),
|
||||||
Lang('haskell', 'hs'),
|
Lang('haskell', 'hs'),
|
||||||
Lang('node', 'ts'),
|
Lang('node', 'ts'),
|
||||||
|
|||||||
Binary file not shown.
BIN
wasm/code.wasm
BIN
wasm/code.wasm
Binary file not shown.
Binary file not shown.
BIN
wasm/loop.wasm
BIN
wasm/loop.wasm
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user