Skip to content

Commit e7b3cfe

Browse files
committed
feat: compiled plugin
1 parent b7dccfd commit e7b3cfe

File tree

6 files changed

+126
-27
lines changed

6 files changed

+126
-27
lines changed

Extism/lib/Extism.pm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use 5.016;
44
use strict;
55
use warnings;
66
use Extism::XS qw(version log_file);
7+
use Extism::CompiledPlugin;
78
use Extism::Plugin;
89
use Extism::Function ':all';
910
use Exporter 'import';
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package Extism::CompiledPlugin;
2+
3+
use 5.016;
4+
use strict;
5+
use warnings;
6+
use Carp qw(croak);
7+
use Extism::XS qw(
8+
compiled_plugin_new
9+
compiled_plugin_free
10+
);
11+
use Exporter 'import';
12+
use Data::Dumper qw(Dumper);
13+
use Devel::Peek qw(Dump);
14+
use version 0.77;
15+
our $VERSION = qv(v0.2.0);
16+
17+
our @EXPORT_OK = qw(BuildPluginNewParams);
18+
19+
sub BuildPluginNewParams {
20+
my ($wasm, $opt) = @_;
21+
my $functions = $opt->{functions} // [];
22+
my @rawfunctions = map {$$_} @{$functions};
23+
my %p = (
24+
wasm => $wasm,
25+
_functions_array => pack('Q*', @rawfunctions)
26+
);
27+
$p{functions} = unpack('Q', pack('P', $p{_functions_array}));
28+
$p{n_functions} = scalar(@rawfunctions);
29+
$p{wasi} = $opt->{wasi} // 0;
30+
$p{fuel_limit} = $opt->{fuel_limit};
31+
$p{errptr} = "\x00" x 8;
32+
$p{errmsg} = unpack('Q', pack('P', $p{errptr}));
33+
\%p
34+
}
35+
36+
sub new {
37+
my ($name, $wasm, $options) = @_;
38+
my %opt = %{$options // {}};
39+
if (defined $opt{fuel_limit}) {
40+
croak "No way to set fuel for CompiledPlugins yet";
41+
}
42+
my $p = BuildPluginNewParams($wasm, \%opt);
43+
my $compiled = compiled_plugin_new($p->{wasm}, length($p->{wasm}), $p->{functions}, $p->{n_functions}, $p->{wasi}, $p->{errmsg});
44+
my %savedoptions;
45+
if ($opt{allow_http_response_headers}) {
46+
$savedoptions{allow_http_response_headers} = $opt{allow_http_response_headers};
47+
}
48+
my %obj = ( compiled => $compiled, options => \%savedoptions);
49+
bless \%obj, $name
50+
}
51+
52+
sub DESTROY {
53+
my ($self) = @_;
54+
$self->{compiled} or return;
55+
compiled_plugin_free($self->{compiled});
56+
}
57+
58+
1;

Extism/lib/Extism/Plugin.pm

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use Carp qw(croak);
77
use Extism::XS qw(
88
plugin_new
99
plugin_new_with_fuel_limit
10+
plugin_new_from_compiled
1011
plugin_allow_http_response_headers
1112
plugin_new_error_free
1213
plugin_call
@@ -22,6 +23,7 @@ use Extism::XS qw(
2223
);
2324
use Extism::Plugin::CallException;
2425
use Extism::Plugin::CancelHandle;
26+
use Extism::CompiledPlugin qw(BuildPluginNewParams);
2527
use Data::Dumper qw(Dumper);
2628
use Devel::Peek qw(Dump);
2729
use JSON::PP qw(encode_json);
@@ -31,38 +33,26 @@ our $VERSION = qv(v0.2.0);
3133

3234
sub new {
3335
my ($name, $wasm, $options) = @_;
34-
my $functions = [];
35-
my $with_wasi = 0;
36-
my $fuel_limit;
37-
my $allow_http_response_headers;
38-
if ($options) {
39-
if (exists $options->{functions}) {
40-
$functions = $options->{functions};
41-
}
42-
if (exists $options->{wasi}) {
43-
$with_wasi = $options->{wasi};
44-
}
45-
if (exists $options->{fuel_limit}) {
46-
$fuel_limit = $options->{fuel_limit};
47-
}
48-
if (exists $options->{allow_http_response_headers}) {
49-
$allow_http_response_headers = $options->{allow_http_response_headers};
50-
}
36+
my ($plugin, $opt, $errptr);
37+
if (!ref($wasm) || !$wasm->isa('Extism::CompiledPlugin')) {
38+
$opt = defined $options ? {%$options} : {};
39+
my $p = BuildPluginNewParams($wasm, $opt);
40+
$plugin = ! defined $p->{fuel_limit}
41+
? plugin_new($p->{wasm}, length($p->{wasm}), $p->{functions}, $p->{n_functions}, $p->{wasi}, $p->{errmsg})
42+
: plugin_new_with_fuel_limit($p->{wasm}, length($p->{wasm}), $p->{functions}, $p->{n_functions}, $p->{wasi}, $p->{fuel_limit}, $p->{errmsg});
43+
$errptr = $p->{errptr};
44+
} else {
45+
$opt = $wasm->{options};
46+
$errptr = "\x00" x 8;
47+
my $errmsg = unpack('Q', pack('P', $errptr));
48+
$plugin = plugin_new_from_compiled($wasm->{compiled}, $errmsg);
5149
}
52-
my $errptr = "\x00" x 8;
53-
my $errptrptr = unpack('Q', pack('P', $errptr));
54-
my @rawfunctions = map {$$_} @{$functions};
55-
my $functionsarray = pack('Q*', @rawfunctions);
56-
my $functionsptr = unpack('Q', pack('P', $functionsarray));
57-
my $plugin = ! defined $fuel_limit
58-
? plugin_new($wasm, length($wasm), $functionsptr, scalar(@rawfunctions), $with_wasi, $errptrptr)
59-
: plugin_new_with_fuel_limit($wasm, length($wasm), $functionsptr, scalar(@rawfunctions), $with_wasi, $fuel_limit, $errptrptr);
6050
if (! $plugin) {
6151
my $errmsg = unpack('p', $errptr);
6252
plugin_new_error_free(unpack('Q', $errptr));
6353
croak $errmsg;
6454
}
65-
if ($allow_http_response_headers) {
55+
if ($opt->{allow_http_response_headers}) {
6656
plugin_allow_http_response_headers($plugin);
6757
}
6858
bless \$plugin, $name

Extism/lib/Extism/XS.pm

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ our @EXPORT_OK = qw(
3939
log_file
4040
log_custom
4141
log_drain
42+
compiled_plugin_new
43+
compiled_plugin_free
44+
plugin_new_from_compiled
4245
CopyToPtr
4346
);
4447

Extism/lib/Extism/XS.xs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ ExtismMemoryHandle T_UV
8181
const ExtismCancelHandle * T_PTR
8282
PV T_PV
8383
uint64_t T_UV
84+
ExtismCompiledPlugin * T_PTR
85+
const ExtismCompiledPlugin * T_PTR
8486
HERE
8587

8688
const char *
@@ -90,6 +92,34 @@ version()
9092
OUTPUT:
9193
RETVAL
9294

95+
ExtismCompiledPlugin *
96+
compiled_plugin_new(wasm, wasm_size, functions, n_functions, with_wasi, errmsg)
97+
const uint8_t *wasm
98+
ExtismSize wasm_size
99+
const ExtismFunction **functions
100+
ExtismSize n_functions
101+
bool with_wasi
102+
char **errmsg
103+
CODE:
104+
RETVAL = extism_compiled_plugin_new(wasm, wasm_size, functions, n_functions, with_wasi, errmsg);
105+
OUTPUT:
106+
RETVAL
107+
108+
void
109+
compiled_plugin_free(compiled_plugin)
110+
ExtismCompiledPlugin *compiled_plugin
111+
CODE:
112+
extism_compiled_plugin_free(compiled_plugin);
113+
114+
ExtismPlugin *
115+
plugin_new_from_compiled(compiled_plugin, errmsg)
116+
const ExtismCompiledPlugin *compiled_plugin
117+
char **errmsg
118+
CODE:
119+
RETVAL = extism_plugin_new_from_compiled(compiled_plugin, errmsg);
120+
OUTPUT:
121+
RETVAL
122+
93123
ExtismPlugin *
94124
plugin_new(wasm, wasm_size, functions, n_functions, with_wasi, errmsg)
95125
const uint8_t *wasm

Extism/t/02-extism.t

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use Extism ':all';
77
use JSON::PP qw(encode_json decode_json);
88
use File::Temp qw(tempfile);
99
use Devel::Peek qw(Dump);
10-
plan tests => 51;
10+
plan tests => 54;
1111

1212
# ...
1313
ok(Extism::version());
@@ -261,3 +261,20 @@ ok($@->{message});
261261
my $plugin = Extism::Plugin->new($wasm, {wasi => 1, allow_http_response_headers => 1});
262262
ok($plugin);
263263
}
264+
265+
# compiled plugin
266+
{
267+
my $compiled = Extism::CompiledPlugin->new($wasm, {wasi => 1});
268+
for (1..2) {
269+
my $plugin = Extism::Plugin->new($compiled);
270+
my $output = $plugin->call('count_vowels', "this is a test");
271+
my $outputhash = decode_json($output);
272+
ok($outputhash->{count} == 4);
273+
}
274+
}
275+
{
276+
eval {
277+
Extism::CompiledPlugin->new($wasm, {wasi => 1, fuel_limit => 20});
278+
};
279+
ok($@);
280+
}

0 commit comments

Comments
 (0)