[Crate] Add feature: serde (#21)

* feat(serde): add additional derives

* fix: remove attr on internal enum

* fix add missing derive
This commit is contained in:
Cain 2023-03-13 15:51:33 +01:00 committed by GitHub
parent bd2e373d66
commit 84af4230f7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 113 additions and 62 deletions

View file

@ -2,7 +2,10 @@
name = "gamedig" name = "gamedig"
version = "0.2.1" version = "0.2.1"
edition = "2021" edition = "2021"
authors = ["CosminPerRam [https://github.com/CosminPerRam]", "node-GameDig contributors [https://github.com/gamedig/node-gamedig/contributors]"] authors = [
"CosminPerRam [https://github.com/CosminPerRam]",
"node-GameDig contributors [https://github.com/gamedig/node-gamedig/contributors]",
]
license = "MIT" license = "MIT"
description = "Check out servers with this." description = "Check out servers with this."
homepage = "https://github.com/gamedig/rust-gamedig" homepage = "https://github.com/gamedig/rust-gamedig"
@ -13,12 +16,14 @@ keywords = ["server", "query", "game", "check", "status"]
rust-version = "1.56.1" rust-version = "1.56.1"
[features] [features]
default = []
no_games = [] no_games = []
serde = ["dep:serde", "serde/derive"]
[dependencies] [dependencies]
byteorder = "1.4.3" byteorder = "1.4.3"
bzip2-rs = "0.1.2"
bzip2-rs = "0.1.2" # for compression
crc32fast = "1.3.2" crc32fast = "1.3.2"
serde_json = "1.0.91"
serde_json = "1.0.91" # json to structs serde = { version = "1.0.155", optional = true }

View file

@ -3,7 +3,11 @@ use crate::GDResult;
use crate::protocols::valve; use crate::protocols::valve;
use crate::protocols::valve::{Server, ServerPlayer, get_optional_extracted_data, SteamApp}; use crate::protocols::valve::{Server, ServerPlayer, get_optional_extracted_data, SteamApp};
#[derive(Debug)] #[cfg (feature = "serde")]
use serde::{Serialize, Deserialize};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct TheShipPlayer { pub struct TheShipPlayer {
pub name: String, pub name: String,
pub score: u32, pub score: u32,
@ -24,7 +28,8 @@ impl TheShipPlayer {
} }
} }
#[derive(Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct Response { pub struct Response {
pub protocol: u8, pub protocol: u8,
pub name: String, pub name: String,

View file

@ -1,7 +1,11 @@
use std::collections::HashMap; use std::collections::HashMap;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
/// A players details. /// A players details.
#[derive(Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Player { pub struct Player {
pub name: String, pub name: String,
pub team: u8, pub team: u8,
@ -13,11 +17,12 @@ pub struct Player {
pub frags: u32, pub frags: u32,
pub deaths: Option<u32>, pub deaths: Option<u32>,
pub health: Option<u32>, pub health: Option<u32>,
pub secret: bool pub secret: bool,
} }
/// A query response. /// A query response.
#[derive(Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Response { pub struct Response {
pub name: String, pub name: String,
pub map: String, pub map: String,
@ -32,5 +37,5 @@ pub struct Response {
pub players_minimum: u8, pub players_minimum: u8,
pub players: Vec<Player>, pub players: Vec<Player>,
pub tournament: bool, pub tournament: bool,
pub unused_entries: HashMap<String, String> pub unused_entries: HashMap<String, String>,
} }

View file

@ -1,45 +1,51 @@
/* /*
Although its a lightly modified version, this file contains code Although its a lightly modified version, this file contains code
by Jaiden Bernard (2021-2022 - MIT) from by Jaiden Bernard (2021-2022 - MIT) from
https://github.com/thisjaiden/golden_apple/blob/master/src/lib.rs https://github.com/thisjaiden/golden_apple/blob/master/src/lib.rs
*/ */
use crate::GDResult;
use crate::bufferer::Bufferer; use crate::bufferer::Bufferer;
use crate::GDError::{PacketBad, UnknownEnumCast}; use crate::GDError::{PacketBad, UnknownEnumCast};
use crate::GDResult;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
/// The type of Minecraft Server you want to query. /// The type of Minecraft Server you want to query.
#[derive(Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum Server { pub enum Server {
/// Java Edition. /// Java Edition.
Java, Java,
/// Legacy Java. /// Legacy Java.
Legacy(LegacyGroup), Legacy(LegacyGroup),
/// Bedrock Edition. /// Bedrock Edition.
Bedrock Bedrock,
} }
/// Legacy Java (Versions) Groups. /// Legacy Java (Versions) Groups.
#[derive(Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum LegacyGroup { pub enum LegacyGroup {
/// 1.6 /// 1.6
V1_6, V1_6,
/// 1.4 - 1.5 /// 1.4 - 1.5
V1_4, V1_4,
/// Beta 1.8 - 1.3 /// Beta 1.8 - 1.3
VB1_8 VB1_8,
} }
/// Information about a player. /// Information about a player.
#[derive(Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Player { pub struct Player {
pub name: String, pub name: String,
pub id: String pub id: String,
} }
/// A Java query response. /// A Java query response.
#[derive(Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct JavaResponse { pub struct JavaResponse {
/// Version name, example: "1.19.2". /// Version name, example: "1.19.2".
pub version_name: String, pub version_name: String,
@ -60,11 +66,12 @@ pub struct JavaResponse {
/// Tells if secure chat is enforced (can be missing). /// Tells if secure chat is enforced (can be missing).
pub enforces_secure_chat: Option<bool>, pub enforces_secure_chat: Option<bool>,
/// Tell's the server type. /// Tell's the server type.
pub server_type: Server pub server_type: Server,
} }
/// A Bedrock Edition query response. /// A Bedrock Edition query response.
#[derive(Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct BedrockResponse { pub struct BedrockResponse {
/// Server's edition. /// Server's edition.
pub edition: String, pub edition: String,
@ -85,7 +92,7 @@ pub struct BedrockResponse {
/// Current game mode. /// Current game mode.
pub game_mode: Option<GameMode>, pub game_mode: Option<GameMode>,
/// Tells the server type. /// Tells the server type.
pub server_type: Server pub server_type: Server,
} }
impl JavaResponse { impl JavaResponse {
@ -100,15 +107,20 @@ impl JavaResponse {
favicon: None, favicon: None,
previews_chat: None, previews_chat: None,
enforces_secure_chat: None, enforces_secure_chat: None,
server_type: Server::Bedrock server_type: Server::Bedrock,
} }
} }
} }
/// A server's game mode (used only by Bedrock servers). /// A server's game mode (used only by Bedrock servers.
#[derive(Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum GameMode { pub enum GameMode {
Survival, Creative, Hardcore, Spectator, Adventure Survival,
Creative,
Hardcore,
Spectator,
Adventure,
} }
impl GameMode { impl GameMode {
@ -119,7 +131,7 @@ impl GameMode {
"Hardcore" => Ok(GameMode::Hardcore), "Hardcore" => Ok(GameMode::Hardcore),
"Spectator" => Ok(GameMode::Spectator), "Spectator" => Ok(GameMode::Spectator),
"Adventure" => Ok(GameMode::Adventure), "Adventure" => Ok(GameMode::Adventure),
_ => Err(UnknownEnumCast) _ => Err(UnknownEnumCast),
} }
} }
} }
@ -137,7 +149,7 @@ pub(crate) fn get_varint(buffer: &mut Bufferer) -> GDResult<i32> {
// The 5th byte is only allowed to have the 4 smallest bits set // The 5th byte is only allowed to have the 4 smallest bits set
if i == 4 && (current_byte & 0xf0 != 0) { if i == 4 && (current_byte & 0xf0 != 0) {
return Err(PacketBad) return Err(PacketBad);
} }
if (current_byte & msb) == 0 { if (current_byte & msb) == 0 {

View file

@ -1,31 +1,38 @@
use std::collections::HashMap; use std::collections::HashMap;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
/// The type of the server. /// The type of the server.
#[derive(Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum Server { pub enum Server {
Dedicated, Dedicated,
NonDedicated, NonDedicated,
TV TV,
} }
/// The Operating System that the server is on. /// The Operating System that the server is on.
#[derive(Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum Environment { pub enum Environment {
Linux, Linux,
Windows, Windows,
Mac Mac,
} }
/// A query response. /// A query response.
#[derive(Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct Response { pub struct Response {
pub info: ServerInfo, pub info: ServerInfo,
pub players: Option<Vec<ServerPlayer>>, pub players: Option<Vec<ServerPlayer>>,
pub rules: Option<HashMap<String, String>> pub rules: Option<HashMap<String, String>>,
} }
/// General server information's. /// General server information's.
#[derive(Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ServerInfo { pub struct ServerInfo {
/// Protocol used by the server. /// Protocol used by the server.
pub protocol: u8, pub protocol: u8,
@ -62,11 +69,12 @@ pub struct ServerInfo {
/// GoldSrc only: Indicates whether the hosted game is a mod. /// GoldSrc only: Indicates whether the hosted game is a mod.
pub is_mod: bool, pub is_mod: bool,
/// GoldSrc only: If the game is a mod, provide additional data. /// GoldSrc only: If the game is a mod, provide additional data.
pub mod_data: Option<ModData> pub mod_data: Option<ModData>,
} }
/// A server player. /// A server player.
#[derive(Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct ServerPlayer { pub struct ServerPlayer {
/// Player's name. /// Player's name.
pub name: String, pub name: String,
@ -81,15 +89,17 @@ pub struct ServerPlayer {
} }
/// Only present for [the ship](https://developer.valvesoftware.com/wiki/The_Ship). /// Only present for [the ship](https://developer.valvesoftware.com/wiki/The_Ship).
#[derive(Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct TheShip { pub struct TheShip {
pub mode: u8, pub mode: u8,
pub witnesses: u8, pub witnesses: u8,
pub duration: u8 pub duration: u8,
} }
/// Some extra data that the server might provide or not. /// Some extra data that the server might provide or not.
#[derive(Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ExtraData { pub struct ExtraData {
/// The server's game port number. /// The server's game port number.
pub port: Option<u16>, pub port: Option<u16>,
@ -102,18 +112,19 @@ pub struct ExtraData {
/// Keywords that describe the server according to it. /// Keywords that describe the server according to it.
pub keywords: Option<String>, pub keywords: Option<String>,
/// The server's 64-bit GameID. /// The server's 64-bit GameID.
pub game_id: Option<u64> pub game_id: Option<u64>,
} }
/// Data related to GoldSrc Mod response. /// Data related to GoldSrc Mod response.
#[derive(Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ModData { pub struct ModData {
pub link: String, pub link: String,
pub download_link: String, pub download_link: String,
pub version: u32, pub version: u32,
pub size: u32, pub size: u32,
pub multiplayer_only: bool, pub multiplayer_only: bool,
pub has_own_dll: bool pub has_own_dll: bool,
} }
pub(crate) type ExtractedData = ( pub(crate) type ExtractedData = (
@ -142,11 +153,12 @@ pub(crate) enum Request {
/// Known as `A2S_PLAYERS` /// Known as `A2S_PLAYERS`
Players = 0x55, Players = 0x55,
/// Known as `A2S_RULES` /// Known as `A2S_RULES`
Rules = 0x56 Rules = 0x56,
} }
/// Supported steam apps /// Supported steam apps
#[derive(Eq, PartialEq, Clone)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum SteamApp { pub enum SteamApp {
/// Counter-Strike /// Counter-Strike
CS, CS,
@ -236,9 +248,9 @@ impl SteamApp {
/// Get the specified app as engine. /// Get the specified app as engine.
pub fn as_engine(&self) -> Engine { pub fn as_engine(&self) -> Engine {
match self { match self {
SteamApp::CS => Engine::GoldSrc(false), //10 SteamApp::CS => Engine::GoldSrc(false), //10
SteamApp::TFC => Engine::GoldSrc(false), //20 SteamApp::TFC => Engine::GoldSrc(false), //20
SteamApp::DOD => Engine::GoldSrc(false), //30 SteamApp::DOD => Engine::GoldSrc(false), //30
SteamApp::CSCZ => Engine::GoldSrc(false), //80 SteamApp::CSCZ => Engine::GoldSrc(false), //80
SteamApp::CSS => Engine::new_source(240), SteamApp::CSS => Engine::new_source(240),
SteamApp::DODS => Engine::new_source(300), SteamApp::DODS => Engine::new_source(300),
@ -282,7 +294,8 @@ impl SteamApp {
} }
/// Engine type. /// Engine type.
#[derive(Eq, PartialEq, Clone)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum Engine { pub enum Engine {
/// A Source game, the argument represents the possible steam app ids, if its **None**, let /// A Source game, the argument represents the possible steam app ids, if its **None**, let
/// the query find it, if its **Some**, the query fails if the response id is not the first /// the query find it, if its **Some**, the query fails if the response id is not the first
@ -290,7 +303,7 @@ pub enum Engine {
Source(Option<(u32, Option<u32>)>), Source(Option<(u32, Option<u32>)>),
/// A GoldSrc game, the argument indicates whether to enforce /// A GoldSrc game, the argument indicates whether to enforce
/// requesting the obsolete A2S_INFO response or not. /// requesting the obsolete A2S_INFO response or not.
GoldSrc(bool) GoldSrc(bool),
} }
impl Engine { impl Engine {
@ -306,7 +319,7 @@ impl Engine {
/// What data to gather, purely used only with the query function. /// What data to gather, purely used only with the query function.
pub struct GatheringSettings { pub struct GatheringSettings {
pub players: bool, pub players: bool,
pub rules: bool pub rules: bool,
} }
impl Default for GatheringSettings { impl Default for GatheringSettings {
@ -314,7 +327,7 @@ impl Default for GatheringSettings {
fn default() -> Self { fn default() -> Self {
Self { Self {
players: true, players: true,
rules: true rules: true,
} }
} }
} }
@ -322,19 +335,23 @@ impl Default for GatheringSettings {
/// Generic response types that are used by many games, they are the protocol ones, but without the /// Generic response types that are used by many games, they are the protocol ones, but without the
/// unnecessary bits (example: the **The Ship**-only fields). /// unnecessary bits (example: the **The Ship**-only fields).
pub mod game { pub mod game {
use std::collections::HashMap;
use crate::protocols::valve::types::get_optional_extracted_data;
use super::{Server, ServerPlayer}; use super::{Server, ServerPlayer};
use crate::protocols::valve::types::get_optional_extracted_data;
use std::collections::HashMap;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
/// A player's details. /// A player's details.
#[derive(Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Player { pub struct Player {
/// Player's name. /// Player's name.
pub name: String, pub name: String,
/// Player's score. /// Player's score.
pub score: u32, pub score: u32,
/// How long a player has been in the server (seconds). /// How long a player has been in the server (seconds).
pub duration: f32 pub duration: f32,
} }
impl Player { impl Player {
@ -342,13 +359,14 @@ pub mod game {
Self { Self {
name: player.name.clone(), name: player.name.clone(),
score: player.score, score: player.score,
duration: player.duration duration: player.duration,
} }
} }
} }
/// The query response. /// The query response.
#[derive(Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct Response { pub struct Response {
/// Protocol used by the server. /// Protocol used by the server.
pub protocol: u8, pub protocol: u8,
@ -387,12 +405,13 @@ pub mod game {
/// Keywords that describe the server according to it. /// Keywords that describe the server according to it.
pub keywords: Option<String>, pub keywords: Option<String>,
/// Server's rules. /// Server's rules.
pub rules: HashMap<String, String> pub rules: HashMap<String, String>,
} }
impl Response { impl Response {
pub fn new_from_valve_response(response: super::Response) -> Self { pub fn new_from_valve_response(response: super::Response) -> Self {
let (port, steam_id, tv_port, tv_name, keywords) = get_optional_extracted_data(response.info.extra_data); let (port, steam_id, tv_port, tv_name, keywords) =
get_optional_extracted_data(response.info.extra_data);
Self { Self {
protocol: response.info.protocol, protocol: response.info.protocol,
@ -401,7 +420,12 @@ pub mod game {
game: response.info.game, game: response.info.game,
appid: response.info.appid, appid: response.info.appid,
players_online: response.info.players_online, players_online: response.info.players_online,
players_details: response.players.unwrap_or_default().iter().map(Player::from_valve_response).collect(), players_details: response
.players
.unwrap_or_default()
.iter()
.map(Player::from_valve_response)
.collect(),
players_maximum: response.info.players_maximum, players_maximum: response.info.players_maximum,
players_bots: response.info.players_bots, players_bots: response.info.players_bots,
server_type: response.info.server_type, server_type: response.info.server_type,
@ -413,7 +437,7 @@ pub mod game {
tv_port, tv_port,
tv_name, tv_name,
keywords, keywords,
rules: response.rules.unwrap_or_default() rules: response.rules.unwrap_or_default(),
} }
} }
} }