Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

GitHub

This documentation is part of the "Projects with Books" initiative at zenOSmosis.

The source code for this project is available on GitHub.

Design Philosophy

Loading…

Design Philosophy

Relevant source files

Purpose and Scope

This document describes the fundamental design principles that guide the architecture and implementation of the rust-muxio framework. It covers four core tenets: runtime-agnostic architecture through a non-async callback-driven model, binary protocol with schemaless RPC design, cross-platform compatibility spanning native and WASM environments, and bidirectional symmetric communication patterns.

For details on how these principles manifest in the layered architecture, see Layered Architecture. For concrete platform implementations, see Platform Implementations.


Runtime Agnosticism: The Non-Async Core

The Callback-Driven Model

The muxio core library is deliberately implemented without async/await primitives. Instead, it uses a synchronous control flow with callback functions to handle events. This architectural choice enables the same core logic to function across fundamentally different runtime environments without modification.

graph TB
    subgraph CoreLibrary["muxio Core Library"]
RpcDispatcher["RpcDispatcher"]
RpcSession["RpcSession"]
FrameDecoder["FrameDecoder"]
end
    
    subgraph Callbacks["Callback Interfaces"]
OnRead["on_read_bytes()\nInvoked when data arrives"]
OnFrame["Frame callbacks\nInvoked per decoded frame"]
OnResponse["Response handlers\nInvoked on RPC completion"]
end
    
    subgraph Runtimes["Compatible Runtimes"]
Tokio["Tokio Multi-threaded\nasync runtime"]
StdThread["std::thread\nSingle-threaded or custom"]
WASM["WASM Browser\nJavaScript event loop"]
end
    
 
   RpcDispatcher -->|registers| OnResponse
 
   RpcSession -->|registers| OnFrame
 
   FrameDecoder -->|invokes| OnFrame
    
 
   Tokio -->|drives| CoreLibrary
 
   StdThread -->|drives| CoreLibrary
 
   WASM -->|drives| CoreLibrary
    
 
   CoreLibrary -->|invokes| Callbacks

The key insight is that the core library never blocks, never spawns tasks, and never assumes an async executor. Instead:

  • Data ingestion occurs through explicit read_bytes() calls src/rpc/rpc_dispatcher.rs:265-389
  • Event processing happens synchronously within the call stack
  • Downstream actions are delegated via callbacks, allowing the caller to decide whether to spawn async tasks, queue work, or handle synchronously

Sources: DRAFT.md:48-52 README.md:35-36

Benefits of Runtime Agnosticism

BenefitDescriptionCode Reference
WASM CompatibilityNo reliance on thread-based async executors that don’t exist in browser environmentsextensions/muxio-wasm-rpc-client/src/rpc_wasm_client.rs:15-140
Flexible IntegrationCore can be wrapped in TokioMutex, StdMutex, or RefCell depending on contextextensions/muxio-tokio-rpc-client/src/rpc_client.rs:30-38
Deterministic ExecutionNo hidden task spawning or scheduling; control flow is explicitsrc/rpc/rpc_dispatcher.rs:1-47
Testing SimplicityCan test without async harness; unit tests run synchronouslysrc/rpc/rpc_dispatcher.rs:391-490

Sources: DRAFT.md:48-52 README.md:35-36 extensions/muxio-wasm-rpc-client/src/rpc_wasm_client.rs:1-32


Binary Protocol and Schemaless Design

Low-Overhead Binary Framing

The muxio protocol operates entirely on raw byte sequences. Unlike text-based protocols (JSON, XML), every layer—from frame headers to RPC payloads—is transmitted as compact binary data. This design decision prioritizes performance and minimizes CPU overhead.

Sources: README.md:33-34 README.md:46-47

graph LR
    subgraph Application["Application Layer"]
RustStruct["Rust Struct\nAdd{a: f64, b: f64}"]
end
    
    subgraph Serialization["Serialization Layer"]
Bitcode["bitcode::encode()\nCompact binary"]
end
    
    subgraph RPC["RPC Protocol Layer"]
RpcRequest["RpcRequest\nmethod_id: u64\nparams: Vec<u8>"]
MethodID["xxhash(method_name)\nCompile-time constant"]
end
    
    subgraph Framing["Framing Layer"]
FrameHeader["Frame Header\nstream_id: u64\nflags: u8\npayload_len: u32"]
FramePayload["Binary Payload\nRaw bytes"]
end
    
 
   RustStruct -->|serialize| Bitcode
 
   Bitcode -->|Vec<u8>| RpcRequest
 
   RpcRequest -->|hash name| MethodID
 
   RpcRequest -->|encode| FramePayload
 
   FramePayload -->|wrap| FrameHeader

Schemaless RPC with Type Safety

The RPC layer is “schemaless” in that the protocol itself makes no assumptions about payload structure. Method IDs are 64-bit hashes computed at compile time via xxhash, and payloads are opaque byte vectors. However, type safety is enforced through shared service definitions :

This design achieves:

  • Compile-time verification : Mismatched types between client and server result in compilation errors, not runtime failures
  • Zero schema overhead : No runtime schema validation or parsing
  • Flexibility : Different services can use different serialization formats (bitcode, bincode, protobuf, etc.) as long as both sides agree

Sources: README.md:50-51 extensions/muxio-rpc-service/src/prebuffered/mod.rs:1-50

Performance Characteristics

AspectText-Based (JSON)Binary (muxio)
Parsing OverheadParse UTF-8, validate syntax, construct ASTDirect byte copying, minimal validation
Payload SizeVerbose keys, quoted strings, escape sequencesCompact type encodings, no metadata
CPU UsageHigh for serialization/deserializationLow, mainly memcpy operations
LatencyHigher due to parsingLower due to binary processing

Sources: README.md:46-47 DRAFT.md11


Cross-Platform Compatibility

Platform-Specific Extensions on a Shared Core

The muxio architecture separates platform-agnostic logic from platform-specific implementations. The core library (muxio) contains all RPC logic, multiplexing, and framing. Platform extensions provide transport bindings:

Sources: README.md:37-41 README.md:48-49

graph TB
    subgraph Shared["Platform-Agnostic Core"]
MuxioCore["muxio crate\nRpcDispatcher, RpcSession, FrameDecoder"]
RpcService["muxio-rpc-service\nRpcMethodPrebuffered trait"]
RpcCaller["muxio-rpc-service-caller\nRpcServiceCallerInterface"]
RpcEndpoint["muxio-rpc-service-endpoint\nRpcServiceEndpointInterface"]
end
    
    subgraph Native["Native Platform (Tokio)"]
TokioClient["muxio-tokio-rpc-client\nRpcClient\ntokio-tungstenite"]
TokioServer["muxio-tokio-rpc-server\nRpcServer\naxum + tokio-tungstenite"]
end
    
    subgraph Browser["Browser Platform (WASM)"]
WasmClient["muxio-wasm-rpc-client\nRpcWasmClient\nwasm-bindgen + js-sys"]
JSBridge["JavaScript Bridge\nstatic_muxio_write_bytes()"]
end
    
    subgraph Application["Application Code"]
ServiceDef["example-muxio-rpc-service-definition\nShared service contracts"]
AppLogic["Application Logic\nSame code for both platforms"]
end
    
 
   MuxioCore --> RpcCaller
 
   MuxioCore --> RpcEndpoint
 
   RpcService --> RpcCaller
 
   RpcService --> RpcEndpoint
    
 
   RpcCaller --> TokioClient
 
   RpcCaller --> WasmClient
 
   RpcEndpoint --> TokioServer
    
 
   TokioClient --> AppLogic
 
   WasmClient --> AppLogic
 
   ServiceDef --> AppLogic
 
   ServiceDef --> RpcService
    
 
   WasmClient --> JSBridge

Write Once, Deploy Everywhere

Because the RpcServiceCallerInterface extensions/muxio-rpc-service-caller/src/caller_interface.rs:1-97 abstracts the underlying transport, application code that calls RPC methods is platform-independent :

The same pattern applies to server-side handlers via RpcServiceEndpointInterface extensions/muxio-rpc-service-endpoint/src/endpoint_interface.rs:1-137 Handlers registered on the endpoint work identically whether the server is Tokio-based or hypothetically implemented for another runtime.

Sources: README.md:48-49 Cargo.toml:20-41

WASM-Specific Considerations

The WASM client (muxio-wasm-rpc-client) demonstrates how the callback-driven core enables browser integration:

  1. No native async runtime : WASM doesn’t have threads or a native async executor. The callback model works directly with JavaScript’s event loop.
  2. Static singleton pattern : Uses thread_local! with RefCell to maintain a global client reference extensions/muxio-wasm-rpc-client/src/static_lib/static_client.rs:10-12
  3. JavaScript bridge : Exposes a single function static_muxio_write_bytes() that JavaScript calls when WebSocket data arrives extensions/muxio-wasm-rpc-client/src/static_lib/mod.rs:63-75

Sources: extensions/muxio-wasm-rpc-client/src/rpc_wasm_client.rs:1-140 extensions/muxio-wasm-rpc-client/src/static_lib/static_client.rs:1-49


Bidirectional and Symmetric Communication

Client-Server Symmetry

Unlike traditional RPC systems where clients can only call servers, muxio treats both sides symmetrically. Every connection has:

This enables:

  • Server-initiated calls : Servers can invoke methods on connected clients
  • Bidirectional streaming : Either side can send data streams
  • Event-driven architectures : Push notifications, real-time updates, etc.

Implementation Details:

Sources: DRAFT.md25 extensions/muxio-tokio-rpc-client/src/rpc_client.rs:30-38 extensions/muxio-tokio-rpc-server/src/rpc_server.rs:41-59


Streaming, Interleaving, and Cancellation

Support for Large Payloads

The multiplexing layer src/rpc/rpc_internals/rpc_session.rs:16-21 enables streaming operations:

Sources: src/rpc/rpc_internals/rpc_session.rs:16-21 src/rpc/rpc_internals/constants.rs:1-5 DRAFT.md:19-21

Cancellation Support

The system supports mid-stream cancellation:

  1. Client-side : Cancel by dropping the response future or explicitly signaling cancellation (implementation-dependent)
  2. Protocol-level : Stream decoders are removed when End or Error events are received src/rpc/rpc_internals/rpc_session.rs:52-120
  3. Resource cleanup : Pending requests are cleared from the dispatcher’s hashmap when completed or errored src/rpc/rpc_dispatcher.rs:265-389

Sources: DRAFT.md21 src/rpc/rpc_dispatcher.rs:265-389 src/rpc/rpc_internals/rpc_session.rs:52-120


Design Trade-offs and Prioritization

What muxio Prioritizes

PriorityRationaleImplementation
PerformanceLow latency and minimal overhead for high-throughput applicationsBinary protocol, zero-copy where possible, compact serialization
Cross-platformSame code works on native and WASMNon-async core, callback-driven model
Type safetyCatch errors at compile time, not runtimeShared service definitions, trait-based contracts
SimplicityEasy to reason about, minimal magicExplicit control flow, no hidden task spawning

What muxio Does Not Prioritize

  • Human readability of wire protocol : The binary format is not human-inspectable (unlike JSON). Debugging requires tooling.
  • Built-in authentication/encryption : Transport security (TLS, authentication) is delegated to the transport layer (e.g., wss:// WebSockets).
  • Schema evolution : No built-in versioning. Breaking changes require careful service definition updates.
  • Automatic code generation : Service definitions are written manually using traits. No macros or code generation (by design, for transparency).

Sources: README.md:42-53 DRAFT.md:9-23


Summary

The muxio design philosophy centers on four pillars:

  1. Runtime agnosticism via non-async, callback-driven primitives
  2. Binary protocol with schemaless flexibility and compile-time type safety
  3. Cross-platform compatibility spanning native (Tokio) and WASM environments
  4. Bidirectional symmetry enabling client-server parity and streaming operations

These choices enable muxio to serve as a high-performance, flexible foundation for distributed systems that require low latency, cross-platform deployment, and type-safe communication.

Sources: README.md:42-53 DRAFT.md:9-52 Cargo.toml:20-41