Skip to main content

deepslate_protocol/packet/
status.rs

1//! Status (server list ping) packets.
2
3use bytes::{Buf, BufMut};
4
5use crate::types::{self, ProtocolError};
6
7use super::Packet;
8
9/// Serverbound status request (packet ID 0x00 in STATUS state).
10/// This packet has no fields.
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct StatusRequestPacket;
13
14impl Packet for StatusRequestPacket {
15    const PACKET_ID: i32 = 0x00;
16
17    fn decode(_buf: &mut impl Buf) -> Result<Self, ProtocolError> {
18        Ok(Self)
19    }
20
21    fn encode(&self, _buf: &mut impl BufMut) {}
22}
23
24/// Clientbound status response (packet ID 0x00 in STATUS state).
25#[derive(Debug, Clone, PartialEq, Eq)]
26pub struct StatusResponsePacket {
27    /// JSON string containing the server status.
28    pub json: String,
29}
30
31impl Packet for StatusResponsePacket {
32    const PACKET_ID: i32 = 0x00;
33
34    fn decode(buf: &mut impl Buf) -> Result<Self, ProtocolError> {
35        let json = types::read_string(buf)?;
36        Ok(Self { json })
37    }
38
39    fn encode(&self, buf: &mut impl BufMut) {
40        types::write_string(buf, &self.json);
41    }
42}
43
44/// Serverbound ping request (packet ID 0x01 in STATUS state).
45#[derive(Debug, Clone, PartialEq, Eq)]
46pub struct PingRequestPacket {
47    /// Arbitrary payload echoed by the server.
48    pub payload: i64,
49}
50
51impl Packet for PingRequestPacket {
52    const PACKET_ID: i32 = 0x01;
53
54    fn decode(buf: &mut impl Buf) -> Result<Self, ProtocolError> {
55        if buf.remaining() < 8 {
56            return Err(ProtocolError::UnexpectedEof);
57        }
58        Ok(Self {
59            payload: buf.get_i64(),
60        })
61    }
62
63    fn encode(&self, buf: &mut impl BufMut) {
64        buf.put_i64(self.payload);
65    }
66}
67
68/// Clientbound pong response (packet ID 0x01 in STATUS state).
69#[derive(Debug, Clone, PartialEq, Eq)]
70pub struct PongResponsePacket {
71    /// The payload echoed from the ping request.
72    pub payload: i64,
73}
74
75impl Packet for PongResponsePacket {
76    const PACKET_ID: i32 = 0x01;
77
78    fn decode(buf: &mut impl Buf) -> Result<Self, ProtocolError> {
79        if buf.remaining() < 8 {
80            return Err(ProtocolError::UnexpectedEof);
81        }
82        Ok(Self {
83            payload: buf.get_i64(),
84        })
85    }
86
87    fn encode(&self, buf: &mut impl BufMut) {
88        buf.put_i64(self.payload);
89    }
90}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95    use proptest::prelude::*;
96
97    proptest! {
98        #[test]
99        fn status_request_roundtrip(packet in Just(StatusRequestPacket)) {
100            let mut buf = Vec::new();
101            packet.encode(&mut buf);
102            let decoded = StatusRequestPacket::decode(&mut &buf[..]).unwrap();
103            prop_assert_eq!(decoded, packet);
104        }
105
106        #[test]
107        fn status_response_roundtrip(json in any::<String>()) {
108            let json = if json.len() > 1024 { json[..1024].to_string() } else { json };
109            let packet = StatusResponsePacket { json };
110            let mut buf = Vec::new();
111            packet.encode(&mut buf);
112            let decoded = StatusResponsePacket::decode(&mut &buf[..]).unwrap();
113            prop_assert_eq!(decoded, packet);
114        }
115
116        #[test]
117        fn ping_request_roundtrip(payload in any::<i64>()) {
118            let packet = PingRequestPacket { payload };
119            let mut buf = Vec::new();
120            packet.encode(&mut buf);
121            let decoded = PingRequestPacket::decode(&mut &buf[..]).unwrap();
122            prop_assert_eq!(decoded, packet);
123        }
124
125        #[test]
126        fn pong_response_roundtrip(payload in any::<i64>()) {
127            let packet = PongResponsePacket { payload };
128            let mut buf = Vec::new();
129            packet.encode(&mut buf);
130            let decoded = PongResponsePacket::decode(&mut &buf[..]).unwrap();
131            prop_assert_eq!(decoded, packet);
132        }
133    }
134}