use serde::{Deserialize, Deserializer};
use std::collections::HashMap;
pub type GameId = u64;
#[derive(Debug, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ServiceStatus {
Ok,
Partial,
Rebooting,
Fatal,
}
#[derive(Debug, Deserialize)]
pub struct GameInfo {
pub urls: Urls,
pub url: Option<String>,
pub org_url: Option<String>,
pub title: String,
#[serde(deserialize_with = "object_empty_as_none")]
pub org_price: Option<Price>,
#[serde(deserialize_with = "object_empty_as_none")]
pub price: Option<Price>,
#[serde(deserialize_with = "object_empty_as_none")]
pub thumbnail: Option<Thumbnail>,
pub kind: ProductKind,
pub tags: Vec<String>,
pub description: Option<String>,
pub rating: Option<f32>,
pub notice: Option<String>,
pub until: Option<f32>,
pub store: Option<Store>,
pub flags: GameFlags,
#[serde(rename = "type")]
pub game_type: AnnouncementType,
pub localized: Option<HashMap<String, LocalizedGameInfo>>,
}
#[derive(Debug, Deserialize)]
pub struct Urls {
pub default: String,
pub browser: String,
pub client: Option<String>,
pub org: String,
}
#[derive(Debug, Deserialize)]
pub struct Price {
pub euro: Option<f64>,
pub dollar: Option<f64>,
}
#[derive(Debug, Deserialize)]
pub struct Thumbnail {
pub org: String,
pub blank: String,
pub full: String,
pub tags: String,
}
#[allow(missing_docs)]
#[derive(Debug, Deserialize)]
pub struct LocalizedGameInfo {
pub lang_name: String,
pub lang_name_en: String,
pub lang_flag_emoji: String,
pub platform: String,
pub claim_long: String,
pub claim_short: String,
pub free: String,
pub header: String,
pub footer: String,
pub org_price_eur: String,
pub org_price_usd: String,
pub until: String,
pub until_alt: String,
pub flags: Vec<String>,
}
#[derive(Debug, Deserialize)]
#[serde(field_identifier, rename_all = "lowercase")]
pub enum Store {
Steam,
Epic,
Humble,
Gog,
Origin,
Uplay,
Twitch,
Itch,
Discord,
Apple,
Google,
Switch,
Ps,
Xbox,
Other(String),
}
#[derive(Debug, Deserialize)]
#[serde(field_identifier, rename_all = "lowercase")]
pub enum AnnouncementType {
Free,
Weekend,
Discount,
Ad,
Unknown(String),
}
#[derive(Debug, Deserialize)]
pub struct GameFlags(u8);
impl GameFlags {
pub fn inner(&self) -> u8 {
self.0
}
fn bit(&self, bit: usize) -> bool {
self.0 >> bit & 1 == 1
}
pub fn trash(&self) -> bool {
self.bit(0)
}
pub fn thirdparty(&self) -> bool {
self.bit(1)
}
}
#[derive(Debug, Deserialize)]
#[serde(field_identifier, rename_all = "lowercase")]
pub enum ProductKind {
Game,
DLC,
Software,
Art,
OST,
Book,
Other(String),
}
fn object_empty_as_none<'de, D, T>(deserializer: D) -> Result<Option<T>, D::Error>
where
D: Deserializer<'de>,
for<'a> T: Deserialize<'a>,
{
#[derive(Deserialize, Debug)]
#[serde(deny_unknown_fields)]
struct Empty {}
#[derive(Deserialize, Debug)]
#[serde(untagged)]
enum Aux<T> {
T(T),
Empty(Empty),
Null,
}
match Deserialize::deserialize(deserializer)? {
Aux::T(t) => Ok(Some(t)),
Aux::Empty(_) | Aux::Null => Ok(None),
}
}