use std::fmt;
use serde::{Deserialize, Serialize};
use crate::error::McError;
#[derive(Serialize, Deserialize, Clone)]
pub struct BedrockStatus {
pub edition: String,
pub motd: String,
pub protocol_version: String,
pub version: String,
pub online_players: u32,
pub max_players: u32,
pub server_uid: String,
pub motd2: String,
pub game_mode: String,
pub game_mode_numeric: String,
pub port_ipv4: Option<u16>,
pub port_ipv6: Option<u16>,
pub map: Option<String>,
pub software: Option<String>,
pub raw_data: String,
}
impl BedrockStatus {
#[doc(hidden)]
pub fn parse_test(data: &str) -> Result<Self, crate::McError> {
Self::parse(data)
}
pub(crate) fn parse(data: &str) -> Result<Self, McError> {
let parts: Vec<&str> = data.split(';').collect();
if parts.len() < 6 {
return Err(McError::invalid_response(format!(
"bedrock response has {} fields, need ≥ 6",
parts.len()
)));
}
Ok(BedrockStatus {
edition: parts[0].into(),
motd: parts[1].into(),
protocol_version: parts[2].into(),
version: parts[3].into(),
online_players: parts[4]
.parse()
.map_err(|_| McError::invalid_response("bad online_players"))?,
max_players: match parts[5] {
"unlimited" => u32::MAX,
s => s.parse()
.map_err(|_| McError::invalid_response("bad max_players"))?,
},
server_uid: parts.get(6).copied().unwrap_or("").into(),
motd2: parts.get(7).copied().unwrap_or("").into(),
game_mode: parts.get(8).copied().unwrap_or("").into(),
game_mode_numeric: parts.get(9).copied().unwrap_or("").into(),
port_ipv4: parts.get(10).and_then(|s| s.parse().ok()),
port_ipv6: parts.get(11).and_then(|s| s.parse().ok()),
map: parts.get(12).map(|s| s.to_string()),
software: parts.get(13).map(|s| s.to_string()),
raw_data: data.into(),
})
}
}
impl fmt::Debug for BedrockStatus {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("BedrockStatus")
.field("edition", &self.edition)
.field("motd", &self.motd)
.field("protocol_version", &self.protocol_version)
.field("version", &self.version)
.field("online_players", &self.online_players)
.field("max_players", &self.max_players)
.field("server_uid", &self.server_uid)
.field("motd2", &self.motd2)
.field("game_mode", &self.game_mode)
.field("game_mode_numeric", &self.game_mode_numeric)
.field("port_ipv4", &self.port_ipv4)
.field("port_ipv6", &self.port_ipv6)
.field("map", &self.map)
.field("software", &self.software)
.field("raw_data_len", &self.raw_data.len())
.finish()
}
}