Expand description
§Writing a Surfer Translator Plugin
Surfer translators are web-asssembly binaries that are loaded at runtime by Surfer.
They can be written in any language that has an extism
plugin
development kit
https://extism.org/docs/concepts/pdk/.
For this example we will use Rust since that is what the rest of Surfer is written in, which allows us to reuse type definitions between Surfer itself and the plugin.
To create a plugin, create a new project
cargo init --lib cool_surfer_translator
then modify the Cargo.toml
to set the library type to “cdylib”, and add the extism_pdk
and surfer-translation-types
library as dependencies
[lib]
crate-type = ["cdylib"]
[dependencies]
extism-pdk = "1.4.1"
surfer-translation-types.git = "https://gitlab.com/surfer-project/surfer.git"
In your new project, you now need to define a few functions which must all
be annotated with #[plugin_fn]
and have the right type signature. Click on each function to learn more
- new: initializes the plugin
- name: sets the name of the plugin in the format selection list
- translates: allows the plugin to opt in or out of translating certain signals
- variable_info: specifies the hierarchical structure of the signal
- translate: does the actual translation of bit vectors to new values
In addition, there are a few optional functions that can be implemented for additional functionality
- reload: Called when Surfer reloads the waveform
- set_wave_source: Called when the current waveform changes
§Accessing Files
Surfer plugins are sandboxed and are in general not allowed any access to the external world. Translators may need to read the file system however, and for that, “host functions” are provided. To use them, define them in your plugin using
use extism_pdk::host_fn;
#[host_fn]
extern "ExtismHost" {
pub fn read_file(filename: String) -> Vec<u8>;
pub fn file_exists(filename: String) -> bool;
}
§Maintaining State
Plugins may need to maintain state between calls. This can be done by simply using static variables in the plugin.
static STATE: Mutex<bool> = Mutex::new(false)
NOTE: The static variables are shared between all “instances” of the translator, i.e. if you want to maintain different state for different variables, this must currently be handled on the plugin side.
§Testing and Installation
To build your plugin, call
cargo build --debug --target wasm32-unknown-unknown
which will create target/debug/cool_surfer_translator.wasm
This file can then be copied to the local or global plugin translator directories in order to be found and automatically loaded by Surfer
Local:
.surfer/translators/
Global
Os | Path |
---|---|
Linux | ~/.config/surfer/translators . |
Windows | C:\Users\<Name>\AppData\Roaming\surfer-project\surfer\config\translators . |
macOS | /Users/<Name>/Library/Application Support/org.surfer-project.surfer/translators |
Modules§
- optional
- Documentation for functions which are not necessary for a basic translator but can do more advanced things.
Functions§
- name
- Returns the name of the plugin as shown to the user. This needs to be unique, so do not set it to a translator name that is already present in Surfer.
- new
- The new function is used to initialize a plugin. It is called once when the plugin is loaded
- translate
- Gets called once for every value of every signal being rendered, and returns the corresponding translated value.
- translates
- Returns a translation preference for the specified variable, which allows the translator to opt out of translating certain signals which it does not support.
- variable_
info - Returns information about the hierarchical structure of the signal. For translators which simply want to do bit vector to string and/or color translation, returning [VariableInfo::Bits] is sufficient.