rs-netty 1.1.0

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

rs-netty is not a direct port of Java Netty. Its goal is to take the useful pipeline/handler/channel model and express it in a Rust-native way.

## Keep The Useful Shape

The framework keeps these concepts:

- codecs sit at pipeline boundaries and convert between bytes/datagrams and typed messages.
- inbound stages process decoded inbound messages.
- final handlers implement application semantics and write application-level responses.
- outbound stages convert handler writes into values the codec can encode.
- channel handles can write, flush, or close from outside the current handler.
- lifecycle hooks can observe server, connection, and UDP socket startup/shutdown.

## Use Rust Types Instead Of Dynamic Pipeline Mutation

Java Netty's dynamic pipeline is flexible, but many mistakes show up at runtime: handlers are in the wrong order, upstream message types do not match downstream handlers, or a TCP pipeline is used with UDP. rs-netty encodes these constraints in builder types:

```text
codec -> inbound* -> business* -> handler -> outbound*
```

Only methods that are valid in the current state exist. For example, `.handler(...)` is unavailable before `.codec(...)`; `.inbound(...)` is unavailable after `.handler(...)`; and the final outbound type must be encodable by the selected codec.

The repository's trybuild tests cover these failure modes, including:

- `fail_stream_handler_before_codec.rs`
- `fail_stream_outbound_before_handler.rs`
- `fail_stream_type_mismatch_inbound_to_handler.rs`
- `fail_stream_final_encoder_mismatch.rs`
- `fail_udp_with_stream_pipeline.rs`
- `fail_tcp_with_datagram_pipeline.rs`

## Separate TCP And UDP Builders

TCP uses `pipeline()` and requires codecs to implement `Decoder` and `Encoder<T>`. UDP uses `datagram_pipeline()` and requires codecs to implement `DatagramDecoder` and `DatagramEncoder<T>`.

This is a type boundary, not just a naming convention. `TcpServer::pipeline` accepts only `IntoStreamPipeline`; `UdpServer::pipeline` accepts only `IntoDatagramPipeline`. Mixing TCP and UDP pipeline builders fails at compile time.

## Prefer Owned Messages

The public API does not expose Java Netty-style reference-counted `ByteBuf`. Codecs and handlers use owned types such as `String`, `bytes::Bytes`, and user-defined structs. This fits Rust ownership and avoids ref-count lifetime mistakes.

## Bounded Queues And Explicit Flush

`Channel` and `DatagramChannel` use bounded Tokio `mpsc` queues internally. `outbound_queue_size` controls the external command queue size. When the queue is full, write calls wait for capacity instead of growing without bound.

Write and flush are explicit:

- `write` only queues or stages data.
- `flush` pushes already staged data to the socket.
- `write_and_flush` writes and creates a flush boundary.

This lets throughput-oriented code batch writes while latency-oriented code can flush explicitly.

## Zero Unsafe

The crate root uses `#![deny(unsafe_code)]`, and `rs-netty-macros` does the same. The current library and macro crate do not use `unsafe` on the main implementation path.