[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"
version = "0.2.1"
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"
description = "Check out servers with this."
homepage = "https://github.com/gamedig/rust-gamedig"
@ -13,12 +16,14 @@ keywords = ["server", "query", "game", "check", "status"]
rust-version = "1.56.1"
[features]
default = []
no_games = []
serde = ["dep:serde", "serde/derive"]
[dependencies]
byteorder = "1.4.3"
bzip2-rs = "0.1.2" # for compression
bzip2-rs = "0.1.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::{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 name: String,
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 protocol: u8,
pub name: String,

View file

@ -1,7 +1,11 @@
use std::collections::HashMap;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
/// A players details.
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Player {
pub name: String,
pub team: u8,
@ -13,11 +17,12 @@ pub struct Player {
pub frags: u32,
pub deaths: Option<u32>,
pub health: Option<u32>,
pub secret: bool
pub secret: bool,
}
/// A query response.
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Response {
pub name: String,
pub map: String,
@ -32,5 +37,5 @@ pub struct Response {
pub players_minimum: u8,
pub players: Vec<Player>,
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
by Jaiden Bernard (2021-2022 - MIT) from
https://github.com/thisjaiden/golden_apple/blob/master/src/lib.rs
*/
use crate::GDResult;
use crate::bufferer::Bufferer;
use crate::GDError::{PacketBad, UnknownEnumCast};
use crate::GDResult;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
/// 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 {
/// Java Edition.
Java,
/// Legacy Java.
Legacy(LegacyGroup),
/// Bedrock Edition.
Bedrock
Bedrock,
}
/// 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 {
/// 1.6
V1_6,
/// 1.4 - 1.5
V1_4,
/// Beta 1.8 - 1.3
VB1_8
VB1_8,
}
/// 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 name: String,
pub id: String
pub id: String,
}
/// A Java query response.
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct JavaResponse {
/// Version name, example: "1.19.2".
pub version_name: String,
@ -60,11 +66,12 @@ pub struct JavaResponse {
/// Tells if secure chat is enforced (can be missing).
pub enforces_secure_chat: Option<bool>,
/// Tell's the server type.
pub server_type: Server
pub server_type: Server,
}
/// 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 {
/// Server's edition.
pub edition: String,
@ -85,7 +92,7 @@ pub struct BedrockResponse {
/// Current game mode.
pub game_mode: Option<GameMode>,
/// Tells the server type.
pub server_type: Server
pub server_type: Server,
}
impl JavaResponse {
@ -100,15 +107,20 @@ impl JavaResponse {
favicon: None,
previews_chat: None,
enforces_secure_chat: None,
server_type: Server::Bedrock
server_type: Server::Bedrock,
}
}
}
/// A server's game mode (used only by Bedrock servers).
#[derive(Debug)]
/// A server's game mode (used only by Bedrock servers.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum GameMode {
Survival, Creative, Hardcore, Spectator, Adventure
Survival,
Creative,
Hardcore,
Spectator,
Adventure,
}
impl GameMode {
@ -119,7 +131,7 @@ impl GameMode {
"Hardcore" => Ok(GameMode::Hardcore),
"Spectator" => Ok(GameMode::Spectator),
"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
if i == 4 && (current_byte & 0xf0 != 0) {
return Err(PacketBad)
return Err(PacketBad);
}
if (current_byte & msb) == 0 {

View file

@ -1,31 +1,38 @@
use std::collections::HashMap;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
/// 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 {
Dedicated,
NonDedicated,
TV
TV,
}
/// 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 {
Linux,
Windows,
Mac
Mac,
}
/// A query response.
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct Response {
pub info: ServerInfo,
pub players: Option<Vec<ServerPlayer>>,
pub rules: Option<HashMap<String, String>>
pub rules: Option<HashMap<String, String>>,
}
/// General server information's.
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ServerInfo {
/// Protocol used by the server.
pub protocol: u8,
@ -62,11 +69,12 @@ pub struct ServerInfo {
/// GoldSrc only: Indicates whether the hosted game is a mod.
pub is_mod: bool,
/// GoldSrc only: If the game is a mod, provide additional data.
pub mod_data: Option<ModData>
pub mod_data: Option<ModData>,
}
/// A server player.
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct ServerPlayer {
/// Player's name.
pub name: String,
@ -81,15 +89,17 @@ pub struct ServerPlayer {
}
/// 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 mode: u8,
pub witnesses: u8,
pub duration: u8
pub duration: u8,
}
/// 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 {
/// The server's game port number.
pub port: Option<u16>,
@ -102,18 +112,19 @@ pub struct ExtraData {
/// Keywords that describe the server according to it.
pub keywords: Option<String>,
/// The server's 64-bit GameID.
pub game_id: Option<u64>
pub game_id: Option<u64>,
}
/// 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 link: String,
pub download_link: String,
pub version: u32,
pub size: u32,
pub multiplayer_only: bool,
pub has_own_dll: bool
pub has_own_dll: bool,
}
pub(crate) type ExtractedData = (
@ -142,11 +153,12 @@ pub(crate) enum Request {
/// Known as `A2S_PLAYERS`
Players = 0x55,
/// Known as `A2S_RULES`
Rules = 0x56
Rules = 0x56,
}
/// 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 {
/// Counter-Strike
CS,
@ -236,9 +248,9 @@ impl SteamApp {
/// Get the specified app as engine.
pub fn as_engine(&self) -> Engine {
match self {
SteamApp::CS => Engine::GoldSrc(false), //10
SteamApp::TFC => Engine::GoldSrc(false), //20
SteamApp::DOD => Engine::GoldSrc(false), //30
SteamApp::CS => Engine::GoldSrc(false), //10
SteamApp::TFC => Engine::GoldSrc(false), //20
SteamApp::DOD => Engine::GoldSrc(false), //30
SteamApp::CSCZ => Engine::GoldSrc(false), //80
SteamApp::CSS => Engine::new_source(240),
SteamApp::DODS => Engine::new_source(300),
@ -282,7 +294,8 @@ impl SteamApp {
}
/// 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 {
/// 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
@ -290,7 +303,7 @@ pub enum Engine {
Source(Option<(u32, Option<u32>)>),
/// A GoldSrc game, the argument indicates whether to enforce
/// requesting the obsolete A2S_INFO response or not.
GoldSrc(bool)
GoldSrc(bool),
}
impl Engine {
@ -306,7 +319,7 @@ impl Engine {
/// What data to gather, purely used only with the query function.
pub struct GatheringSettings {
pub players: bool,
pub rules: bool
pub rules: bool,
}
impl Default for GatheringSettings {
@ -314,7 +327,7 @@ impl Default for GatheringSettings {
fn default() -> Self {
Self {
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
/// unnecessary bits (example: the **The Ship**-only fields).
pub mod game {
use std::collections::HashMap;
use crate::protocols::valve::types::get_optional_extracted_data;
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.
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Player {
/// Player's name.
pub name: String,
/// Player's score.
pub score: u32,
/// How long a player has been in the server (seconds).
pub duration: f32
pub duration: f32,
}
impl Player {
@ -342,13 +359,14 @@ pub mod game {
Self {
name: player.name.clone(),
score: player.score,
duration: player.duration
duration: player.duration,
}
}
}
/// The query response.
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct Response {
/// Protocol used by the server.
pub protocol: u8,
@ -387,12 +405,13 @@ pub mod game {
/// Keywords that describe the server according to it.
pub keywords: Option<String>,
/// Server's rules.
pub rules: HashMap<String, String>
pub rules: HashMap<String, String>,
}
impl Response {
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 {
protocol: response.info.protocol,
@ -401,7 +420,12 @@ pub mod game {
game: response.info.game,
appid: response.info.appid,
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_bots: response.info.players_bots,
server_type: response.info.server_type,
@ -413,7 +437,7 @@ pub mod game {
tv_port,
tv_name,
keywords,
rules: response.rules.unwrap_or_default()
rules: response.rules.unwrap_or_default(),
}
}
}