### read_handshake_helper! invocation example
Source: https://docs.rs/protocraft_framework/latest/src/protocraft_framework/protocol/mod.rs.html
Example invocation of the read_handshake_helper! macro, showing how to read a handshake packet by reading the version, handling standard, legacy, and pre-1.6 cases, and discarding remaining bytes.
```rust
read_handshake_helper!({
let mut reader = read_stream!();
match read!(HandshakeVersion, reader) {
HandshakeVersion::Standard(bound) => {
with_bound!(reader(bound) => {
let packet_id: i32 = read!(VarInt, reader).into();
if let Some(designator) = S::designator_from_id(packet_id) {
let result = handle_packet!(designator, reader);
discard_remaining!(reader);
result
} else {
Err(ReadError::UnknownPacket {
state: S::STATE_NAME,
id: packet_id,
})
}
})
}
HandshakeVersion::Legacy1_6(bound) => {
with_bound!(reader(bound) => {
let result = handle_packet!(Handshake::Legacy1_6, reader);
discard_remaining!(reader);
result
})
}
HandshakeVersion::Pre1_6 => {
with_bound!(reader(0) => {
let result = handle_packet!(Handshake::Legacy1_5, reader);
discard_remaining!(reader);
result
})
}
}
})
```
--------------------------------
### write_packet_internal_helper Usage
Source: https://docs.rs/protocraft_framework/latest/src/protocraft_framework/protocol/mod.rs.html
Example usage of the write_packet_internal_helper macro to initialize packet writing variables.
```rust
write_packet_internal_helper!((id, packet: PACKET) {
let compression_threshold = threshold!();
let compression_level = level!();
let mut writer = writer!();
let id_varint = VarInt::from(id);
let id_size = id_varint.size();
let packet_size = packet.size();
```
--------------------------------
### pub fn into_next_state(self) -> ProtocolHandler
Source: https://docs.rs/protocraft_framework/latest/protocraft_framework/protocol/struct.ProtocolHandler.html
Transitions the protocol handler to the next protocol state.
```APIDOC
## into_next_state
### Description
Takes this protocol handler to the next state.
### Method
into_next_state
### Signature
pub fn into_next_state(self) -> ProtocolHandler
### Parameters
None
### Returns
- `ProtocolHandler
` - A new protocol handler in the next state.
```
--------------------------------
### pub fn into_login_state(self) -> ProtocolHandler
Source: https://docs.rs/protocraft_framework/latest/protocraft_framework/protocol/struct.ProtocolHandler.html
Transitions the protocol handler from the handshake state to the login state.
```APIDOC
## into_login_state
### Description
Takes this protocol handler from the handshake state to the login state.
### Method
into_login_state
### Signature
pub fn into_login_state(self) -> ProtocolHandler
### Parameters
None
### Returns
- `ProtocolHandler
` - A new protocol handler in the login state.
```
--------------------------------
### ReadError Enum Definition
Source: https://docs.rs/protocraft_framework/latest/protocraft_framework/error/enum.ReadError.html
The complete definition of the ReadError enum with all its variants and fields. This is the primary code example on the page.
```rust
pub enum ReadError {
StreamError(E),
OverSized {
name: &'static str,
maximum: usize,
was: usize,
},
NegativeLength {
name: &'static str,
},
UnknownPacket {
state: &'static str,
id: i32,
},
BadEnum {
name: &'static str,
value: i32,
},
StringDecode {
name: &'static str,
},
MalformedLegacyPing,
Custom {
text: &'static str,
},
}
```
--------------------------------
### pub fn write_legacy_1_6_ping_response(&mut self, response: &Legacy1_6PingResponse) -> Result<(), WriteError< as Writer>::Error>>
Source: https://docs.rs/protocraft_framework/latest/protocraft_framework/protocol/struct.ProtocolHandler.html
Writes a version 1.4-1.6 ping response to the stream.
```APIDOC
## write_legacy_1_6_ping_response
### Description
Writes a version 1.4-1.6 ping response to the stream.
### Method
write_legacy_1_6_ping_response
### Signature
pub fn write_legacy_1_6_ping_response(&mut self, response: &Legacy1_6PingResponse) -> Result<(), WriteError< as Writer>::Error>>
where String: AsRef
### Parameters
- `response` (&Legacy1_6PingResponse) - Required - The ping response to write.
### Returns
- `Result<(), WriteError< as Writer>::Error>>` - Ok if successful, otherwise an error.
```
--------------------------------
### pub fn write_legacy_1_3_ping_response(&mut self, response: &Legacy1_3PingResponse) -> Result<(), WriteError< as Writer>::Error>>
Source: https://docs.rs/protocraft_framework/latest/protocraft_framework/protocol/struct.ProtocolHandler.html
Writes a version 1.3 and previous ping response to the stream.
```APIDOC
## write_legacy_1_3_ping_response
### Description
Writes a version 1.3 and previous ping response to the stream.
### Method
write_legacy_1_3_ping_response
### Signature
pub fn write_legacy_1_3_ping_response(&mut self, response: &Legacy1_3PingResponse) -> Result<(), WriteError< as Writer>::Error>>
where String: AsRef
### Parameters
- `response` (&Legacy1_3PingResponse) - Required - The ping response to write.
### Returns
- `Result<(), WriteError< as Writer>::Error>>` - Ok if successful, otherwise an error.
```
--------------------------------
### _build_protocol_writer macro
Source: https://docs.rs/protocraft_framework/latest/src/protocraft_framework/protocol/versions/mod.rs.html
Generates write_packet and async_write_packet implementations for a protocol handler.
```rust
#[doc(hidden)]
#[macro_export]
macro_rules! _build_protocol_writer {
($state:ident, $reciprocal:ident) => {
impl $crate::protocol::ProtocolHandler {
/// Writes a packet to the stream given a packet type `packet` and the internal packet
/// data `payload`.
pub fn write_packet(
&mut self,
packet: $reciprocal,
payload: &PACKET,
) -> Result<
(),
$crate::error::WriteError< as $crate::traits::Writer>::Error>,
>
where
PACKET: $crate::traits::ToWriter + $crate::traits::Serializable,
{
self.write_packet_internal(packet.id(), payload)
}
}
/// Writes a packet to the stream given a packet type `packet` and the internal packet
/// data `payload`.
#[cfg(feature = "async")]
impl
$crate::protocol::ProtocolHandler
{
pub async fn async_write_packet(
&mut self,
packet: $reciprocal,
payload: &PACKET,
) -> Result<
(),
$crate::error::WriteError<
as $crate::traits::asynchronous::AsyncWriter>::Error,
>,
>
where
PACKET: $crate::traits::asynchronous::AsyncToWriter + $crate::traits::Serializable,
{
self.async_write_packet_internal(packet.id(), payload).await
}
}
};
}
```
--------------------------------
### build_protocol macro
Source: https://docs.rs/protocraft_framework/latest/src/protocraft_framework/protocol/versions/mod.rs.html
High-level macro to define a full protocol version structure including status, login, config, and play states.
```rust
#[macro_export]
macro_rules! build_protocol {
($name:ident($version:literal):
status:
clientbound:
$( $s_c_id:literal => $s_c_name:ident )+
serverbound:
$( $s_s_id:literal => $s_s_name:ident )+
login:
clientbound:
$( $l_c_id:literal => $l_c_name:ident )+
serverbound:
$( $l_s_id:literal => $l_s_name:ident )+
config:
clientbound:
$( $c_c_id:literal => $c_c_name:ident )+
serverbound:
$( $c_s_id:literal => $c_s_name:ident )+
play:
clientbound:
$( $p_c_id:literal => $p_c_name:ident )+
serverbound:
$( $p_s_id:literal => $p_s_name:ident )+
) => {
pub mod $name {
/// The protocol version number
pub const VERSION: u16 = $version;
/// Represents a client in the handshake state
pub enum ClientboundHandshakeState {}
impl $crate::traits::ProtocolState for ClientboundHandshakeState {
const STATE_NAME: &'static str = "clientbound_handshake";
type PacketDesignator = $crate::protocol::Handshake;
fn designator_from_id(_id: i32) -> Option {
None
}
}
/// Represents a server in the handshake state
pub enum ServerboundHandshakeState {}
```
--------------------------------
### pub fn into_status_state(self) -> ProtocolHandler
Source: https://docs.rs/protocraft_framework/latest/protocraft_framework/protocol/struct.ProtocolHandler.html
Transitions the protocol handler from the handshake state to the status state.
```APIDOC
## into_status_state
### Description
Takes this protocol handler from the handshake state to the status state.
### Method
into_status_state
### Signature
pub fn into_status_state(self) -> ProtocolHandler
### Parameters
None
### Returns
- `ProtocolHandler
` - A new protocol handler in the status state.
```
--------------------------------
### pub fn write_raw(&mut self, data: &D) -> Result<(), WriteError< as Writer>::Error>>
Source: https://docs.rs/protocraft_framework/latest/protocraft_framework/protocol/struct.ProtocolHandler.html
Writes raw data to the underlying stream.
```APIDOC
## write_raw
### Description
Writes raw data to the underlying stream.
### Method
write_raw
### Signature
pub fn write_raw(&mut self, data: &D) -> Result<(), WriteError< as Writer>::Error>>
where D: ToWriter
### Parameters
- `data` (&D) - Required - The data to write.
### Returns
- `Result<(), WriteError< as Writer>::Error>>` - Ok if successful, otherwise an error.
```
--------------------------------
### Legacy1_6PingResponse::new
Source: https://docs.rs/protocraft_framework/latest/protocraft_framework/protocol/struct.Legacy1_6PingResponse.html
Creates a new Legacy1_6PingResponse instance for Minecraft versions 1.4-1.6. Returns None if the payload string exceeds 32767 code units.
```APIDOC
## Legacy1_6PingResponse::new
### Description
Creates a ping response for Minecraft versions 1.4-1.6. Returns None if the payload string is greater than 32767 code units.
### Method
Constructor
### Signature
```rust
pub fn new(
server_version: S,
motd: S,
player_count: S,
max_players: S,
) -> Option
```
### Parameters
- **server_version** (S) - Required - The server version string.
- **motd** (S) - Required - The message of the day string.
- **player_count** (S) - Required - The player count string.
- **max_players** (S) - Required - The maximum players string.
### Returns
- **Option** - Returns `Some(Legacy1_6PingResponse)` if the payload string is within the limit, otherwise `None`.
### Example
```rust
let response = Legacy1_6PingResponse::new(
"1.6.4",
"A Minecraft Server",
"0",
"20"
);
```
```
--------------------------------
### Export to_writer_helper macro for sync and async writer implementations
Source: https://docs.rs/protocraft_framework/latest/src/protocraft_framework/primatives/mod.rs.html
Exported macro that simplifies implementing ToWriter and AsyncToWriter for a type. It accepts an optional where clause and an optional wrapped generic list, forwarding to the internal macro for both sync and async (when the "async" feature is enabled) implementations.
```rust
#[macro_export]
macro_rules! to_writer_helper {
($type:path $(where ($($bounds:tt)+))?, ($this:ident){$($func:tt)+}) => {
$crate::_to_writer_helper_internal!(sync $type: bounds: ($($($bounds)+)?), $this {$($func)*});
#[cfg(feature = "async")]
$crate::_to_writer_helper_internal!(async $type: bounds: ($($($bounds)+)?), $this {$($func)*});
};
($type:path $(where ($($bounds:tt)+))?, wrapped <$($generic:ident),+>, ($this:ident){$($func:tt)+}) => {
$crate::_to_writer_helper_internal!(sync $type: bounds: ($($generic: $crate::traits::ToWriter),+ $(,$($bounds)+)?), $this {$($func)+});
#[cfg(feature = "async")]
$crate::_to_writer_helper_internal!(async $type: bounds: ($($generic: $crate::traits::asynchronous::AsyncToWriter),+ $(,$($bounds)+)?), $this {$($func)+});
};
}
```
--------------------------------
### Macro to generate protocol states and writers
Source: https://docs.rs/protocraft_framework/latest/src/protocraft_framework/protocol/versions/mod.rs.html
Defines a macro that takes version and packet ID mappings for status, login, and play states, generating protocol state enums, writer implementations, and handshake state transitions. It also provides constructors for server-side and client-side protocol handlers.
```rust
macro_rules! _build_protocol_version {
(
$name:ident,
$version:literal,
status_clientbound:
$( $s_c_id:literal => $s_c_name:ident )+
status_serverbound:
$( $s_s_id:literal => $s_s_name:ident )+
login_clientbound:
$( $l_c_id:literal => $l_c_name:ident )+
login_serverbound:
$( $l_s_id:literal => $l_s_name:ident )+
play_clientbound:
$( $p_c_id:literal => $p_c_name:ident )+
play_serverbound:
$( $p_s_id:literal => $p_s_name:ident )+
) => {
pub mod $name {
/// The protocol version number
pub const VERSION: u16 = $version;
/// Represents a client in the handshake state
pub enum ClientboundHandshakeState {}
impl $crate::traits::ProtocolState for ClientboundHandshakeState {
const STATE_NAME: &'static str = "clientbound_handshake";
type PacketDesignator = $crate::protocol::Handshake;
fn designator_from_id(_id: i32) -> Option {
None
}
}
/// Represents a server in the handshake state
pub enum ServerboundHandshakeState {}
impl $crate::traits::ProtocolState for ServerboundHandshakeState {
const STATE_NAME: &'static str = "serverbound_handshake";
type PacketDesignator = $crate::protocol::Handshake;
fn designator_from_id(id: i32) -> Option {
if id == 0 {
Some($crate::protocol::Handshake::Standard)
} else {
None
}
}
}
$crate::_build_protocol_state!(ClientboundStatusState, ClientboundStatusPacket, "clientbound_status", $($s_c_id => $s_c_name)+);
$crate::_build_protocol_state!(ServerboundStatusState, ServerboundStatusPacket, "serverbound_status", $($s_s_id => $s_s_name)+);
$crate::_build_protocol_writer!(ClientboundStatusState, ServerboundStatusPacket);
$crate::_build_protocol_writer!(ServerboundStatusState, ClientboundStatusPacket);
$crate::_build_protocol_state!(ClientboundLoginState, ClientboundLoginPacket, "clientbound_login", $($l_c_id => $l_c_name)+);
$crate::_build_protocol_state!(ServerboundLoginState, ServerboundLoginPacket, "serverbound_login", $($l_s_id => $l_s_name)+);
$crate::_build_protocol_writer!(ClientboundLoginState, ServerboundLoginPacket);
$crate::_build_protocol_writer!(ServerboundLoginState, ClientboundLoginPacket);
$crate::_build_protocol_state!(ClientboundPlayState, ClientboundPlayPacket, "clientbound_play", $($p_c_id => $p_c_name)+);
$crate::_build_protocol_state!(ServerboundPlayState, ServerboundPlayPacket, "serverbound_play", $($p_s_id => $p_s_name)+);
$crate::_build_protocol_writer!(ClientboundPlayState, ServerboundPlayPacket);
$crate::_build_protocol_writer!(ServerboundPlayState, ClientboundPlayPacket);
impl $crate::traits::HandshakeProtocolState for ClientboundHandshakeState {
type StatusState = ClientboundStatusState;
type LoginState = ClientboundLoginState;
}
impl $crate::traits::HandshakeProtocolState for ServerboundHandshakeState {
type StatusState = ServerboundStatusState;
type LoginState = ServerboundLoginState;
}
impl $crate::traits::HasNextProtocolState for ClientboundLoginState {
type NextState = ClientboundPlayState;
}
impl $crate::traits::HasNextProtocolState for ServerboundLoginState {
type NextState = ServerboundPlayState;
}
pub fn new_serverside(provider: P) -> $crate::protocol::ProtocolHandler
{
$crate::protocol::ProtocolHandler {
provider,
_x: ::core::marker::PhantomData {}
}
}
pub fn new_clientside
(provider: P) -> $crate::protocol::ProtocolHandler
{
$crate::protocol::ProtocolHandler {
provider,
_x: ::core::marker::PhantomData {}
}
}
}
};
}
```
--------------------------------
### Legacy1_3PingResponse::new
Source: https://docs.rs/protocraft_framework/latest/protocraft_framework/protocol/struct.Legacy1_3PingResponse.html
Creates a ping response for Minecraft versions 1.3 and earlier. Returns None if the payload string is greater than 256 code units.
```APIDOC
## Legacy1_3PingResponse::new
### Description
Creates a ping response for Minecraft versions 1.3 and earlier. Returns None if the payload string is greater than 256 code units.
### Method
`pub fn new(motd: S, player_count: S, max_players: S) -> Option`
### Parameters
- **motd** (S) - Required - The message of the day.
- **player_count** (S) - Required - The current player count.
- **max_players** (S) - Required - The maximum player count.
### Returns
- `Option` - Returns `Some(Legacy1_3PingResponse)` if the payload string is within 256 code units, otherwise `None`.
### Example
```rust
let response = Legacy1_3PingResponse::new("A Minecraft Server", "1", "20");
```
```
--------------------------------
### from_reader_helper macro definition
Source: https://docs.rs/protocraft_framework/latest/protocraft_framework/macro.from_reader_helper.html
Shows the macro_rules! definition for from_reader_helper with two patterns: one for a simple type path and one for a wrapped type with generic parameters.
```rust
macro_rules! from_reader_helper {
($type:path $(where ($($bounds:tt)+))? {$($func:tt)+}) => { ... };
($type:path $(where ($($bounds:tt)+))?, wrapped <$($generic:ident),+> {$($func:tt)+}) => { ... };
}
```
--------------------------------
### Implement Serializable for Option with size, read, and write
Source: https://docs.rs/protocraft_framework/latest/src/protocraft_framework/primatives/option.rs.html
Implements the Serializable trait for Option in the protocraft_framework crate. The size method returns 1 plus the size of the contained value when Some, or 1 when None. Uses the from_reader_helper and to_writer_helper macros to read and write an Option as a boolean flag followed by the value when present.
```rust
use crate::{from_reader_helper, to_writer_helper, traits::Serializable};
impl Serializable for Option
where
T: Serializable,
{
#[inline]
fn size(&self) -> usize {
match self {
Some(val) => 1 + val.size(),
None => 1,
}
}
}
from_reader_helper!(Option, wrapped {
Ok(if read!(bool) {
Some(read!(T))
} else {
None
})
});
to_writer_helper!(Option, wrapped , (this){
match this {
Some(val) => {
write!(bool, true);
write!(T, val);
}
None => {
write!(bool, false);
}
}
Ok(())
});
```
--------------------------------
### Module declarations and internal macros for FromReader/ToWriter
Source: https://docs.rs/protocraft_framework/latest/src/protocraft_framework/primatives/mod.rs.html
Declares submodules and defines internal macros `_from_reader_helper_internal`, `from_reader_helper`, and `_to_writer_helper_internal` to generate `FromReader` and `ToWriter` implementations. The `from_reader_helper` macro supports both sync and async (feature-gated) implementations, and handles generic bounds with the `wrapped` syntax.
```rust
pub mod array;
mod bool;
pub mod handshake_version;
mod option;
mod str;
mod tuple;
pub mod varint;
#[doc(hidden)]
#[macro_export]
macro_rules! _from_reader_helper_internal {
(sync $type:path: bounds: ($($($bound:tt)+)?), {$($func:tt)+}) => {
impl$(<$($bound)+>)? $crate::traits::FromReader for $type {
fn from_reader(reader: &mut R) -> Result>
where
R: $crate::traits::Reader
{
#[allow(unused_macros)]
macro_rules! read_bytes {
($count:literal) => {{
let mut buf = [0u8; $count];
reader.read_exact(&mut buf).map_err($crate::error::ReadError::StreamError)?;
buf
}};
($count:ident) => {{
let mut buf = [0u8; $count];
reader.read_exact(&mut buf).map_err($crate::error::ReadError::StreamError)?;
buf
}};
}
#[allow(unused_macros)]
macro_rules! read {
($read_ty:ty) => {
<$read_ty as $crate::traits::FromReader>::from_reader(reader)?
}
}
#[allow(unused_macros)]
macro_rules! try_read_byte {
() => (reader.try_read_byte().map_err($crate::error::ReadError::StreamError)?)
}
$($func)+
}
}
};
(async $type:path: bounds: ($($($bound:tt)+)?), {$($func:tt)+}) => {
impl$(<$($bound)+>)? $crate::traits::asynchronous::AsyncFromReader for $type {
async fn async_from_reader(
reader: &mut R,
) -> Result>
where
R: $crate::traits::asynchronous::AsyncReader
{
#[allow(unused_macros)]
macro_rules! read_bytes {
($count:literal) => {{
let mut buf = [0u8; $count];
reader.async_read_exact(&mut buf).await.map_err($crate::error::ReadError::StreamError)?;
buf
}};
($count:ident) => {{
let mut buf = [0u8; $count];
reader.async_read_exact(&mut buf).await.map_err($crate::error::ReadError::StreamError)?;
buf
}};
}
#[allow(unused_macros)]
macro_rules! read {
($read_ty:ty) => {
<$read_ty as $crate::traits::asynchronous::AsyncFromReader>::async_from_reader(reader).await?
}
}
#[allow(unused_macros)]
macro_rules! try_read_byte {
() => (reader.async_try_read_byte().await.map_err($crate::error::ReadError::StreamError)?)
}
$($func)+
}
}
};
}
#[macro_export]
macro_rules! from_reader_helper {
($type:path $(where ($($bounds:tt)+))? {$($func:tt)+}) => {
$crate::_from_reader_helper_internal!(sync $type: bounds: ($($($bounds)+)?), {$($func)+});
#[cfg(feature = "async")]
$crate::_from_reader_helper_internal!(async $type: bounds: ($($($bounds)+)?), {$($func)+});
};
($type:path $(where ($($bounds:tt)+))?, wrapped <$($generic:ident),+> {$($func:tt)+}) => {
$crate::_from_reader_helper_internal!(sync $type: bounds: ($($generic: $crate::traits::FromReader),+ $(,$($bounds)+)?), {$($func)+});
#[cfg(feature = "async")]
$crate::_from_reader_helper_internal!(async $type: bounds: ($($generic: $crate::traits::asynchronous::AsyncFromReader),+ $(,$($bounds)+)?), {$($func)+});
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! _to_writer_helper_internal {
(sync $type:path: bounds: ($($($bound:tt)+)?), $this:ident {$($func:tt)+}) => {
impl$(<$($bound)+>)? $crate::traits::ToWriter for $type {
fn to_writer(
&self,
writer: &mut W,
) -> Result<(), $crate::error::WriteError>
where
W: $crate::traits::Writer,
{
#[allow(unused_macros)]
macro_rules! write_bytes {
($bytes:expr) => {
writer
```
--------------------------------
### Implement Serializable for bool with size, read, and write helpers
Source: https://docs.rs/protocraft_framework/latest/src/protocraft_framework/primatives/bool.rs.html
Implements the Serializable trait for bool, defining its serialized size as 1 byte. Uses the from_reader_helper and to_writer_helper macros to read a u8 and interpret non-zero as true, and to write 0x01 for true or 0x00 for false.
```rust
use crate::{from_reader_helper, to_writer_helper, traits::Serializable};
impl Serializable for bool {
#[inline]
fn size(&self) -> usize {
1
}
}
from_reader_helper!(bool {
let byte = read!(u8);
Ok(byte != 0)
});
to_writer_helper!(bool, (this){
let byte = if *this {0x01} else {0x00};
write!(u8, &byte);
Ok(())
});
```
--------------------------------
### FuturesIo adapter implementation for futures-io
Source: https://docs.rs/protocraft_framework/latest/src/protocraft_framework/asynchronous.rs.html
Implements AsyncReader and AsyncWriter for futures_io types. The async_read method copies data to a sink and discards the rest, returning an error if the discard count does not match. The async_write method writes all data and flushes. Requires the 'futures-io' feature.
```rust
impl AsyncWriter for FuturesIo
where
W: AsyncWrite + Unpin,
{
type Error = futures_io::Error;
async fn async_write(&mut self, data: &[u8]) -> Result<(), Self::Error> {
self.0.write_all(data).await?;
Ok(())
}
async fn async_flush(&mut self) -> Result<(), Self::Error> {
self.0.flush().await?;
Ok(())
}
}
```
--------------------------------
### Packet reading helper invocation with compression handling
Source: https://docs.rs/protocraft_framework/latest/src/protocraft_framework/protocol/mod.rs.html
Invokes the read_packet_helper! macro with the body that reads a packet length (max 3-byte VarInt), validates it is non-negative, then reads the packet ID and dispatches to the handler. Handles optional compression: a data_length of 0 means uncompressed, otherwise it decompresses within a bound. Returns ReadError::NegativeLength for negative lengths and ReadError::UnknownPacket for unknown IDs.
```rust
read_packet_helper!({
let compression_threshold = threshold!();
let mut reader = read_stream!();
// 3-Byte VarInts are the maximum allowed for packet lengths
let packet_length: i32 = with_bound!(reader(3) => {
read!(VarInt, reader).into()
});
if packet_length < 0 {
return Err(ReadError::NegativeLength {
name: "packet_length",
});
}
macro_rules! handle_helper {
($stream:ident) => {{
let packet_id: i32 = read!(VarInt, $stream).into();
if let Some(designator) = S::designator_from_id(packet_id) {
let result = handle_packet!(designator, $stream);
discard_remaining!($stream);
result
} else {
Err(ReadError::UnknownPacket {
state: S::STATE_NAME,
id: packet_id,
})
}
}};
}
// SAFETY: We validated that `packet_length` >= 0.
let result = with_bound!(reader(packet_length as usize) => {
match compression_threshold {
Some(_) => {
let data_length: i32 = read!(VarInt, reader).into();
if data_length < 0 {
return Err(ReadError::NegativeLength {
name: "uncompressed_size",
});
}
if data_length == 0 {
// Length of 0 means an uncompressed packet
handle_helper!(reader)
} else {
with_decompression!(reader => {
// SAFETY: We validated that `data_length` >= 0.
with_bound!(reader(data_length as usize) => {
handle_helper!(reader)
})
})
}
}
None => handle_helper!(reader),
}
});
let _ = reader;
result
});
```
--------------------------------
### Asynchronous Packet Writing Macros
Source: https://docs.rs/protocraft_framework/latest/src/protocraft_framework/protocol/mod.rs.html
Macros for handling asynchronous packet writing, including compression and stream management.
```rust
macro_rules! with_pre_compression {
($writer:ident($level:expr) => $p_c_func:tt) => {
{
let (size, data, __writer) = {
use $crate::traits::asynchronous::{AsyncCompressableWriter, AsyncPreCompressionWriter};
let mut $writer = $writer.async_pre_compression_writer($level);
$p_c_func;
$writer.async_finish().await.map_err(WriteError::StreamError)?
};
$writer = __writer;
(size, data)
}
}
}
```
```rust
macro_rules! with_compression {
($writer:ident($level:expr, $payload:ident) => $c_func:tt) => {
{
let __writer = {
use $crate::traits::asynchronous::{AsyncCompressableWriter, AsyncCompressionWriter};
let mut $writer = $writer.with_async_compression($level);
$writer.async_initialize($payload).await.map_err(WriteError::StreamError)?;
$c_func;
$writer.into()
};
$writer = __writer;
}
}
}
```
```rust
macro_rules! write {
($type:ty, $value:ident=> $writer:ident) => (<$type as $crate::traits::asynchronous::AsyncToWriter>::async_to_writer(&$value, &mut $writer).await?)
}
```
```rust
macro_rules! write_bytes {
($bytes:expr => $writer:ident) => {{
use $crate::traits::asynchronous::AsyncWriter;
$writer.async_write($bytes).await.map_err(WriteError::StreamError)?
}}
}
```
```rust
macro_rules! flush {
($writer:ident) => {{
use $crate::traits::asynchronous::AsyncWriter;
$writer.async_flush().await.map_err(WriteError::StreamError)?
}}
}
```
--------------------------------
### Generate primitive serialization for all standard types
Source: https://docs.rs/protocraft_framework/latest/src/protocraft_framework/primatives/mod.rs.html
Instantiates the build_primative macro for all standard Rust primitive types with their byte sizes. This generates the serialization implementations for u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, f32, and f64.
```rust
build_primative!(u8, 1);
build_primative!(i8, 1);
build_primative!(u16, 2);
build_primative!(i16, 2);
build_primative!(u32, 4);
build_primative!(i32, 4);
build_primative!(u64, 8);
build_primative!(i64, 8);
build_primative!(u128, 16);
build_primative!(i128, 16);
build_primative!(f32, 4);
build_primative!(f64, 8);
```
--------------------------------
### _build_protocol_state macro
Source: https://docs.rs/protocraft_framework/latest/src/protocraft_framework/protocol/versions/mod.rs.html
Defines a protocol state and its associated packet designator enum, implementing the ProtocolState trait.
```rust
#[doc(hidden)]
#[macro_export]
macro_rules! _build_protocol_state {
($state:ident, $state_designator:ident, $state_name:literal, $($id:literal => $packet_name:ident)+) => {
/// The specific protocol state
pub enum $state {}
/// The packets that are avaliable in the specific protocol state
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum $state_designator {
$(
$packet_name
),+
}
impl $crate::traits::ProtocolState for $state {
const STATE_NAME: &'static str = $state_name;
type PacketDesignator = $state_designator;
fn designator_from_id(id: i32) -> Option {
match id {
$(
$id => Some($state_designator::$packet_name),
)+
_ => None
}
}
}
impl $state_designator {
/// Returns the associated packet id for the packet type
pub const fn id(&self) -> i32 {
match self {
$(
Self::$packet_name => $id
),+
}
}
}
}
}
```
--------------------------------
### Implement Serializable for str with size and to_writer helper
Source: https://docs.rs/protocraft_framework/latest/src/protocraft_framework/primatives/str.rs.html
Defines the Serializable trait implementation for str, providing a size method that returns the string length and a to_writer helper that writes the string's bytes. The to_writer_helper macro is used to generate the write logic.
```rust
use crate::{to_writer_helper, traits::Serializable};
impl Serializable for str {
fn size(&self) -> usize {
self.len()
}
}
to_writer_helper!(str, (this) {
write_bytes!(this.as_bytes());
Ok(())
});
```
--------------------------------
### Token I/O adapter for tokio AsyncRead and AsyncWrite
Source: https://docs.rs/protocraft_framework/latest/src/protocraft_framework/asynchronous.rs.html
Implements the AsyncReader and AsyncWriter traits for a generic wrapper around types that implement tokio's AsyncRead and AsyncWrite. This prevents trait conflicts when both tokio-io and futures-io features are enabled. This module is only compiled when the 'tokio-io' feature is active.
```rust
#[cfg(feature = "tokio-io")]
mod tokio {
use core::{
future::Future,
task::{Context, Poll, Waker},
time::Duration,
};
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
use crate::traits::asynchronous::{AsyncReader, AsyncWriter};
/// Wrapper type for types that implement tokio `AsyncRead` or `AsyncWrite` to prevent
/// conflicts when all features are used
pub struct TokioIo(pub S);
impl From for TokioIo {
fn from(value: S) -> Self {
TokioIo(value)
}
}
impl AsyncReader for TokioIo
where
R: AsyncRead + Unpin,
{
type Error = tokio::io::Error;
async fn async_read_exact(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
self.0.read_exact(buf).await?;
Ok(())
}
async fn async_try_read_byte(&mut self) -> Result, Self::Error> {
// FIXME: Is there a better way to do this than sleeping to ensure all bytes have been sent
// over the network? This function is only used once during the handshake.
tokio::time::sleep(Duration::from_millis(5)).await;
let waker = Waker::noop();
let mut context = Context::from_waker(waker);
let future = self.0.read_u8();
tokio::pin!(future);
match future.poll(&mut context) {
Poll::Pending => Ok(None),
Poll::Ready(result) => result.map(Some),
}
}
async fn async_discard(&mut self, amount: usize) -> Result<(), Self::Error> {
if amount != 0 {
let amount = amount as u64;
let mut reader = (&mut self.0).take(amount);
let amount_discarded = tokio::io::copy(&mut reader, &mut tokio::io::sink()).await?;
if amount_discarded != amount {
return Err(tokio::io::Error::new(
tokio::io::ErrorKind::UnexpectedEof,
"EOF while discarding",
));
}
}
Ok(())
}
}
impl AsyncWriter for TokioIo
where
W: AsyncWrite + Unpin,
{
type Error = tokio::io::Error;
async fn async_write(&mut self, data: &[u8]) -> Result<(), Self::Error> {
self.0.write_all(data).await?;
Ok(())
}
async fn async_flush(&mut self) -> Result<(), Self::Error> {
self.0.flush().await?;
Ok(())
}
}
}
```
--------------------------------
### read_handshake_helper macro definition with sync and async implementations
Source: https://docs.rs/protocraft_framework/latest/src/protocraft_framework/protocol/mod.rs.html
Defines the read_handshake_helper macro that generates both synchronous and asynchronous read_handshake methods. It uses internal macros like read_stream!, with_bound!, handle_packet!, read!, and discard_remaining! to abstract stream reading and packet processing. The async version uses the 'async' feature and async traits.
```rust
macro_rules! read_stream {
() => (self.provider.read_stream())
}
macro_rules! with_bound {
($reader:ident($bound:expr) => $bound_func:tt) => {{
let mut $reader = $reader.with_bound($bound);
$bound_func
}};
}
macro_rules! handle_packet {
($designator:expr, $reader:ident) => (H::handle_packet($designator, &mut $reader))
}
macro_rules! read {
($type:ty, $reader:ident) => (<$type as $crate::traits::FromReader>::from_reader(&mut $reader)?)
}
macro_rules! discard_remaining {
($reader:ident) => {{
use $crate::traits::Reader;
let remaining = $reader.remaining();
$reader.discard(remaining).map_err(ReadError::StreamError)?;
}}
}
$($func)+
```
```rust
macro_rules! read_stream {
() => (self.provider.async_read_stream())
}
macro_rules! with_bound {
($reader:ident($bound:expr) => $bound_func:tt) => {
{
let (result, __reader) = {
use $crate::traits::asynchronous::AsyncBoundableDecompressableReader;
let mut $reader = $reader.with_bound($bound);
let result = $bound_func;
(result, $reader)
};
$reader = __reader.into();
allow_unused!($reader);
result
}
};
}
macro_rules! handle_packet {
($designator:expr, $reader:ident) => (H::async_handle_packet($designator, &mut $reader).await)
}
macro_rules! read {
($type:ty, $reader:ident) => (<$type as $crate::traits::asynchronous::AsyncFromReader>::async_from_reader(&mut $reader).await?)
}
macro_rules! discard_remaining {
($reader:ident) => {{
use $crate::traits::asynchronous::{AsyncReader, AsyncBoundedReader};
let remaining = $reader.async_remaining().await;
$reader.async_discard(remaining).await.map_err(ReadError::StreamError)?;
}}
}
$($func)+
```
--------------------------------
### write_packet_internal_helper! macro definition with compression macros
Source: https://docs.rs/protocraft_framework/latest/src/protocraft_framework/protocol/mod.rs.html
Defines the write_packet_internal_helper! macro that generates an impl block for ProtocolHandler with a write_packet_internal method. The method takes a packet ID and a reference to a packet type that implements ToWriter and Serializable, and returns a Result with WriteError. Inside, it defines local macros for compression threshold, level, writer stream, pre-compression writer, and compression writer.
```rust
macro_rules! write_packet_internal_helper {
(($id:ident, $packet:ident: $packet_type:ident) {$($func:tt)+}) => {
impl
ProtocolHandler
{
#[allow(unused)]
fn write_packet_internal<$packet_type>(
&mut self,
id: i32,
packet: &$packet_type,
) -> Result<(), WriteError< as $crate::traits::Writer>::Error>>
where
$packet_type: $crate::traits::ToWriter + $crate::traits::Serializable,
{
macro_rules! threshold {
() => (self.provider.compression_threshold())
}
macro_rules! level {
() => (self.provider.compression_level())
}
macro_rules! writer {
() => (self.provider.write_stream())
}
macro_rules! with_pre_compression {
($writer:ident($level:expr) => $p_c_func:tt) => {
{
let mut $writer = $writer.pre_compression_writer($level);
$p_c_func;
$writer.finish().map_err(WriteError::StreamError)?
}
}
}
macro_rules! with_compression {
($writer:ident($level:expr, $payload:ident) => $c_func:tt) => {
```
--------------------------------
### Compression enum and module exports in protocraft_framework defaults
Source: https://docs.rs/protocraft_framework/latest/src/protocraft_framework/defaults/mod.rs.html
Defines the `Compression` enum with three variants: `None`, `SpeedOptimized`, and `Variable(u8)`. The `Default` implementation returns `Variable(4)`. The `Into` conversion maps `None` to 0, `SpeedOptimized` to 1, and `Variable(x)` to `10.max(2 + x)`. The module also conditionally exports `sync` under the `defaults` feature and always exports `asynchronous`.
```rust
#[cfg(feature = "defaults")]
pub mod sync;
pub mod asynchronous;
/// Detemines how much compression to use.
/// `None` is no compression.
/// `SpeedOptimized` uses a special compression scheme optimized for speed.
/// `Variable` takes a value from 0-8 where 0 is the fastest compression with the worst compression
/// and 8 is the best compression with the worst speed.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Compression {
None,
SpeedOptimized,
Variable(u8),
}
impl Default for Compression {
fn default() -> Self {
Self::Variable(4)
}
}
#[allow(clippy::from_over_into)]
impl Into for Compression {
fn into(self) -> u8 {
match self {
Self::None => 0,
Self::SpeedOptimized => 1,
Self::Variable(x) => 10.max(2 + x),
}
}
}
```
--------------------------------
### CompressionWriter
Source: https://docs.rs/protocraft_framework/latest/src/protocraft_framework/traits.rs.html
A Writer that receives the exact same calls to write prior to a CompressionWriter. finish is called to obtain a payload used to initialize a CompressionWriter.
```APIDOC
## CompressionWriter
### Description
A `Writer` that receives the exact same calls to `Self::write` prior to a `CompressionWriter`. `Self::finish` will be called and its returned `Self::Payload` will be used to initialize a `CompressionWriter`. If a `no-alloc` environment is used, this can be useful to compress the data into a sink to calculate the compressed size in order to serialize the compressed length before actually serializing the compressed data.
### Associated Types
- **Payload** - The payload returned by `finish` used to initialize a `CompressionWriter`.
### Methods
#### finish
- **Signature**: `fn finish(self) -> Self::Payload`
- **Description**: Finalizes the writer and returns the payload used to initialize a `CompressionWriter`.
- **Returns**: `Self::Payload` - The payload for initializing a `CompressionWriter`.
```
--------------------------------
### Compression enum definition
Source: https://docs.rs/protocraft_framework/latest/protocraft_framework/defaults/enum.Compression.html
Defines the compression levels for protocraft_framework. None disables compression, SpeedOptimized uses a speed-optimized scheme, and Variable takes a value from 0 to 8 where 0 is fastest with worst compression and 8 is best compression with worst speed.
```rust
pub enum Compression {
None,
SpeedOptimized,
Variable(u8),
}
```
--------------------------------
### pub fn provider(&self) -> &P
Source: https://docs.rs/protocraft_framework/latest/protocraft_framework/protocol/struct.ProtocolHandler.html
Returns an immutable reference to the underlying stream provider.
```APIDOC
## provider
### Description
Returns an immutable reference to the underlying stream provider.
### Method
provider
### Signature
pub fn provider(&self) -> &P
### Parameters
None
### Returns
- `&P` - Immutable reference to the stream provider.
```
--------------------------------
### Internal macros for async packet reading (handle_packet, read, discard_remaining)
Source: https://docs.rs/protocraft_framework/latest/src/protocraft_framework/protocol/mod.rs.html
Defines three internal macros used by the packet reading helper: handle_packet delegates to the handler's async method, read converts a type from the reader using AsyncFromReader, and discard_remaining consumes any leftover bytes in the stream. These macros are invoked within the read_packet_helper! expansion.
```rust
macro_rules! handle_packet {
($designator:expr, $reader:ident) => (H::async_handle_packet($designator, &mut $reader).await)
}
macro_rules! read {
($type:ty, $reader:ident) => (<$type as $crate::traits::asynchronous::AsyncFromReader>::async_from_reader(&mut $reader).await?)
}
macro_rules! discard_remaining {
($reader:ident) => {{
use $crate::traits::asynchronous::{AsyncReader, AsyncBoundedReader};
let remaining = $reader.async_remaining().await;
$reader.async_discard(remaining).await.map_err(ReadError::StreamError)?;
}}
}
```