use crate::codec::{decode_u16, encode_u16, Codec, CodecError, CodecResult, Reader};
use std::fmt::Debug;
use std::io;
use std::io::{Read, Write};
use std::sync::atomic::{AtomicU16, Ordering};
#[derive(Debug)]
pub enum PacketError {
CodecError(CodecError),
IO(io::Error),
}
impl From<CodecError> for PacketError {
fn from(err: CodecError) -> Self {
PacketError::CodecError(err)
}
}
impl From<io::Error> for PacketError {
fn from(err: io::Error) -> Self {
PacketError::IO(err)
}
}
pub type PacketResult<T> = Result<T, PacketError>;
#[derive(Debug)]
pub struct EmptyContent {}
impl Codec for EmptyContent {
fn encode(&self, _: &mut Vec<u8>) {}
fn decode(_: &mut Reader) -> CodecResult<Self> {
Ok(EmptyContent {})
}
}
impl PacketContent for EmptyContent {}
pub trait PacketContent: Codec + Debug {}
pub trait PacketComponent: Debug + Eq + PartialEq {
fn component(&self) -> u16;
fn command(&self) -> u16;
fn from_value(value: u16) -> Self;
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PacketType {
Request,
Response,
Notify,
Error,
Unknown(u16),
}
impl PacketType {
pub fn value(&self) -> u16 {
match self {
PacketType::Request => 0x0000,
PacketType::Response => 0x1000,
PacketType::Notify => 0x2000,
PacketType::Error => 0x3000,
PacketType::Unknown(value) => *value,
}
}
pub fn from_value(value: u16) -> PacketType {
match value {
0x0000 => PacketType::Request,
0x1000 => PacketType::Response,
0x2000 => PacketType::Notify,
0x3000 => PacketType::Error,
value => PacketType::Unknown(value),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PacketHeader {
pub component: u16,
pub command: u16,
pub error: u16,
pub ty: PacketType,
pub id: u16,
}
impl PacketHeader {
pub fn encode_bytes(&self, length: usize) -> Vec<u8> {
let mut header = Vec::with_capacity(12);
let is_extended = length > 0xFFFF;
encode_u16(&(length as u16), &mut header);
encode_u16(&self.component, &mut header);
encode_u16(&self.command, &mut header);
encode_u16(&self.error, &mut header);
header.push((self.ty.value() >> 8) as u8);
header.push(if is_extended { 0x10 } else { 0x00 });
encode_u16(&self.id, &mut header);
if is_extended {
header.push(((length & 0xFF000000) >> 24) as u8);
header.push(((length & 0x00FF0000) >> 16) as u8);
}
header
}
pub fn read<R: Read>(input: &mut R) -> PacketResult<(PacketHeader, usize)>
where
Self: Sized,
{
let mut header = [0u8; 12];
input.read_exact(&mut header)?;
let mut length = decode_u16(&header[0..2])? as usize;
let component = decode_u16(&header[2..4])?;
let command = decode_u16(&header[4..6])?;
let error = decode_u16(&header[6..8])?;
let q_type = decode_u16(&header[8..10])?;
let id = decode_u16(&header[10..12])?;
if q_type & 0x10 != 0 {
let mut buffer = [0; 2];
input.read_exact(&mut buffer)?;
let ext_length = u16::from_be_bytes(buffer);
length += (ext_length as usize) << 16;
}
let ty = PacketType::from_value(q_type);
let header = PacketHeader {
component,
command,
error,
ty,
id,
};
Ok((header, length))
}
}
#[derive(Debug)]
pub struct Packet<C: PacketContent>(PacketHeader, C);
pub struct Packets {}
impl Packets {
pub fn response<C: PacketContent>(packet: &OpaquePacket, contents: C) -> Packet<C> {
let mut header = packet.0.clone();
header.ty = PacketType::Response;
Packet(header, contents)
}
#[inline]
pub fn response_empty(packet: &OpaquePacket) -> Packet<EmptyContent> {
Self::response(packet, EmptyContent {})
}
pub fn error<C: PacketContent>(
packet: &OpaquePacket,
error: impl Into<u16>,
contents: C,
) -> Packet<C> {
let mut header = packet.0.clone();
header.error = error.into();
header.ty = PacketType::Error;
Packet(header, contents)
}
#[inline]
pub fn error_empty(packet: &OpaquePacket, error: impl Into<u16>) -> Packet<EmptyContent> {
Self::error(packet, error, EmptyContent {})
}
pub fn notify<C: PacketContent>(component: impl PacketComponent, contents: C) -> Packet<C> {
Packet(
PacketHeader {
component: component.component(),
command: component.command(),
error: 0,
ty: PacketType::Notify,
id: 0,
},
contents,
)
}
#[inline]
pub fn notify_empty(component: impl PacketComponent) -> Packet<EmptyContent> {
Self::notify(component, EmptyContent {})
}
pub fn request<R: RequestCounter, C: PacketContent>(
counter: &mut R,
component: impl PacketComponent,
contents: C,
) -> Packet<C> {
Packet(
PacketHeader {
component: component.component(),
command: component.command(),
error: 0,
ty: PacketType::Request,
id: counter.next(),
},
contents,
)
}
}
impl<C: PacketContent> Packet<C> {
pub fn read<R: Read>(input: &mut R) -> PacketResult<Packet<C>>
where
Self: Sized,
{
let (header, length) = PacketHeader::read(input)?;
let mut contents = vec![0u8; length];
input.read_exact(&mut contents)?;
let mut reader = Reader::new(&contents);
let contents = C::decode(&mut reader)?;
Ok(Packet(header, contents))
}
pub fn write<W: Write>(&self, output: &mut W) -> io::Result<()>
where
Self: Sized,
{
let content = self.1.encode_bytes();
let header = self.0.encode_bytes(content.len());
output.write_all(&header)?;
output.write_all(&content)?;
Ok(())
}
}
impl<C: PacketContent> TryInto<Packet<C>> for OpaquePacket {
type Error = CodecError;
fn try_into(self) -> Result<Packet<C>, Self::Error> {
let contents = self.contents::<C>()?;
Ok(Packet(self.0, contents))
}
}
#[derive(Debug)]
pub struct OpaquePacket(pub PacketHeader, pub Vec<u8>);
impl OpaquePacket {
pub fn contents<R: PacketContent>(&self) -> CodecResult<R> {
let mut reader = Reader::new(&self.1);
R::decode(&mut reader)
}
pub fn read<R: Read>(input: &mut R) -> PacketResult<Self>
where
Self: Sized,
{
let (header, length) = PacketHeader::read(input)?;
let mut contents = vec![0u8; length];
input.read_exact(&mut contents)?;
Ok(Self(header, contents))
}
}
pub trait RequestCounter {
fn next(&mut self) -> u16;
}
pub struct SimpleCounter {
value: u16,
}
impl SimpleCounter {
pub fn new() -> SimpleCounter {
SimpleCounter { value: 0 }
}
}
impl RequestCounter for SimpleCounter {
fn next(&mut self) -> u16 {
self.value += 1;
self.value
}
}
pub struct AtomicCounter {
value: AtomicU16,
}
impl AtomicCounter {
pub fn new() -> AtomicCounter {
AtomicCounter {
value: AtomicU16::new(0),
}
}
}
impl RequestCounter for AtomicCounter {
fn next(&mut self) -> u16 {
self.value.fetch_add(1, Ordering::AcqRel)
}
}
#[cfg(test)]
mod test {
use crate::packet::{OpaquePacket, Packet, Packets};
use crate::types::VarInt;
use crate::{define_components, packet};
use std::io::Cursor;
packet! {
struct Test {
TEST: String,
ALT: VarInt,
AA: u32,
}
}
define_components! {
Authentication (0x0) {
First (0x1)
Second (0x2)
Third (0x3)
}
Other (0x1) {
First (0x1)
Second (0x2)
Third (0x3)
}
}
#[test]
fn test() {
let contents = Test {
TEST: String::from("Test"),
ALT: VarInt(0),
AA: 32,
};
println!("{:?}", contents);
let packet = Packets::notify(components::Authentication::Second, contents);
println!("{packet:?}");
let mut out = Cursor::new(Vec::new());
packet.write(&mut out).unwrap();
let bytes = out.get_ref();
println!("{bytes:?}");
let mut bytes_in = Cursor::new(bytes);
let packet_in = OpaquePacket::read(&mut bytes_in).unwrap();
println!("{packet_in:?}");
let packet_in_dec: Packet<Test> = packet_in.try_into().unwrap();
println!("{packet_in_dec:?}");
assert_eq!(packet.0, packet_in_dec.0)
}
}