Expand description
§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. This is achieved
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" cargo run --release --example benchmarkExample results on a AMD Ryzen 5 3600 CPU (64 byte frames, 5 million frames):
--- Benchmark: random bytes ---
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
--- Benchmark: ASCII-only bytes ---
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 slipstream::{decode_frame, encode_frame, Result};
fn main() -> Result<()> {
let frame = encode_frame(b"hello");
let payload = decode_frame(&frame)?;
assert_eq!(payload, b"hello");
Ok(())
}Run cargo run --example basic for a complete program.
§Streaming I/O
use slipstream::{SlipReader, SlipWriter, Result};
use std::io::Cursor;
fn main() -> Result<()> {
let mut writer = SlipWriter::new(Vec::new());
writer.write_frame(b"ping")?;
writer.write_frame(b"pong")?;
let encoded = writer.into_inner();
let mut reader = SlipReader::new(Cursor::new(encoded));
while let Some(frame) = reader.read_frame()? {
println!("Frame: {:?}", frame);
}
Ok(())
}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 aslipstream::async_codec::SlipCodecimplementing theasynchronous_codectraits for runtime-agnostic async I/O.tokio-codecenables aslipstream::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 benchmarkTo 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.
Structs§
- Frame
Remainder - Captures decoded bytes that were buffered when a stream ended without a
terminating
ENDbyte. - Slip
Reader - Reader wrapper that decodes SLIP frames from an underlying byte stream.
- Slip
Writer - Writer wrapper that encodes outgoing frames as SLIP before forwarding them to the underlying writer.
Enums§
- Slip
Error - Error type for SLIP encoding and decoding operations.
Constants§
- END
- SLIP END byte (0xC0).
- ESC
- SLIP ESC byte (0xDB).
- ESC_END
- SLIP ESC END byte (0xDC).
- ESC_ESC
- SLIP ESC ESC byte (0xDD).
Functions§
- decode_
frame - Decode a single SLIP frame from the provided bytes.
- decode_
frames - Decode all SLIP frames contained in the provided byte slice.
- decode_
frames_ iter - Decode all SLIP frames produced by the given iterator over bytes.
- decode_
frames_ iter_ with_ remainder - Iterator variant of
decode_frames_with_remainder. - decode_
frames_ with_ remainder - Decode SLIP frames and also return any buffered remainder when the input ends without a trailing
END. - decoded_
lengths - Determine the decoded length of each SLIP frame in the provided input without materialising the payloads.
- decoded_
lengths_ iter - Iterator variant of
decoded_lengths. - encode_
frame - Encode arbitrary bytes as a SLIP frame and return the encoded data as a newly allocated
Vec. - encode_
into_ writer - Encode bytes as SLIP and write the result directly into the provided writer.
- encode_
iter - Encode an arbitrary iterator of bytes as a SLIP frame and return the encoded data.
- encoded_
len - Compute the encoded length (including the trailing
ENDdelimiter) without allocating.
Type Aliases§
- Result
- Convenient result alias used throughout the crate.