ax-codec-bytes 0.1.6

Buffer pooling and bytes crate integration for zero-copy operations and memory-efficient encoding
Documentation
# ax-codec-bytes

Buffer pooling and integration with the `bytes` crate for ax-codec. This crate provides memory-efficient buffer management and zero-copy operations with `bytes::Bytes`.

## Features

- **Thread-local buffer pooling** - Reduces allocations for small buffers
- **`bytes` crate integration** - Zero-copy operations with `Bytes` and `BytesMut`
- **`smallvec` integration** - Stack-allocated small vectors (optional)
- **`no_std` compatible** (with `alloc` feature)

## Installation

Add to your `Cargo.toml`:

```toml
[dependencies]
ax-codec-bytes = { version = "0.1", features = ["std"] }
```

### Feature Flags

- `std` - Enables std library support (default)
- `bytes` - Enables integration with `bytes` crate
- `smallvec` - Enables integration with `smallvec` crate

## Thread-Local Buffer Pool

### BufferPool

Thread-local pool for reusing buffers:

```rust
use ax_codec_bytes::{BufferPool, PooledWriter};
use std::sync::Arc;

let pool = Arc::new(BufferPool::new());
let mut writer = PooledWriter::with_pool(pool.clone());

writer.write_all(b"hello").unwrap();
let data = writer.finish(); // Takes ownership, doesn't recycle

// Or recycle explicitly:
let mut writer = PooledWriter::with_pool(pool.clone());
writer.write_all(b"world").unwrap();
writer.recycle(); // Returns buffer to pool
```

### Custom Pool Configuration

```rust
use ax_codec_bytes::BufferPool;

let pool = BufferPool::with_capacity(
    64,    // max buffers in pool
    4096   // default buffer size
);
```

### Pool Statistics

```rust
use ax_codec_bytes::BufferPool;

let pool = BufferPool::new();
println!("Pool size: {}", pool.len());
println!("Pool empty: {}", pool.is_empty());
```

## bytes Crate Integration

### BytesReader

Zero-copy reader for `bytes::Bytes`:

```rust
use ax_codec_bytes::BytesReader;
use ax_codec_core::{Decode, View};
use bytes::Bytes;

let bytes = Bytes::from(b"\x2a\x00\x00\x00");
let mut reader = BytesReader::new(&bytes);

let value: u32 = Decode::decode(&mut reader).unwrap();
println!("Decoded: {}", value);
```

### BytesMutWriter

Writer for `bytes::BytesMut`:

```rust
use ax_codec_bytes::BytesMutWriter;
use ax_codec_core::Encode;

let mut writer = BytesMutWriter::with_capacity(1024);
42u32.encode(&mut writer).unwrap();

let bytes = writer.freeze(); // Convert to immutable Bytes
```

### Decode from Bytes

Helper function for decoding directly from `Bytes`:

```rust
use ax_codec_core::bytes_impl;
use bytes::Bytes;

let mut buf = Bytes::from(&[0x2a, 0x00, 0x00, 0x00][..]);
let value: u32 = bytes_impl::decode_from_bytes(&mut buf).unwrap();
```

### Validate from Bytes

Validate wire format without allocation:

```rust
use ax_codec_core::bytes_impl;
use bytes::Bytes;

let mut buf = Bytes::from(&[0x2a, 0x00, 0x00, 0x00][..]);
bytes_impl::validate_from_bytes::<u32>(&mut buf).unwrap();
```

## smallvec Integration

### SmallVecBuf

Stack-allocated small vectors for zero-allocation small collections:

```rust
use ax_codec_bytes::SmallVecBuf;
use ax_codec_core::{Encode, Decode};
use ax_codec_core::buffer::{VecWriter, SliceReader};

// Encode
let mut writer = VecWriter::new();
let data: SmallVecBuf<[u8; 4]> = SmallVecBuf::from(vec![1, 2, 3]);
data.encode(&mut writer).unwrap();

// Decode
let mut reader = SliceReader::new(writer.as_slice());
let decoded: SmallVecBuf<[u8; 4]> = Decode::decode(&mut reader).unwrap();
```

## Memory Management

### Automatic Recycling

`PooledWriter` automatically recycles its buffer on drop if not explicitly finished:

```rust
use ax_codec_bytes::{BufferPool, PooledWriter};
use std::sync::Arc;

let pool = Arc::new(BufferPool::new());

{
    let mut writer = PooledWriter::with_pool(pool.clone());
    writer.write_all(b"temp data").unwrap();
    // Buffer automatically recycled here
}

assert_eq!(pool.len(), 1); // Buffer returned to pool
```

### Manual Control

Take ownership of the buffer instead of recycling:

```rust
use ax_codec_bytes::{BufferPool, PooledWriter};
use std::sync::Arc;

let pool = Arc::new(BufferPool::new());
let mut writer = PooledWriter::with_pool(pool.clone());
writer.write_all(b"important data").unwrap();

let data = writer.finish(); // Takes ownership, doesn't recycle
assert_eq!(pool.len(), 0); // Buffer not returned to pool
```

## Performance Considerations

### When to Use Pooling

Buffer pooling is beneficial when:
- Creating many small buffers (≤ 64 KB)
- Buffers have similar lifetimes
- You want to reduce heap allocations

### When Not to Use Pooling

Avoid pooling when:
- Buffers are very large (> 64 KB)
- Buffers need to be shared across threads
- Memory pressure is a concern (pool holds onto memory)

### Thread Safety

- `BufferPool` uses `Arc<Mutex<>>` for thread-safe access
- Each thread has its own thread-local pool in ax-codec-core
- Choose based on your use case:
  - `ax-codec-bytes::BufferPool` - Thread-safe, shared pool
  - `ax-codec-core::pool` - Thread-local pool (faster, not shared)

## Examples

### Zero-Copy with Bytes

```rust
use ax_codec_bytes::BytesReader;
use ax_codec_core::View;
use bytes::Bytes;

#[derive(ax_codec_derive::View)]
struct Message<'a> {
    id: u32,
    text: &'a str,
}

let bytes = Bytes::from(&[0x2a, 0x00, 0x00, 0x00, 0x05, b'h', b'e', b'l', b'l', b'o'][..]);
let mut reader = BytesReader::new(&bytes);
let msg = Message::view(&mut reader).unwrap();
println!("ID: {}, Text: {}", msg.id, msg.text);
```

### Efficient Network Buffering

```rust
use ax_codec_bytes::{BufferPool, PooledWriter};
use ax_codec_core::BufferWriter;
use std::sync::Arc;

let pool = Arc::new(BufferPool::with_capacity(32, 8192));

// Reuse buffers for multiple messages
for i in 0..100 {
    let mut writer = PooledWriter::with_pool(pool.clone());
    write_message(i, &mut writer).unwrap();
    
    // Send the buffer
    let data = writer.finish();
    send_to_network(data);
}
```

## License

MIT