#![feature(proc_macro)]
#[macro_use]
extern crate serde_derive;
use std::collections::HashMap;
use std::ops::Deref;
use std::str::FromStr;
extern crate serde;
extern crate iso_country;
use serde::*;
use iso_country::Country as CountryBase;
mod protocols;
use protocols::*;
#[derive(Clone, Debug, PartialEq)]
pub struct Country(CountryBase);
impl Deref for Country {
type Target = iso_country::Country;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl Default for Country {
fn default() -> Country {
Country(CountryBase::Unspecified)
}
}
impl Serialize for Country {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer
{
serializer.serialize_str(self.to_string().as_str())
}
}
impl Deserialize for Country {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
where D: Deserializer
{
struct Visitor;
impl de::Visitor for Visitor {
type Value = Country;
fn visit_str<E>(&mut self, value: &str) -> Result<Country, E>
where E: de::Error
{
Ok(Country(CountryBase::from_str(value).unwrap_or(CountryBase::Unspecified)))
}
}
deserializer.deserialize_str(Visitor)
}
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub enum Status {
Unspecified,
Up,
Down,
}
impl Default for Status {
fn default() -> Status {
Status::Unspecified
}
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct Player {
pub name: String,
pub ping: i64,
pub info: HashMap<String, String>,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct Server {
pub host: String,
#[serde(default)]
pub protocol: Protocol,
#[serde(default)]
pub status: Status,
#[serde(default)]
pub country: Country,
#[serde(default)]
pub rules: HashMap<String, String>,
#[serde(skip_serializing_if="Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if="Option::is_none")]
pub need_pass: Option<bool>,
#[serde(skip_serializing_if="Option::is_none")]
pub mod_name: Option<String>,
#[serde(skip_serializing_if="Option::is_none")]
pub game_type: Option<String>,
#[serde(skip_serializing_if="Option::is_none")]
pub terrain: Option<String>,
#[serde(skip_serializing_if="Option::is_none")]
pub num_clients: Option<i64>,
#[serde(skip_serializing_if="Option::is_none")]
pub max_clients: Option<i64>,
#[serde(skip_serializing_if="Option::is_none")]
pub num_bots: Option<i64>,
#[serde(skip_serializing_if="Option::is_none")]
pub secure: Option<bool>,
#[serde(skip_serializing_if="Option::is_none")]
pub ping: Option<i64>,
#[serde(skip_serializing_if="Option::is_none")]
pub players: Option<Vec<Player>>,
}
#[cfg(test)]
mod tests {
use super::*;
extern crate serde_json;
#[test]
fn serialization() {
let myserver = Server {
protocol: Protocol::Q3S,
status: Status::Up,
host: "127.0.0.1".to_string(),
country: Country(CountryBase::RU),
name: None,
need_pass: None,
mod_name: None,
game_type: None,
terrain: None,
num_clients: None,
max_clients: None,
num_bots: None,
secure: None,
ping: None,
players: None,
rules: HashMap::new(),
};
assert_eq!(serde_json::to_string(&myserver).unwrap(), "{\"host\":\"127.0.0.1\",\"protocol\":\"Q3S\",\"status\":\"Up\",\"country\":\"RU\",\"rules\":{}}");
}
#[test]
fn deserialization() {
let myserver = Server {
protocol: Protocol::Q3S,
status: Status::Up,
host: "127.0.0.1".to_string(),
country: Country(CountryBase::RU),
name: None,
need_pass: None,
mod_name: None,
game_type: None,
terrain: None,
num_clients: None,
max_clients: None,
num_bots: None,
secure: None,
ping: None,
players: None,
rules: HashMap::new(),
};
assert_eq!(serde_json::from_str::<Server>("{\"protocol\":\"Q3S\",\"status\":\"Up\",\"host\":\"127.0.0.1\",\"country\":\"RU\",\"rules\":{}}").unwrap(), myserver);
}
}