Skip to main content

Crate byteflow

Crate byteflow 

Source
Expand description

Byteflow — embeddable flow runtime (package byteflow-actors).

Not a language, not Tokio, not a JVM. You assemble register bytecode in host Rust (ChunkBuilder), spawn many lightweight flows on an M:N scheduler, and they talk through mailboxes with a strict hop protocol.

Dependents write use byteflow::... (crate name) while crates.io lists the package as byteflow-actors.

§What you get

PieceRole
ChunkBuilder / OpcodeAssemble .bf programs in Rust (no source language)
Vm / VmResultPer-flow register interpreter; effects hand off to the scheduler
RuntimeWorker pool + timer; spawn / join / host Runtime::send
Value::MessageAtomic Hop envelope — the only value allowed on Send / Ask
Value::CapFlowCap address for bytecode delivery (Send / Ask targets)
SupervisorRestart policies when a flow fails
std_native_tableprint, now_ms, make_msg, msg_*, msg_reply_cap

§Atomic Hop (messaging contract)

Every bytecode Send / Ask carries exactly one Message:

Message { sender, reply_cap, request_id, tag, payload }
  • Bare Int / Pid / Str on Send → trap / SendError::NotAHop
  • Scheduler stamps sender (authenticated origin) and mints reply_cap (SEND-only Cap back to the caller)
  • Reply with std_native_table’s msg_reply_capnot msg_sender (Pid is identity, not an address)

Also: selective receive (ReceiveMatch), and Ask for correlated RPC.

§FlowCap (addressing)

ValueUse
Value::CapTarget of Send / Ask; from SelfPid, Spawn, or reply_cap
Value::PidIdentity inside a delivered hop (msg_sender)

Host Runtime::send still takes FlowId (trusted embedder path).

§Values (ABI v4)

Unit | Bool | Int | Float | Pid | Message | Cap | Str | Bytes

Str / Bytes are Arc-backed for cheap register/mailbox clones. They are not Atomic Hops by themselves.

§Quick start — scalar

use byteflow::{ChunkBuilder, Opcode, FlowOutcome, Runtime, Value};

let mut b = ChunkBuilder::new("demo");
b.begin_function("main", 0, 2);
b.emit_load_imm(0, 41);
b.emit_load_imm(1, 1);
b.emit_binop(Opcode::Add, 0, 0, 1);
b.emit_return(0);

let rt = Runtime::new(b.finish())?;
let outcome = rt.spawn(0, &[])?.join();
rt.shutdown();
assert!(matches!(outcome, FlowOutcome::Completed(Value::Int(42))));

§Quick start — Atomic Hop (ping-pong)

Hop demos need the std native table (make_msg / msg_*):

use byteflow::{samples, std_native_table, FlowOutcome, Runtime, Value};

let rt = Runtime::with_natives(samples::ping_pong(), std_native_table())?;
let main = rt.function_index("main").expect("main");
let outcome = rt.spawn(main, &[])?.join();
rt.shutdown();
assert!(matches!(outcome, FlowOutcome::Completed(Value::Int(2))));

More samples: samples::atomic_request_reply, samples::ask_reply, samples::selective_receive, forged-sender security regressions.

§Design guides (rendered on docs.rs)

§What this is not

  • Not a replacement for Tokio / async Rust (no .await IO loop)
  • Not a distributed cluster runtime (single process, in-memory mailboxes)
  • Not a full object-capability OS (native quotas / Cap attenuation come later)

Host owns I/O and policy. Byteflow owns cheap concurrency and hop delivery.

Re-exports§

pub use bytecode::asm_macros;
pub use bytecode::decode;
pub use bytecode::disassemble;
pub use bytecode::encode;
pub use bytecode::verify;
pub use bytecode::Chunk;
pub use bytecode::ChunkBuilder;
pub use bytecode::FormatError;
pub use bytecode::FunctionDef;
pub use bytecode::Instruction;
pub use bytecode::Label;
pub use bytecode::Message;
pub use bytecode::Opcode;
pub use bytecode::Value;
pub use bytecode::VerifyError;
pub use bytecode::ABI_VERSION;
pub use bytecode::MAGIC;
pub use natives::std_native_map;
pub use natives::std_native_table;
pub use natives::std_natives;
pub use scheduler::fault_count;
pub use scheduler::next_flow_id;
pub use scheduler::flow_id_from_u64;
pub use scheduler::report_fault;
pub use scheduler::CapId;
pub use scheduler::CapRights;
pub use scheduler::ChildSpec;
pub use scheduler::Delivery;
pub use scheduler::Mailbox;
pub use scheduler::Flow;
pub use scheduler::FlowHandle;
pub use scheduler::FlowId;
pub use scheduler::FlowMetrics;
pub use scheduler::FlowOutcome;
pub use scheduler::FlowState;
pub use scheduler::RestartPolicy;
pub use scheduler::Runtime;
pub use scheduler::RuntimeConfig;
pub use scheduler::RuntimeError;
pub use scheduler::RuntimeMetrics;
pub use scheduler::RuntimeMetricsSnapshot;
pub use scheduler::RuntimeSpawner;
pub use scheduler::SendError;
pub use scheduler::SpawnError;
pub use scheduler::Supervisor;
pub use scheduler::SupervisorConfig;
pub use scheduler::DEFAULT_QUANTUM;
pub use vm::expect_arg;
pub use vm::expect_bool;
pub use vm::expect_int;
pub use vm::expect_message;
pub use vm::expect_u64;
pub use vm::Fault;
pub use vm::NativeFn;
pub use vm::NativeResult;
pub use vm::NativeTable;
pub use vm::NativeTableBuilder;
pub use vm::Vm;
pub use vm::VmResult;
pub use vm::MAX_CALL_DEPTH;

Modules§

bytecode
Instruction set, .bf (BFV0) wire format, assembler and verifier.
docs
Long-form design notes shipped inside the crate (also under docs/ on GitHub).
log
Host-side scheduler diagnostics on stderr, gated by BYTEFLOW_LOG.
natives
Standard native (FFI) table shipped with the facade.
samples
Built-in demo chunks assembled with crate::ChunkBuilder.
scheduler
M:N flows, mailboxes, timer, supervisor and Runtime.
vm
Register-based interpreter for one virtual flow.

Macros§

emit_native1_from
emit_native1_from!(builder, dest, src, native) — sugar for crate::ChunkBuilder::emit_native1_from.
emit_native_n
emit_native_n!(builder, base, native, argc) — sugar for crate::ChunkBuilder::emit_native_n.