use crate::error::PingError;
use crate::varint;
pub const DEFAULT_PROTOCOL_VERSION: i32 = 767;
pub fn build_handshake_packet(
protocol_version: i32,
address: &str,
port: u16,
next_state: i32,
) -> Vec<u8> {
let mut buf = Vec::new();
varint::encode_varint(0x00, &mut buf);
varint::encode_varint(protocol_version, &mut buf);
varint::encode_string(address, &mut buf);
buf.extend_from_slice(&port.to_be_bytes());
varint::encode_varint(next_state, &mut buf);
let mut framed = Vec::new();
varint::encode_varint(buf.len() as i32, &mut framed);
framed.extend_from_slice(&buf);
framed
}
pub fn build_status_request_packet() -> Vec<u8> {
let mut buf = Vec::new();
varint::encode_varint(1, &mut buf);
varint::encode_varint(0x00, &mut buf);
buf
}
pub fn parse_status_response(data: &[u8]) -> Result<(String, usize), PingError> {
if data.is_empty() {
return Err(PingError::Protocol("empty response".to_string()));
}
let (packet_len, offset) = varint::decode_varint(data)?;
if packet_len < 1 {
return Err(PingError::Protocol(format!(
"invalid packet length: {}",
packet_len
)));
}
let body = &data[offset..];
if body.len() < (packet_len as usize) {
return Err(PingError::Protocol(format!(
"packet body too short: expected {}, got {}",
packet_len,
body.len()
)));
}
let (packet_id, pid_offset) = varint::decode_varint(body)?;
if packet_id != 0x00 {
return Err(PingError::Protocol(format!(
"unexpected packet ID: 0x{:02X}, expected 0x00",
packet_id
)));
}
let json_data = &body[pid_offset..];
let (json_str, consumed) = varint::decode_string(json_data)?;
let total_consumed = offset + pid_offset + consumed;
Ok((json_str, total_consumed))
}