1extern crate self as extism;
3
4macro_rules! catch_out_of_fuel {
5 ($store: expr, $x:expr) => {{
6 let y = $x;
7 if y.is_err() && $store.get_fuel().is_ok_and(|x| x == 0) {
8 Err(Error::msg("plugin ran out of fuel"))
9 } else {
10 y
11 }
12 }};
13}
14
15pub(crate) use extism_convert::*;
16pub(crate) use std::collections::BTreeMap;
17use std::str::FromStr;
18pub(crate) use wasmtime::*;
19
20#[doc(inline)]
21pub use extism_convert as convert;
22
23pub use anyhow::Error;
24
25mod current_plugin;
26mod function;
27mod internal;
28pub(crate) mod manifest;
29pub(crate) mod pdk;
30mod plugin;
31mod plugin_builder;
32mod pool;
33mod readonly_dir;
34mod timer;
35
36pub mod sdk;
38
39pub use current_plugin::CurrentPlugin;
40pub use extism_convert::{FromBytes, FromBytesOwned, ToBytes};
41pub use extism_manifest::{Manifest, Wasm, WasmMetadata};
42pub use function::{Function, UserData, Val, ValType, PTR};
43pub use plugin::{
44 CancelHandle, CompiledPlugin, Plugin, WasmInput, EXTISM_ENV_MODULE, EXTISM_USER_MODULE,
45};
46pub use plugin_builder::{DebugOptions, PluginBuilder};
47pub use pool::{Pool, PoolBuilder, PoolPlugin};
48
49pub(crate) use internal::{Internal, Wasi};
50pub(crate) use timer::{Timer, TimerAction};
51pub(crate) use tracing::{debug, error, trace, warn};
52
53#[cfg(test)]
54mod tests;
55
56pub(crate) const VERSION: &str = concat!(env!("CARGO_PKG_VERSION"), "\0");
57
58pub fn extism_version() -> &'static str {
61 VERSION
62}
63
64#[derive(Clone)]
65struct LogFunction<F: Clone + Fn(&str)> {
66 func: F,
67}
68
69unsafe impl<F: Clone + Fn(&str)> Send for LogFunction<F> {}
70unsafe impl<F: Clone + Fn(&str)> Sync for LogFunction<F> {}
71
72impl<F: Clone + Fn(&str)> std::io::Write for LogFunction<F> {
73 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
74 if let Ok(s) = std::str::from_utf8(buf) {
75 (self.func)(s)
76 }
77
78 Ok(buf.len())
79 }
80
81 fn flush(&mut self) -> std::io::Result<()> {
82 Ok(())
83 }
84}
85
86pub fn set_log_callback<F: 'static + Clone + Fn(&str)>(
92 func: F,
93 filter: impl AsRef<str>,
94) -> Result<(), Error> {
95 let filter = filter.as_ref();
96 let is_level = tracing::Level::from_str(filter).is_ok();
97 let cfg = tracing_subscriber::FmtSubscriber::builder().with_env_filter({
98 let x = tracing_subscriber::EnvFilter::builder()
99 .with_default_directive(tracing::Level::ERROR.into());
100 if is_level {
101 x.parse_lossy(format!("extism={filter}"))
102 } else {
103 x.parse_lossy(filter)
104 }
105 });
106 let w = LogFunction { func };
107 cfg.with_ansi(false)
108 .with_writer(move || w.clone())
109 .try_init()
110 .map_err(|x| Error::msg(x.to_string()))?;
111 Ok(())
112}