rs-netty 1.1.0

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

The main path has four layers: transport, pipeline runtime, stage traits, and channel/context.

## Crate Layout

- `src/lib.rs`: public modules and common re-exports.
- `src/traits.rs`: `Inbound`, `Business`, `Handler`, `DatagramHandler`, `Outbound`, and `Flow`.
- `src/pipeline/stream`: TCP typed builder and runtime pipeline.
- `src/pipeline/datagram`: UDP typed builder and runtime pipeline.
- `src/pipeline/core`: shared `Identity`, `Then`, stage pipe traits, and builder state markers.
- `src/codec`: stream/datagram codec traits and built-in codecs.
- `src/context`: stage contexts, handler contexts, stats, and identity types.
- `src/channel`: external write handles and internal command enums.
- `src/tls.rs`: optional TLS context builders and server/client contexts behind the `tls` feature.
- `src/transport/tcp`: TCP server, client, connection runtime, and config.
- `src/transport/udp`: UDP server, client, socket runtime, and config.
- `src/life.rs`: lifecycle hook trait and close reasons.
- `rs-netty-macros`: the `#[handler]` attribute macro.

## TCP Runtime Flow

A TCP server calls the pipeline factory once for each accepted connection. A client can use either a reusable factory or `pipeline_instance`, which consumes one single-use pipeline.

The runtime flow is roughly:

```text
TcpListener / TcpStream
  -> optional TLS accept/connect
  -> read_buf
  -> Decoder::decode
  -> InboundPipe
  -> BusinessPipe
  -> Handler::read(Context<W>, msg)
  -> Context outbox or Channel command queue
  -> OutboundPipe
  -> Encoder::encode
  -> write_buf
  -> flush/write_all
```

`StreamConnectionRuntime` selects over socket reads, external channel commands, and shutdown signals. Without an idle timeout it uses a no-timeout loop. With `idle_timeout`, it adds a read-idle timer. The timer is reset only by socket reads; outbound writes do not reset it.

## UDP Runtime Flow

UDP servers and clients run around one socket task. The pipeline is socket-level:

```text
UdpSocket::recv_from
  -> DatagramDecoder::decode_datagram
  -> InboundPipe
  -> BusinessPipe
  -> DatagramHandler::read(DatagramContext<W>, msg)
  -> DatagramContext outbox or DatagramChannel command queue
  -> OutboundPipe
  -> DatagramEncoder::encode_datagram
  -> pending_datagrams
  -> flush/send_to
```

A UDP server does not currently create per-peer child pipelines. If you need per-peer state, store it in the handler explicitly, for example with `HashMap<SocketAddr, State>`.

## Static Stage Composition

The builder composes stages at the type level as `Then<A, B>`. `Identity` means that a direction has no user stages. Runtime `InboundPipe`, `BusinessPipe`, and `OutboundPipe` process `Then` recursively:

- `Flow::Next(value)` forwards the value to the next stage.
- `Flow::Stop` stops processing the current message direction without treating it as an error.
- `Err` is mapped by the connection/socket runtime into decode, encode, handler, or runtime errors.

The main path does not use dynamic `Box<dyn Handler>` pipeline dispatch. Pipeline types are built from generic static stage composition.

## Channel And Context

`Context<W>` and `DatagramContext<W>` are the write entry points inside final handlers. They hold a handler-local outbox, which is useful for multiple writes and explicit flush boundaries during one read.

`Channel<W>` and `DatagramChannel<W>` are cloneable external handles. They send commands to the connection/socket task through a bounded Tokio `mpsc` queue. TCP channels expose `stats()`, `capacity()`, `max_capacity()`, and `is_closed()`; UDP channels expose socket identity and queue state.