use bytes::{Bytes, BytesMut};
use crate::codec::{Decode, DecodeResult, Encode, EncodeResult, McWrite, decode_exact};
use crate::error::DecodeError;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum State {
Handshaking,
Status,
Login,
Play,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Direction {
Clientbound,
Serverbound,
}
pub trait Packet: Encode + Decode {
const ID: i32;
const NAME: &'static str;
const STATE: State;
const DIRECTION: Direction;
}
pub trait PacketSet: Sized {
const STATE: State;
const DIRECTION: Direction;
fn decode_raw(raw: &RawPacket) -> DecodeResult<Self>;
fn id(&self) -> i32;
fn name(&self) -> &'static str;
fn encode_body(&self, w: &mut BytesMut) -> EncodeResult;
fn name_of(id: i32) -> Option<&'static str>;
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RawPacket {
pub id: i32,
pub body: Bytes,
}
impl RawPacket {
#[inline]
pub fn new(id: i32, body: Bytes) -> Self {
RawPacket { id, body }
}
#[inline]
pub fn decode_as<P: Packet>(&self) -> DecodeResult<P> {
if self.id != P::ID {
return Err(DecodeError::IdMismatch {
expected: P::ID,
actual: self.id,
});
}
decode_exact(&self.body)
}
pub fn from_packet<P: Packet>(p: &P) -> Result<Self, crate::error::EncodeError> {
let mut w = BytesMut::new();
p.encode(&mut w)?;
Ok(RawPacket::new(P::ID, w.freeze()))
}
}
#[inline]
pub fn write_packet<P: Packet>(p: &P, w: &mut BytesMut) -> EncodeResult {
w.put_varint(P::ID);
p.encode(w)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct PacketFilter {
bits: [u64; 4],
}
impl Default for PacketFilter {
fn default() -> Self {
Self::all()
}
}
impl PacketFilter {
pub const fn all() -> Self {
PacketFilter {
bits: [u64::MAX; 4],
}
}
pub const fn none() -> Self {
PacketFilter { bits: [0; 4] }
}
#[must_use]
pub const fn with(mut self, id: i32) -> Self {
if id >= 0 && id < 256 {
self.bits[(id as usize) >> 6] |= 1 << (id & 63);
}
self
}
#[must_use]
pub const fn without(mut self, id: i32) -> Self {
if id >= 0 && id < 256 {
self.bits[(id as usize) >> 6] &= !(1 << (id & 63));
}
self
}
pub fn insert(&mut self, id: i32) {
*self = self.with(id);
}
pub fn remove(&mut self, id: i32) {
*self = self.without(id);
}
#[inline]
pub const fn contains(&self, id: i32) -> bool {
if id < 0 || id >= 256 {
return true;
}
self.bits[(id as usize) >> 6] & (1 << (id & 63)) != 0
}
#[inline]
pub const fn is_all(&self) -> bool {
self.bits[0] == u64::MAX
&& self.bits[1] == u64::MAX
&& self.bits[2] == u64::MAX
&& self.bits[3] == u64::MAX
}
}
pub trait Version: Copy + Send + Sync + 'static {
const PROTOCOL: i32;
const NAME: &'static str;
const POSITION_LAYOUT: crate::types::PositionLayout;
type HandshakingServerbound: PacketSet;
type StatusClientbound: PacketSet;
type StatusServerbound: PacketSet;
type LoginClientbound: PacketSet;
type LoginServerbound: PacketSet;
type PlayClientbound: PacketSet;
type PlayServerbound: PacketSet;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn filter() {
let f = PacketFilter::none().with(0x21).with(200);
assert!(f.contains(0x21) && f.contains(200) && !f.contains(0x22));
assert!(f.contains(300) && f.contains(-1));
assert!(PacketFilter::all().is_all() && !f.is_all());
assert!(!PacketFilter::all().without(5).contains(5));
}
}