Appearance
WASM Development Guide
BlueCurve supports WebAssembly (WASM) for high-performance, cross-platform extensibility. This guide helps you set up your development environment and build your first search plugin using Rust, Zig, Kotlin, or Go.
Use matching SDK and host builds. Fingerprint helpers preserve all 128 bits; the host computation imports now take (ptr: i32, len: i32, outPtr: i32) and write 16 bytes in little-endian order. Rebuild plugins that used the older two-argument imports. Prefer the SDK helpers so your plugin does not have to manage these output buffers directly.
Choosing a Language
- Rust: Recommended for most developers. Offers a rich ecosystem, excellent memory safety, and a type-safe SDK.
- Zig: Recommended for low-level optimizations and minimal binary sizes. Best for developers who prefer manual memory control.
- Kotlin: Useful when sharing models or business logic with Kotlin-based systems and targeting Kotlin/Wasm WASI.
- Go: Useful for teams already building connector logic in Go and targeting WASI reactor modules.
Rust Development
1. Prerequisites
- Rust (Stable)
- WASM target:
rustup target add wasm32-wasip1
2. Project Setup
Extract the Rust SDK source artifact beside your plugin and add a path dependency to Cargo.toml.
toml
[package]
name = "my-bluecurve-plugin"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
bluecurve-search-sdk = { path = "../bluecurve-search-sdk-rust" }3. Implementation
See the Indexing Plugins or Job Plugins guides for implementation details using the #[bluecurve_file] or #[bluecurve_job] macros.
4. Compilation
bash
cargo build --target wasm32-wasip1 --release --config 'target.wasm32-wasip1.rustflags=["-C","link-arg=--allow-undefined"]'The resulting binary will be located at target/wasm32-wasip1/release/my_bluecurve_plugin.wasm.
Zig Development
1. Prerequisites
- Zig 0.15.2
2. Project Setup
Create a project with zig init. Add .bluecurve = .{ .path = "../bluecurve-search-sdk-zig" } to the dependencies in build.zig.zon, pointing to the extracted SDK. Use this build.zig:
zig
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const sdk = b.dependency("bluecurve", .{ .target = target, .optimize = optimize });
const exe = b.addExecutable(.{
.name = "my-plugin",
.root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
}),
});
exe.root_module.addImport("bluecurve", sdk.module("bluecurve"));
exe.entry = .disabled;
exe.rdynamic = true;
b.installArtifact(exe);
}3. Compilation
bash
zig build -Dtarget=wasm32-freestanding -Doptimize=ReleaseSmallThe binary will be in zig-out/bin/my-plugin.wasm.
Kotlin Development
The Kotlin SDK targets Kotlin/Wasm WASI. Add its sources to your plugin's wasmWasiMain source set:
kotlin
@file:OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
plugins { kotlin("multiplatform") version "2.3.21" }
repositories { mavenCentral() }
kotlin {
wasmWasi { nodejs(); binaries.executable() }
sourceSets.getByName("wasmWasiMain").kotlin.srcDir("../bluecurve-search-sdk-kotlin/src/wasmWasiMain/kotlin")
}Use bluecurveFile or bluecurveJob in your exported entrypoint; see the complete plugin examples below. These helpers copy the inbound payload before running your handler, so WasmPayload remains readable after SDK calls. The exported allocator supports one host write followed immediately by the entrypoint and a matching release. It rejects overlapping allocations and is not a general persistent allocator.
Build with ./gradlew compileProductionExecutableKotlinWasmWasi (.\gradlew.bat on Windows). Ship the .wasm under build/compileSync/wasmWasi/main/productionExecutable/kotlin. Production compilation removes unused imports from the other plugin role. The BlueCurve host supports the GC and exception features this compiler output requires.
Go Development
Use Go 1.26 with the SDK module bluecurve.io/search/sdk/golang. Build a WASI reactor; BlueCurve calls its _initialize export before invoking your file or job entrypoint.
sh
GOOS=wasip1 GOARCH=wasm go build -buildmode=c-shared -o plugin.wasm .File exports use (unsafe.Pointer, int32) -> int64; job exports use (unsafe.Pointer, int32). Use FileEntrypoint or JobEntrypoint to access the payload.
SDK Features Reference
| Feature | Rust | Zig | Kotlin | Go |
|---|---|---|---|---|
| Logging | Logger::info(...) | bc.log(.Info, ...) | Logger.info(...) | bluecurve.Info(...) |
| Telemetry | Kpi::new() | bc.Job.Kpi | Kpi() | Kpi{} |
| Indexing | DocumentIndexBuilder | bc.Indexer.Builder | DocumentIndexBuilder | DocumentIndexBuilder |
| Language | detect_language(...) | bc.detectLanguage(...) | detectLanguage(...) | DetectLanguage(...) |
| Hashing | compute_fingerprint(...) | bc.computeFingerprint(...) | computeFingerprint(...) | ComputeFingerprint(...) |
State and repository metadata reads automatically grow their buffers when necessary. Missing data remains distinct from empty values. The shared host validation suite compiles and executes both plugin roles for all four SDKs.
Complete examples: Indexing Plugins and Job Plugins.
Next: Packaging & Deployment