#byte #overhead #buffer #cobs #stuffing #encode-decode

no-std cobs-rs

A minimal no-std library for doing Consistent Overhead Byte Stuffing

5 stable releases

1.1.2 Jul 29, 2022
1.1.1 Mar 25, 2021
1.1.0 Mar 17, 2021
1.0.1 Mar 11, 2021

#335 in Embedded development

29 downloads per month
Used in corncobs

MIT license

24KB
313 lines

COBS-RS

GitHub docs.rs

A very minimal no_std Consistent Overhead Byte Stuffing library written in Rust. The COBS algorithm, and thus also this crate, provides an encoding for arbitrary data which removes any occurrence of a specific marker byte. This is mostly useful when we are transferring arbitrary data which is terminated with a null byte, and therefore we don't want our arbitrary data buffer to contain any null bytes. In fact, this crate will automatically append the marker byte at the end of any encoded buffer.

Take a look at the documentation.

Features

The cobs-rs crate only provides two specific functions. Namely, the stuff and the unstuff function, which encode and decode respectively. This, together with the fact that the crate doesn't use the std, makes the crate perfect for embedded hardware. However, it can also be used outside of embedded systems.

Usage

Both the encode(stuff) and decode(unstuff) functions, use const generics. This may make usage a bit counter-intuitive for people unfamiliar with this feature at first.

Something to take into account here is that the COBS algorithm will at most add 2 + (size of input buffer / 256) (with integer division) bytes to the encoded buffer in size compared to input buffer. This fact allows us to always reserve enough space for the output buffer.

Encoding buffers

Let us have a look at a small example of how to encode some data using the stuff function.

let data: [u8; 254] = [
    // ...snip
];

// Our input buffer is 254 bytes long.
// Thus, we need to reserve 2 + (254 / 256) = 2 extra bytes
// for the encoded buffer.
let encoded: [u8; 256] = cobs_rs::stuff(data, 0x00);

// We can also encode much larger buffers
let a_lot_of_data: [u8; 1337] = [
    // ...snip
];

// Our input buffer is 1337 bytes long.
// Thus, we need to reserve 2 + (1337 / 256) = 7 extra bytes
// for the encoded buffer.
let a_lot_of_output: [u8; 1344] = cobs_rs::stuff(a_lot_of_data, 0x00);

Note: The output buffer type specifications are always necessary. The type specifications for the input data isn't necessary most of the time.

Decoding buffers

Now, let us look at an example of how to decode data using the unstuff function.

It is generally a good idea to reserve size of encoded buffer - 2 bytes for the decoded buffer. With this rule, we will always have enough space for the encoded buffer. Next to the decoded buffer, the unstuff function will also return the actual filled size of the buffer.

// We are given some encoded data buffer
let encoded_data: [u8; 256] = [
    //... snip
];

// We reserve 256 - 2 = 254 bytes for the decoded buffer.
let (decoded_data: [u8; 254], decoded_data_length) =
    cobs_rs::unstuff(encoded_data, 0x00);

// We can also decode bigger buffers
let a_lot_of_encoded_data: [u8; 1344] = [
    //... snip
];

// We reserve 1344 - 2 = 1342 bytes for the decoded buffer.
let (a_lot_of_decoded_data: [u8; 1342], a_lot_of_decoded_data_length) =
    cobs_rs::unstuff(encoded_data, 0x00);

Note: The decoded buffer type specifications are always necessary. The type specifications for the encoded data isn't necessary most of the time.

License

Licensed under a MIT license.

No runtime deps