Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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:

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.