1use bytes::{Bytes, BytesMut};
4
5use crate::codec::{Decode, DecodeResult, Encode, EncodeResult, McWrite, decode_exact};
6use crate::error::DecodeError;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10#[non_exhaustive]
11pub enum State {
12 Handshaking,
14 Status,
16 Login,
18 Play,
20}
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
24pub enum Direction {
25 Clientbound,
27 Serverbound,
29}
30
31pub trait Packet: Encode + Decode {
33 const ID: i32;
35 const NAME: &'static str;
37 const STATE: State;
39 const DIRECTION: Direction;
41}
42
43pub trait PacketSet: Sized {
45 const STATE: State;
47 const DIRECTION: Direction;
49
50 fn decode_raw(raw: &RawPacket) -> DecodeResult<Self>;
52 fn id(&self) -> i32;
54 fn name(&self) -> &'static str;
56 fn encode_body(&self, w: &mut BytesMut) -> EncodeResult;
58 fn name_of(id: i32) -> Option<&'static str>;
60}
61
62#[derive(Debug, Clone, PartialEq, Eq)]
66pub struct RawPacket {
67 pub id: i32,
69 pub body: Bytes,
71}
72
73impl RawPacket {
74 #[inline]
76 pub fn new(id: i32, body: Bytes) -> Self {
77 RawPacket { id, body }
78 }
79
80 #[inline]
82 pub fn decode_as<P: Packet>(&self) -> DecodeResult<P> {
83 if self.id != P::ID {
84 return Err(DecodeError::IdMismatch {
85 expected: P::ID,
86 actual: self.id,
87 });
88 }
89 decode_exact(&self.body)
90 }
91
92 pub fn from_packet<P: Packet>(p: &P) -> Result<Self, crate::error::EncodeError> {
94 let mut w = BytesMut::new();
95 p.encode(&mut w)?;
96 Ok(RawPacket::new(P::ID, w.freeze()))
97 }
98}
99
100#[inline]
102pub fn write_packet<P: Packet>(p: &P, w: &mut BytesMut) -> EncodeResult {
103 w.put_varint(P::ID);
104 p.encode(w)
105}
106
107#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
113pub struct PacketFilter {
114 bits: [u64; 4],
115}
116
117impl Default for PacketFilter {
118 fn default() -> Self {
119 Self::all()
120 }
121}
122
123impl PacketFilter {
124 pub const fn all() -> Self {
126 PacketFilter {
127 bits: [u64::MAX; 4],
128 }
129 }
130
131 pub const fn none() -> Self {
133 PacketFilter { bits: [0; 4] }
134 }
135
136 #[must_use]
138 pub const fn with(mut self, id: i32) -> Self {
139 if id >= 0 && id < 256 {
140 self.bits[(id as usize) >> 6] |= 1 << (id & 63);
141 }
142 self
143 }
144
145 #[must_use]
147 pub const fn without(mut self, id: i32) -> Self {
148 if id >= 0 && id < 256 {
149 self.bits[(id as usize) >> 6] &= !(1 << (id & 63));
150 }
151 self
152 }
153
154 pub fn insert(&mut self, id: i32) {
156 *self = self.with(id);
157 }
158
159 pub fn remove(&mut self, id: i32) {
161 *self = self.without(id);
162 }
163
164 #[inline]
166 pub const fn contains(&self, id: i32) -> bool {
167 if id < 0 || id >= 256 {
168 return true;
169 }
170 self.bits[(id as usize) >> 6] & (1 << (id & 63)) != 0
171 }
172
173 #[inline]
175 pub const fn is_all(&self) -> bool {
176 self.bits[0] == u64::MAX
177 && self.bits[1] == u64::MAX
178 && self.bits[2] == u64::MAX
179 && self.bits[3] == u64::MAX
180 }
181}
182
183pub trait Version: Copy + Send + Sync + 'static {
189 const PROTOCOL: i32;
191 const NAME: &'static str;
193 const POSITION_LAYOUT: crate::types::PositionLayout;
195
196 type HandshakingServerbound: PacketSet;
198 type StatusClientbound: PacketSet;
200 type StatusServerbound: PacketSet;
202 type LoginClientbound: PacketSet;
204 type LoginServerbound: PacketSet;
206 type PlayClientbound: PacketSet;
208 type PlayServerbound: PacketSet;
210}
211
212#[cfg(test)]
213mod tests {
214 use super::*;
215
216 #[test]
217 fn filter() {
218 let f = PacketFilter::none().with(0x21).with(200);
219 assert!(f.contains(0x21) && f.contains(200) && !f.contains(0x22));
220 assert!(f.contains(300) && f.contains(-1));
221 assert!(PacketFilter::all().is_all() && !f.is_all());
222 assert!(!PacketFilter::all().without(5).contains(5));
223 }
224}