Generating Code

Single file

# Rust (default target)
vexilc codegen hello.vexil --target rust --output hello.rs

# TypeScript
vexilc codegen hello.vexil --target typescript --output hello.ts

# Go
vexilc codegen hello.vexil --target go --output hello.go

Default target is rust. Output goes to stdout if --output is omitted.

Multi-file project

For schemas with imports, use the build subcommand:

vexilc build root.vexil --include ./schemas --output ./generated --target rust

This resolves all imports, compiles in topological order, and generates one file per namespace.

Watch mode

Auto-rebuild on save:

vexilc watch root.vexil --include ./schemas --output ./generated --target typescript

Changes to any .vexil file in the watched directories trigger a rebuild with 200ms debounce.

Using generated code

Rust

Add vexil-runtime to your Cargo.toml:

[dependencies]
vexil-runtime = "0.5"
#![allow(unused)]
fn main() {
use vexil_runtime::{BitWriter, BitReader, Pack, Unpack};

let greeting = Greeting {
    name: "world".to_string(),
    message: "hello".to_string(),
    count: 42,
    _unknown: Vec::new(),
};

// Encode
let mut w = BitWriter::new();
greeting.pack(&mut w).unwrap();
let bytes = w.finish();

// Decode
let mut r = BitReader::new(&bytes);
let decoded = Greeting::unpack(&mut r).unwrap();
}

TypeScript

Install @vexil-lang/runtime:

npm install @vexil-lang/runtime
import { BitWriter, BitReader } from '@vexil-lang/runtime';
import { encodeGreeting, decodeGreeting } from './hello';

const w = new BitWriter();
encodeGreeting(
  { name: 'world', message: 'hello', count: 42, _unknown: new Uint8Array(0) },
  w,
);
const bytes = w.finish();

const r = new BitReader(bytes);
const decoded = decodeGreeting(r);

Go

import vexil "github.com/vexil-lang/vexil/packages/runtime-go"

greeting := &Greeting{
    Name:    "world",
    Message: "hello",
    Count:   42,
}

w := vexil.NewBitWriter()
greeting.Pack(w)
bytes := w.Finish()

r := vexil.NewBitReader(bytes)
var decoded Greeting
decoded.Unpack(r)