pcobs 1.0.0

Binary encoding for structured data communication
Documentation
<div align="center">

# πŸ“¦ pcobs

**postcard + crc + cobs = structured data over anything**

[![Crates.io](https://img.shields.io/crates/v/pcobs)](https://crates.io/crates/pcobs)
[![Documentation](https://docs.rs/pcobs/badge.svg)](https://docs.rs/pcobs)
[![Rust](https://img.shields.io/badge/rust-1.83%2B-orange.svg)](https://www.rust-lang.org)
[![no_std](https://img.shields.io/badge/no__std-support-brightgreen.svg)](https://github.com/rust-embedded/wg)
[![zero-alloc](https://img.shields.io/badge/alloc--free-brightgreen.svg)](https://github.com/rust-embedded/wg)

**`no_std` β€’ zero-allocation β€’ embedded-ready**

</div>

---

## πŸ’‘ Why?

You've got structs. You need to send them over UART/TCP/USB/whatever.

**pcobs** gives you:
- πŸ“ **postcard** β€” compact serde serialization, `no_std` friendly
- πŸ” **CRC-16** β€” catch corrupted packets
- 🧱 **COBS framing** β€” zero-byte delimiters, no escaping hell
- πŸ’Ύ **Zero allocations** β€” stack-only, no `Vec`/`Box`/`HashMap`
- ⚑ **`no_std`** β€” works on bare-metal, no OS required

Two functions. That's it.

```rust
let len = serialize(&my_struct, &mut buf)?;
let my_struct = deserialize::<MyStruct>(&mut buf, len)?;
```

---

## πŸš€ Quick Start

```toml
[dependencies]
pcobs = "1"
serde = { version = "1", features = ["derive"] }
```

```rust
use pcobs::{serialize, deserialize};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
struct SensorData {
    id: u8,
    value: f32,
    flags: u16,
}

// Sender
let data = SensorData { id: 1, value: 23.5, flags: 0xABCD };
let mut buf = [0u8; 256];
let len = serialize(&data, &mut buf)?;
stream.write_all(&buf[..len])?;
stream.write_all(&[0x00])?; // COBS delimiter

// Receiver
let mut buf = [0u8; 256];
let n = read_until_delimiter(stream, &mut buf)?;
let decoded: SensorData = deserialize(&mut buf, n)?;
```

---

## πŸ“ Packet Format

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”
β”‚ Payload                     β”‚ CRC-16   β”‚ 0x00 β”‚
β”‚ postcard(your data)         β”‚ checksum β”‚      β”‚
│────────────────────────────────────────│      β”‚
β”‚ COBS frame                             β”‚ delimβ”‚
β”‚ no zeros in encoded data               β”‚      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”˜
```
Steps:
1. Serialize your struct with **postcard**
2. Append **CRC-16** checksum (2 bytes)
3. COBS-encode the whole thing
4. Send over your transport, appending a **0x00** delimiter

---

## πŸ“ Buffer Math

Encoding is done **in-place** - no buffer splitting needed. COBS adds minimal overhead (at most 1 byte per 254 bytes), plus 2 bytes for CRC.

| Buffer | Max Payload |
|--------|-------------|
| 64 B   | ~60 B       |
| 256 B  | ~252 B      |
| 512 B  | ~508 B      |
| 1024 B | ~1018 B     |

---

## πŸ› οΈ Transport Agnostic

Works over anything that moves bytes:

- πŸ“‘ UART / Serial
- 🌐 TCP sockets
- πŸ”Œ USB bulk endpoints
- πŸ“» Radio (LoRa, BLE, etc.)
- πŸ§ͺ Pipes / files for testing

---

## ⚑ Features

- **`no_std`** β€” works on bare-metal, no OS required
- **Zero allocations** β€” stack-only, no heap, embedded-friendly
- `serde` β€” derive your structs
- Single-pass encoding
- In-place decoding