use bytes::{Buf, BufMut};
use crate::types::{self, ProtocolError};
use crate::varint;
use super::Packet;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HandshakeIntent {
Status = 1,
Login = 2,
Transfer = 3,
}
impl HandshakeIntent {
pub fn from_id(id: i32) -> Result<Self, ProtocolError> {
match id {
1 => Ok(Self::Status),
2 => Ok(Self::Login),
3 => Ok(Self::Transfer),
_ => Err(ProtocolError::InvalidData(format!(
"unknown handshake intent: {id}"
))),
}
}
}
#[derive(Debug, Clone)]
pub struct HandshakePacket {
pub protocol_version: i32,
pub server_address: String,
pub server_port: u16,
pub next_state: HandshakeIntent,
}
impl Packet for HandshakePacket {
const PACKET_ID: i32 = 0x00;
fn decode(buf: &mut impl Buf) -> Result<Self, ProtocolError> {
let protocol_version = varint::read_var_int(buf)?;
let server_address = types::read_string_max(buf, 255)?;
if buf.remaining() < 2 {
return Err(ProtocolError::UnexpectedEof);
}
let server_port = buf.get_u16();
let next_state_id = varint::read_var_int(buf)?;
let next_state = HandshakeIntent::from_id(next_state_id)?;
Ok(Self {
protocol_version,
server_address,
server_port,
next_state,
})
}
fn encode(&self, buf: &mut impl BufMut) {
varint::write_var_int(buf, self.protocol_version);
types::write_string(buf, &self.server_address);
buf.put_u16(self.server_port);
varint::write_var_int(buf, self.next_state as i32);
}
}