What is Sans-IO?
Sans-IO (French for "without I/O") is an architectural pattern for writing protocol implementations that are completely decoupled from I/O operations. This makes protocols:
- Testable: Test protocol logic without mocking sockets or async runtimes
- Portable: Run the same protocol code in sync, async, embedded, or WASM environments
- Composable: Stack and combine protocol layers easily
- Debuggable: Step through protocol state machines without I/O side effects
Features
- Clean push-pull API for message handling
- Zero-cost abstractions with generic type parameters
- Support for custom events and timeout handling
- Works with any I/O backend (sync, async, embedded)
- No dependencies, minimal footprint
- Fully documented with examples
no_stdby default - works in any environment
no_std Support
This crate is no_std by default and works seamlessly in any environment - embedded systems,
bare-metal applications, WASM, or standard applications.
Time Handling
The Time associated type is fully generic, so you can use any time representation that fits
your environment:
Using std::time::Instant:
Using tick counts (embedded):
Using milliseconds:
No timeout needed:
The Protocol Trait
The Protocol trait provides a simplified Sans-IO interface for building network protocols:
Quick Start
Add sansio to your Cargo.toml:
[]
= "1"
Example: Uppercase Protocol
A simple protocol that converts incoming strings to uppercase:
use Protocol;
use VecDeque;
;
/// A simple uppercase protocol: converts incoming strings to uppercase
// Usage example
Testing Made Easy
Sans-IO protocols are trivial to test because they don't involve any I/O:
Use Cases
- Network Protocols: HTTP, WebSocket, custom TCP/UDP protocols
- Message Parsers: Protocol buffers, JSON-RPC, custom formats
- State Machines: Connection handling, handshakes, negotiations
- Protocol Testing: Unit test protocol logic without network I/O
- Embedded Systems: Protocols that need to work with both blocking and non-blocking I/O
- WASM: Browser-based protocol implementations
Why Sans-IO?
Traditional protocol implementations mix I/O and protocol logic:
// Traditional approach - tightly coupled to async I/O
async
Sans-IO separates concerns:
// Sans-IO approach - protocol logic is independent
// I/O layer is separate and can be swapped
async
Benefits:
- Protocol logic can be tested without async runtime
- Same protocol works with sync, async, or embedded I/O
- Easier to debug and reason about
- Protocol layers can be composed and reused
Documentation
Full API documentation is available at docs.rs/sansio
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.