use crate::protocols::{gamespy, minecraft, quake, valve};
use crate::{GDError::InvalidInput, GDResult};
use std::time::Duration;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub enum ProprietaryProtocol {
TheShip,
FFOW,
JC2MP,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub enum Protocol {
Gamespy(gamespy::GameSpyVersion),
Minecraft(Option<minecraft::types::Server>),
Quake(quake::QuakeVersion),
Valve(valve::SteamApp),
#[cfg(feature = "games")]
PROPRIETARY(ProprietaryProtocol),
}
#[derive(Debug, Clone, PartialEq)]
pub enum GenericResponse<'a> {
GameSpy(gamespy::VersionedResponse<'a>),
Minecraft(minecraft::VersionedResponse<'a>),
Quake(quake::VersionedResponse<'a>),
Valve(&'a valve::Response),
#[cfg(feature = "games")]
TheShip(&'a crate::games::ts::Response),
#[cfg(feature = "games")]
FFOW(&'a crate::games::ffow::Response),
#[cfg(feature = "games")]
JC2MP(&'a crate::games::jc2mp::Response),
}
#[derive(Debug, Clone, PartialEq)]
pub enum GenericPlayer<'a> {
Valve(&'a valve::ServerPlayer),
QuakeOne(&'a quake::one::Player),
QuakeTwo(&'a quake::two::Player),
Minecraft(&'a minecraft::Player),
Gamespy(gamespy::VersionedPlayer<'a>),
#[cfg(feature = "games")]
TheShip(&'a crate::games::ts::TheShipPlayer),
#[cfg(feature = "games")]
JCMP2(&'a crate::games::jc2mp::Player),
}
pub trait CommonResponse {
fn as_original(&self) -> GenericResponse;
fn as_json(&self) -> CommonResponseJson {
CommonResponseJson {
name: self.name(),
description: self.description(),
game: self.game(),
game_version: self.game_version(),
has_password: self.has_password(),
map: self.map(),
players_maximum: self.players_maximum(),
players_online: self.players_online(),
players_bots: self.players_bots(),
players: self
.players()
.map(|players| players.iter().map(|p| p.as_json()).collect()),
}
}
fn name(&self) -> Option<&str> { None }
fn description(&self) -> Option<&str> { None }
fn game(&self) -> Option<&str> { None }
fn game_version(&self) -> Option<&str> { None }
fn map(&self) -> Option<&str> { None }
fn players_maximum(&self) -> u64;
fn players_online(&self) -> u64;
fn players_bots(&self) -> Option<u64> { None }
fn has_password(&self) -> Option<bool> { None }
fn players(&self) -> Option<Vec<&dyn CommonPlayer>> { None }
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct CommonResponseJson<'a> {
pub name: Option<&'a str>,
pub description: Option<&'a str>,
pub game: Option<&'a str>,
pub game_version: Option<&'a str>,
pub map: Option<&'a str>,
pub players_maximum: u64,
pub players_online: u64,
pub players_bots: Option<u64>,
pub has_password: Option<bool>,
pub players: Option<Vec<CommonPlayerJson<'a>>>,
}
pub trait CommonPlayer {
fn as_original(&self) -> GenericPlayer;
fn as_json(&self) -> CommonPlayerJson {
CommonPlayerJson {
name: self.name(),
score: self.score(),
}
}
fn name(&self) -> &str;
fn score(&self) -> Option<u32> { None }
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct CommonPlayerJson<'a> {
pub name: &'a str,
pub score: Option<u32>,
}
#[derive(Clone, Debug)]
pub struct TimeoutSettings {
read: Option<Duration>,
write: Option<Duration>,
}
impl TimeoutSettings {
pub fn new(read: Option<Duration>, write: Option<Duration>) -> GDResult<Self> {
if let Some(read_duration) = read {
if read_duration == Duration::new(0, 0) {
return Err(InvalidInput);
}
}
if let Some(write_duration) = write {
if write_duration == Duration::new(0, 0) {
return Err(InvalidInput);
}
}
Ok(Self { read, write })
}
pub fn get_read(&self) -> Option<Duration> { self.read }
pub fn get_write(&self) -> Option<Duration> { self.write }
}
impl Default for TimeoutSettings {
fn default() -> Self {
Self {
read: Some(Duration::from_secs(4)),
write: Some(Duration::from_secs(4)),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::time::Duration;
#[test]
fn test_new_with_valid_durations() -> GDResult<()> {
let read_duration = Duration::from_secs(1);
let write_duration = Duration::from_secs(2);
let timeout_settings = TimeoutSettings::new(Some(read_duration), Some(write_duration))?;
assert_eq!(timeout_settings.get_read(), Some(read_duration));
assert_eq!(timeout_settings.get_write(), Some(write_duration));
Ok(())
}
#[test]
fn test_new_with_zero_duration() {
let read_duration = Duration::new(0, 0);
let write_duration = Duration::from_secs(2);
let result = TimeoutSettings::new(Some(read_duration), Some(write_duration));
assert!(result.is_err());
assert_eq!(result.unwrap_err(), InvalidInput);
}
#[test]
fn test_default_values() {
let default_settings = TimeoutSettings::default();
assert_eq!(default_settings.get_read(), Some(Duration::from_secs(4)));
assert_eq!(default_settings.get_write(), Some(Duration::from_secs(4)));
}
}