SLIPspeed

A pure-Rust implementation of the Serial Line Internet Protocol (SLIP) encoder and decoder with support for in-memory buffers as well as streaming I/O.
The crate exposes convenience helpers for encoding and decoding byte slices as well as SlipWriter and SlipReader wrappers for any std::io::Write or std::io::Read implementor.
A C/C++ port of this library, focused on embedded systems, is available at libslipstream, (but sadly, the slipstream crate name on crates.io is already taken).
Performance
SLIPspeed attempts to be as fast as the speed of light will allow.
Generally, passing more than one byte at a time can improve performance by reducing the overhead of multiple function calls and allowing for better optimization by utilizing memchr to quickly locate special characters in the input data. This approach uses vectorized instructions and efficient memory scanning techniques to process larger chunks of data in a single operation, leading to significant speed improvements compared to processing one byte at a time.
The integrated benchmark encodes ASCII fraes random frames of varying lengths and reports throughput for encoding and decoding. Performance is higher for ASCII frames, as random frames may include lots of characters that need escaping. To run the benchmark example:
RUSTFLAGS="-C target-cpu=native"
Example results on a AMD Ryzen 5 3600 CPU (64 byte frames, 5 million frames):
Frames processed: 5000000
Encoded bytes: 650000616
Encoding took: 697.361468ms (139.47 ns/frame)
Encoding throughput: 932.09 MB/s
Decoding took: 908.336552ms (181.67 ns/frame)
Decoding throughput: 715.59 MB/s
Frames processed: 5000000
Encoded bytes: 645000000
Encoding took: 226.643427ms (45.33 ns/frame)
Encoding throughput: 2845.88 MB/s
Decoding took: 488.094976ms (97.62 ns/frame)
Decoding throughput: 1321.46 MB/s
Frame Structure
SLIP is specified in RFC 1055 and uses the following conventions:
- Frames are delimited by the byte
0xC0(END). - Literal
ENDbytes in the payload are escaped as the two-byte sequence0xDB 0xDC(ESC,ESC_END). - Literal escape bytes
0xDB(ESC) are encoded as0xDB 0xDD(ESC,ESC_ESC). - The decoder clears its buffer whenever it encounters an
END, emitting the accumulated payload as a frame.
Note: This implementation does not add or verify any checksums. If you require integrity checks, consider adding a CRC or similar mechanism to your payloads.
In contrast to the simple_slip crate, we do not add extra END bytes before a frame. This allows for more efficient streaming scenarios where frames are sent back-to-back.
Quick Start
use ;
Run cargo run --example basic for a complete program.
Streaming I/O
use ;
use Cursor;
See examples/stream.rs for the full example.
Utilities
encode_frame,decode_frames, anddecode_frames_with_remainderfor slice-based workflows.encoded_lenanddecoded_lengthsto inspect frame sizes without materialising payloads.SlipReader::read_frame_lengthandSlipReader::take_remainderfor streaming scenarios that require sizing or recovery after truncated input.
Cargo Features
async-codecenables aslipspeed::async_codec::SlipCodecimplementing theasynchronous_codectraits for runtime-agnostic async I/O.tokio-codecenables aslipspeed::tokio_codec::SlipCodeccompatible withtokio_util::codecFramed adapters.
Additional Examples
cargo run --example async_codec --features async-codecdemonstrates the runtime-agnosticasynchronous_codecintegration.cargo run --example tokio_codec --features tokio-codecshowcases usage with Tokio'sduplexstreams andtokio_util::codec::Framed.cargo run --example benchmarkperforms a reproducible encoding and decoding micro-benchmark over pseudo-random frames.
Benchmark example
The examples/benchmark.rs program performs a reproducible micro-benchmark using a fixed-seed
LCG (Linear Congruential Generator). By default it generates a large number of small random
frames and reports:
- total frames processed
- total encoded bytes
- wall-clock time for encoding and decoding
- per-frame average (ns/frame)
This example is intended as a simple throughput sanity check rather than a rigorous benchmark (it prints elapsed times to stdout). To run the example:
cargo run --example benchmark
To make the example quicker during development, lower the FRAME_COUNT constant at the
top of the example file (for example to 20_000). The RNG seed is fixed (0xDEADBEEF)
for reproducible runs.