Building A Plugin System with Rust+Wasm

Robert Masen

Slides

https://github.com/freemasen/rbr-wasmer

Repo

https://github.com/freemasen/rbr-plugins

What Is Wasm

  • Bytecode
  • Needs VM

# #![allow(unused_variables)]
#fn main() {
#[no_mangle]
pub fn double(n: u32) -> u32 {
    n * 2
}
#}
(module
  (type $t0 (func (param i32) (result i32)))
  (func $double (export "double") (type $t0) (param $p0 i32) (result i32)
    (i32.shl
      (local.get $p0)
      (i32.const 1)))
  (table $T0 1 1 funcref)
  (memory $memory (export "memory") 16)
  (global $g0 (mut i32) (i32.const 1048576))
  (global $__data_end (export "__data_end") i32 (i32.const 1048576))
  (global $__heap_base (export "__heap_base") i32 (i32.const 1048576)))

  • The simplest VM to use right now

Requirements

  • Rust (obviously)
  • The wasm32-unknown-unknown target
    • rustup target add wasm32-unknown-unknown
  • Cmake
    • MacOS
      • brew install cmake
      • ports install cmake
    • Debian/Ubuntu
      • apt-get install cmake
    • FreeBSD
      • pkg install cmake
    • Windows
      • choco install cmake
      • (cmake.org/download)[https://cmake.org/download/]

Wasm's Limitations

  • Only knows numbers

Simple Plugin

Code!

Simple Plugin Runner

Code!

Work Arounds

  • Remember WASM Only Knows Numbers
    • How could we pass/return a String?

Plugin Strings

Memory

0 1 2 3 4 5 6 7 8 9 10
® 0 0 0 0 d o u b l e

# #![allow(unused_variables)]
#fn main() {
//                0,1,2,3,4, 5 , 6 , 7 , 8 , 9 , 10
let memory = vec![0,0,0,0,0,100,111,117,98 ,108,101];
//                ®,0,0.0.0, d , o , u , b , l , e
let wi_len = vec![0,0,0,0,6,100,111,117,98 ,108,101];
//                 [ 6u32 ], d , o , u , b , l , e
let double = vec![0,0,0,0,12,100,111,117,98 ,108,101,100,111,117,98 ,108,101]
//                [ 12u32 ] , d , o , u , b , l , e , d , o , u , b , l , e
#}

Code!

with a little unsafe

Runner Strings

Code!

Error Feedback

But what if this goes wrong?

  • Import a function from the host
    • First Arg always Context

Proc Macro

  • Attribute Macro
  • TokenStreams to TokenStreams

Move the scary bits

Code!

Potental

  • What if we wanted to work with even more complicated data?
  • Could we use a binary serialization format?
    • Bincode
    • cbor
    • msg-pack