Expand description
A Rust implementation of the Advanced Navigation Packet Protocol.
The Advanced Navigation Packet Protocol is a low-overhead communication protocol designed mainly for embedded systems. It provides a mechanism for breaking a stream of data into packets (framing) while ensuring data integrity via CRC-16 checksums.
§Examples
Each Packet
is essentially a collection of bytes with an associated ID.
The communication protocol is transport-agnostic (it doesn’t care if
you’re using RS-232, ethernet, smoke signals, etc), you just create a
Packet
and write it to a buffer that can be handed off to the
underlying transport mechanism.
// create a packet
let pkt = Packet::with_data(42, b"A very important message")?;
// then write it to an internal buffer
let mut buffer = [0; 512];
let bytes_written = pkt.write_to_buffer(&mut buffer)?;
// and finally, you can send the information using your actual transport
// mechanism. In this case, RS-232.
send_serial_message(&buffer[..bytes_written])?;
In order to read a message on the other side, you’ll need a Decoder
.
The idea is you write raw data into the Decoder
and it’ll keep returning
DecodeError::RequiresMoreData
until it has received a complete packet.
// create the decoder
let mut dec = Decoder::new();
// then read some data
let data = read_data_from_serial();
// next you need to copy the data into the decoder
dec.push_data(&data)?;
// Now the decoder has some bytes to work with, we can read back our packet
let pkt = dec.decode()?;
assert_eq!(pkt.id(), 42);
assert_eq!(pkt.contents(), b"A very important message");
§Feature Flags
The std
feature flag enables several nice-to-have features, including:
- Implementations of
std::error::Error
for all error types - The
Decoder
will use a dynamically sized buffer which can resize when it is full instead of throwing an error - You can use the
std::io::Write
trait to write data into theDecoder
andPacket
- A
write_to()
method is added toPacket
, allowing you to write thePacket
directly to anything that implementsstd::io::Write
An example of using std::io::Write
with a Packet
:
use std::io::Write;
// open our serial port again
let mut port = open_serial_port("/dev/TTYUSB1");
// then create a packet
let mut pkt = Packet::with_data(42, b"This is a very important message")?;
// oops, we forgot to finish the sentence!
pkt.write(b".")?;
// now encode the packet and write it out over RS-232
pkt.write_to(&mut port)?;
Likewise, std::io::Write
makes it easy to work with a decoder.
use std::io;
let mut dec = Decoder::new();
let mut serial = open_serial_port("/dev/TTYUSB0");
// `std::io::copy()` copies all data from a Reader to a Writer
let bytes_read = io::copy(&mut serial, &mut dec)?;
let pkt = dec.decode()?;
assert_eq!(pkt.id(), 42);
Modules§
- errors
- All error types used in this crate.