Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

65 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Bebop FFI

High-performance stable C ABI for Bebop binary serialization, with Zig as the canonical implementation

RSR Bronze TPCF Perimeter 3 License IIoT Edge Kaldor Integration

Overview

Bebop FFI provides a small, explicit FFI boundary that exposes the Bebop binary serialization format via a stable C ABI.

The project defines the FFI contract (include/bebop_v_ffi.h) and allows multiple implementations behind it (Zig is canonical; Rust welcome), so that applications in any language can decode and encode Bebop messages without reimplementing the wire format.

This library is a core component of the Kaldor IIoT ecosystem, enabling efficient message passing between resource-constrained edge devices (ESP32-C6, RISC-V microcontrollers) and backend services.

Why "FFI" (not "bridge")?

This project focuses on defining and maintaining a correct Foreign Function Interface — the hard part is not connecting languages, but correctness of the ABI boundary.

An FFI boundary is where you must be explicit about things that higher-level code usually hides:

  • ABI stability - calling conventions, alignment/padding

  • Ownership and lifetimes - who frees what, when

  • Error propagation - how failures cross the boundary

  • Message framing - for networked data

Getting any of those wrong can produce silent corruption rather than a clean crash.

So this repo treats the C ABI as the core deliverable: a small, boring, stable contract that V can rely on, while different implementations can evolve underneath without changing user code.

Current Status

Component Status Notes

ABI header

drafted

include/bebop_v_ffi.h (stable, historical name for C ABI compatibility)

Zig implementation

in development

implementations/zig/

Rust implementation

help wanted

implementations/rust/README.md

Example framing

included

v/examples/iiot_server.v, v/examples/iiot_client.v

Quickstart (conceptual)

  1. Generate C bindings from schema with bebopc --lang c

  2. Build the Zig implementation via zig build

  3. Link your application against the compiled FFI library

  4. Call C functions from include/bebop_v_ffi.h

Why Bebop?

Bebop is a schema-based binary serialization format optimized for real-time applications:

  • 10-100x faster than Protocol Buffers, MessagePack, and JSON

  • Zero-copy deserialization - reads directly from wire format

  • Tiny code generation - ~50KB for full runtime (ideal for microcontrollers)

  • Schema evolution - backwards-compatible message updates

  • No reflection - compile-time code generation, no runtime overhead

Benchmark: 1M messages (100-byte payload)
┌────────────────┬───────────┬─────────────┐
│ Format         │ Serialize │ Deserialize │
├────────────────┼───────────┼─────────────┤
│ Bebop          │ 12ms      │ 8ms         │
│ FlatBuffers    │ 45ms      │ 15ms        │
│ Protocol Bufs  │ 180ms     │ 220ms       │
│ MessagePack    │ 350ms     │ 410ms       │
│ JSON           │ 890ms     │ 1,200ms     │
└────────────────┴───────────┴─────────────┘

Why Zig for the canonical implementation?

Zig offers:

  • C ABI compatible - direct FFI with C, no wrapper overhead

  • Memory safe - bounds checking, no buffer overflows

  • No hidden allocations - predictable memory usage

  • Fast compilation - builds in milliseconds

  • Cross-compilation first - seamless targeting ESP32, ARM, RISC-V

  • Ideal for embedded - minimal runtime, bare-metal friendly

Zig enables us to maintain a correct, auditable FFI layer that consumers in any language can trust.

Why This FFI?

Kaldor IIoT needs to move telemetry data (temperature, humidity, loom status, spinning metrics) between:

  • Edge devices (ESP32-C6 and other microcontrollers)

  • Gateway nodes (Raspberry Pi, RISC-V SBCs)

  • Backend services (Deno, Rust, ReScript)

Bebop FFI provides the glue layer via stable C ABI, enabling:

┌─────────────────┐     Bebop Binary      ┌─────────────────┐
│  Firmware       │◄────────────────────►│  Deno/Rust      │
│  (ESP32-C6)     │    ~8 bytes/msg       │  Backend        │
└────────┬────────┘                       └────────┬────────┘
         │                                         │
         │  Matter Protocol (Thread mesh)          │  WASM Compute
         │                                         │
         ▼                                         ▼
┌─────────────────┐                       ┌─────────────────┐
│  Gateway Node   │                       │  TimescaleDB    │
│  (RISC-V SBC)   │                       │  (Time-series)  │
└─────────────────┘                       └─────────────────┘

Key Features

  • Zero-Copy Parsing - Reads Bebop messages without intermediate allocations

  • Code Generation - V source generated from .bop schema files

  • Memory Safe - Bounds checking, no buffer overflows

  • Tiny Footprint - <20KB compiled FFI layer

  • Cross-Platform - Linux, macOS, Windows, embedded targets

  • Thread Safe - No global state, safe for concurrent use

  • Offline-First - Works completely air-gapped

  • RSR Compliant - Rhodium Standard Repository Bronze tier

Quick Start

Installation

# Clone repository
git clone https://github.com/hyperpolymath/bebop-v-ffi.git
cd bebop-v-ffi

# Build the FFI library
v build -prod src/

# Run tests
v test tests/

# Install Bebop compiler (for schema compilation)
# See: https://bebop.sh/guide/installation/

Define Schema

Create a .bop schema file:

// schemas/telemetry.bop
struct SensorReading {
    uint32 device_id;
    uint64 timestamp_ms;
    float32 temperature_c;
    float32 humidity_pct;
    uint8 status_flags;
}

message LoomStatus {
    1 -> uint32 loom_id;
    2 -> string pattern_name;
    3 -> uint32 picks_completed;
    4 -> uint32 picks_total;
    5 -> float32 efficiency_pct;
}

Build the FFI Library

# Build Zig implementation
cd implementations/zig
zig build -Drelease-safe

# Output: shared library (libbepopc.so / .dylib / .dll)

Generate struct definitions and FFI bindings from your schema, then call the C functions in include/bebop_v_ffi.h:

// Pseudocode: C-compatible FFI calls
VBebopCtx *ctx = bebop_ctx_new();
VBytes encoded = bebop_encode_sensor_reading(ctx, &reading);
// ... send encoded buffer ...
VBytes_free(ctx, encoded);
bebop_ctx_free(ctx);

Architecture

┌─────────────────────────────────────────────────────────┐
│                     User Application                     │
│              (any language with C FFI)                  │
└─────────────────────────┬───────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────┐
│                   C ABI Contract                         │
│         (include/bebop_v_ffi.h - stable & explicit)    │
├─────────────────────────────────────────────────────────┤
│  bebop_ctx_new/free, bebop_encode_*, bebop_decode_*   │
│  Memory ownership rules clearly defined                 │
└─────────────────────────┬───────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────┐
│                 Zig Implementation                       │
│              (implementations/zig/ - canonical)        │
├─────────────────────────────────────────────────────────┤
│  - Buffer management (arena allocator)                  │
│  - Endianness handling                                  │
│  - Bounds checking                                      │
│  - Zero-copy view creation                              │
└─────────────────────────┬───────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────┐
│                 Bebop Wire Format                        │
│         (standardized binary serialization)             │
└─────────────────────────────────────────────────────────┘

Design Rationale

Why a stable C ABI?

The FFI contract enables multiple things:

  1. Language agnostic - Any language with C FFI can use it (V, Rust, Zig, Ada, ReScript, etc.)

  2. Implementation flexibility - We can improve under the ABI without breaking consumers

  3. Binary compatibility - Applications stay linked even after library updates

Why Zig implementation?

Zig is ideal because:

  1. Zero-overhead FFI - Compiles directly to correct C ABI

  2. Memory safety - Catches mistakes at compile time

  3. Cross-compilation - Targets embedded platforms seamlessly

  4. Small footprint - Minimal runtime for microcontroller constraints

Why not reimplement Bebop?

Bebop’s wire format is standardized and battle-tested. We wrap it rather than reinvent to:

  1. Guarantee correctness - Use the canonical implementation

  2. Track upstream - Bebop updates flow through automatically

  3. Multi-language parity - Same wire format across all consumer languages

Integration with Kaldor IIoT

Bebop FFI is designed to work seamlessly with the Kaldor IIoT platform. Any language with C FFI support can use it. Example pseudocode for a firmware app:

// Pseudocode: language-independent example
// Create an FFI context
ctx := bebop_ctx_new()

// Build a message (generated structs from schema)
reading := SensorReading{
    device_id: 0x1001,
    timestamp_ms: get_time_ms(),
    temperature_c: read_temperature(),
    humidity_pct: read_humidity(),
    status_flags: 0x01
}

// Serialize via FFI
buffer := bebop_encode_sensor_reading(ctx, reading)

// Send payload via Matter/network...
publish("kaldor/telemetry", buffer)

// Clean up
bebop_ctx_free(ctx)

Kaldor Message Types

| Message Type | Size | Use Case | |--------------|------|----------| | SensorReading | 17 bytes | Environmental telemetry | | LoomStatus | ~40 bytes | Weaving progress tracking | | SpinnerMetrics | 24 bytes | Spinning node performance | | AlertEvent | ~60 bytes | Fault notifications | | GossipHeartbeat | 12 bytes | Mesh network health |

Documentation

Standards Compliance

RSR Framework: Bronze Tier

Bebop-V-FFI meets Rhodium Standard Repository (RSR) Bronze tier requirements:

  • Type safety (V compile-time guarantees)

  • Memory safety (bounds checking, no raw pointers in public API)

  • Offline-first (no network dependencies)

  • Complete documentation

  • .well-known/ directory

  • Build system (Justfile)

  • CI/CD pipeline

TPCF: Perimeter 3 (Community Sandbox)

This project uses the Tri-Perimeter Contribution Framework (TPCF):

  • Perimeter 1: Core maintainers only

  • Perimeter 2: Trusted contributors

  • Perimeter 3: Community Sandbox - Open to all

All contributions are welcome! See CONTRIBUTING.md.

Building from Source

Prerequisites

  • V compiler 0.4.4+ (v version)

  • C compiler (GCC 11+ or Clang 14+)

  • Bebop compiler (bebopc --version)

  • just command runner

Build Commands

# Build library
just build

# Build with optimizations
just build-release

# Run tests
just test

# Generate V bindings from schemas
just codegen

# Check RSR compliance
just validate-rsr

# Build for ESP32-C6 target
just build-esp32

Testing

# Run all tests
v test tests/

# Run with verbose output
v test tests/ -stats

# Run specific test
v test tests/test_encode.v

# Benchmark serialization
v run benchmarks/bench_encode.v

Performance

| Operation | Time (1M msgs) | Memory | |-----------|----------------|--------| | Encode SensorReading | 8ms | 0 allocs | | Decode SensorReading | 5ms | 0 allocs | | Encode LoomStatus | 12ms | 1 alloc (string) | | Decode LoomStatus | 9ms | 1 alloc (string) |

Binary sizes:

  • FFI library: ~18KB (stripped)

  • Full firmware (with Matter): ~280KB

  • Bebop runtime: ~50KB

Security

See SECURITY.md for:

  • Supported versions

  • Vulnerability reporting process

  • Security best practices

License

SPDX-License-Identifier: CC-BY-SA-4.0

Dual licensed under your choice of:

  • MPL-2.0 - GNU Affero General Public License

  • MPL-2.0 v0.8 - Community ownership with reversibility

  • kaldor-iiot - Parent IIoT platform

  • bunsenite - Nickel config parser with similar FFI architecture

  • Bebop - Binary serialization format

  • V Language - Systems programming language

Roadmap

See ROADMAP.adoc for the full development roadmap including:

  • Phase 1: Core FFI implementation and schema codegen

  • Phase 2: Release and packaging (crates.io, vpkg)

  • Phase 3: Next-gen Rust-V-Bebop hybrid implementation

Help Wanted: Rust Implementation (plug-compatible)

We’d welcome a Rust implementation behind the same C ABI, so consumers can choose Zig or Rust underneath.

What you’d do:

  • Implement the functions in include/bebop_v_ffi.h as a Rust cdylib

  • Use VBytes (ptr+len) for all strings/bytes (do not assume NUL-terminated data)

  • Match the framing + golden test vectors under test-vectors/

Good first PR:

  • bebop_decode_sensor_reading() for SensorReading

  • bebop_ctx_new() / bebop_ctx_free() and bebop_free_reading()

See docs/60-contributing-implementations.adoc for technical notes and common pitfalls.

Acknowledgments


Version: 0.1.0
Status: Active Development
Last Updated: 2025-12-24

"Microseconds matter when you’re weaving the future."

About

Zig FFI bindings for the Bebop binary serialization format.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages