rs-netty 1.1.0

A Tokio-native typed TCP/UDP pipeline framework inspired by Netty.
Documentation
# Codecs

Codecs sit at pipeline boundaries. Stream codecs are for TCP byte streams; datagram codecs are for UDP datagrams.

## Stream Codec Traits

```rust
pub trait Decoder: Send + 'static {
    type Item: Send + 'static;
    fn decode(&mut self, src: &mut bytes::BytesMut) -> Result<Option<Self::Item>>;
}

pub trait Encoder<I>: Send + 'static {
    fn encode(&mut self, item: I, dst: &mut bytes::BytesMut) -> Result<()>;
}
```

`decode` should consume bytes only when a complete frame is available and return `Some(item)`. It returns `Ok(None)` when more bytes are needed.

## Datagram Codec Traits

```rust
pub trait DatagramDecoder: Send + 'static {
    type Item: Send + 'static;
    fn decode_datagram(&mut self, src: &[u8]) -> Result<Self::Item>;
}

pub trait DatagramEncoder<I>: Send + 'static {
    fn encode_datagram(&mut self, item: I, dst: &mut bytes::BytesMut) -> Result<()>;
}
```

A UDP decoder receives one complete datagram payload at a time.

## Built-In Stream Codecs

- `LineCodec`: UTF-8 newline-delimited stream codec; decoding strips `\n` and optional `\r`, encoding appends `\n`.
- `ByteArrayDecoder`: drains the current buffer into `Bytes`; it can also encode `Bytes`.
- `ByteArrayEncoder`: pass-through `Bytes` encoder.
- `FixedLengthFrameDecoder`: fixed-size binary frame codec; encoding requires the exact configured length.
- `DelimiterBasedFrameDecoder`: delimiter-terminated binary frame codec; can keep or strip delimiters.
- `LengthFieldBasedFrameDecoder`: Netty-shaped length-field frame decoder with 1/2/3/4/8 byte fields, offset, adjustment, strip count, and byte order. As an encoder, it supports only zero offset and zero adjustment.
- `LengthFieldPrepender`: `Bytes` encoder that prepends a length field.
- `HttpCodec`: minimal HTTP/1.1 server codec; decodes requests and encodes responses. Supports `Content-Length` and optional chunked request bodies.
- `MqttCodec`: MQTT 5 packet codec for fixed headers, Remaining Length, properties, and supported control packets. It does not maintain broker/client session state.
- `WebSocketCodec`: available with the `websocket` feature; server-side WebSocket codec that transitions from HTTP Upgrade handshake state to frame state.
- `HttpWsCodec`: available with the `websocket` feature; handles HTTP requests and WebSocket upgrades on one TCP port.

## Built-In Datagram Codecs

- `Utf8DatagramCodec`: treats every datagram as one UTF-8 `String`.
- `BytesDatagramCodec`: treats every datagram as raw `bytes::Bytes`.

## JSON Is A Pipeline Stage

`JsonDecode<T>` and `JsonEncode<T>` are available with the `json` feature. They are typed pipeline stages, not framing codecs:

```rust
let pipeline = pipeline()
    .codec(LineCodec::new())
    .inbound(JsonDecode::<Request>::new())
    .handler(ApiHandler)
    .outbound(JsonEncode::<Response>::new());
```

This keeps framing separate from JSON parsing/serialization. `LineCodec` defines message boundaries, `JsonDecode<T>` converts `String`/`Bytes` into `T`, and `JsonEncode<T>` converts `T` into a compact JSON `String`.

## Codec Position

The codec is always the first required builder stage. It decides the initial inbound type and the final outbound type the pipeline must produce.

For example:

```rust
pipeline()
    .codec(LineCodec::new())          // Decoder<Item = String>, Encoder<String>
    .inbound(ParseRequest)            // String -> Request
    .handler(Router)                  // Request -> writes Response
    .outbound(RenderResponse);        // Response -> String
```

Without `RenderResponse`, `LineCodec` cannot encode `Response`, so the pipeline fails to compile.