use serde::{self, Serialize, Deserialize};
use crate::traits::{PropLimRouteable, PropLimFetchable};
use crate::serde::{one_default, oxffffff_default, deserialize_number_from_string};
use std::ops::{Deref, DerefMut};
use crate::util::fetch_route;
use crate::error::Result;
#[cfg(feature = "async")]
use async_trait::async_trait;
#[cfg(feature = "async")]
use crate::util::a_fetch_route;
use crate::http::Client;
use crate::http::routes::Route;
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
pub struct PlayerLeaderboard {
#[serde(default)]
pub items: Vec<PlayerRanking>,
}
impl Deref for PlayerLeaderboard {
type Target = Vec<PlayerRanking>;
fn deref(&self) -> &Vec<PlayerRanking> {
&self.items
}
}
impl DerefMut for PlayerLeaderboard {
fn deref_mut(&mut self) -> &mut Vec<PlayerRanking> {
&mut self.items
}
}
#[cfg_attr(feature = "async", async_trait)]
impl PropLimFetchable for PlayerLeaderboard {
type Property = str;
type Limit = u8;
fn fetch(client: &Client, country_code: &str, limit: u8) -> Result<PlayerLeaderboard> {
let route = PlayerLeaderboard::get_route(country_code, limit);
fetch_route::<PlayerLeaderboard>(client, &route)
}
#[cfg(feature="async")]
async fn a_fetch(
client: &Client, country_code: &'async_trait str, limit: u8
) -> Result<PlayerLeaderboard>
where Self: 'async_trait,
Self::Property: 'async_trait,
{
let route = PlayerLeaderboard::get_route(&country_code, limit);
a_fetch_route::<PlayerLeaderboard>(client, &route).await
}
}
impl PropLimRouteable for PlayerLeaderboard {
type Property = str;
type Limit = u8;
fn get_route(country_code: &str, limit: u8) -> Route {
Route::PlayerRankings {
country_code: country_code.to_owned(),
limit
}
}
}
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PlayerRanking {
#[serde(default)]
pub club: PlayerRankingClub,
#[serde(default)]
pub tag: String,
#[serde(default)]
pub name: String,
#[serde(default)]
pub trophies: usize,
#[serde(default = "one_default")]
pub rank: u8,
#[serde(default = "oxffffff_default")]
#[serde(deserialize_with = "deserialize_number_from_string")]
pub name_color: u64,
}
#[non_exhaustive]
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
pub struct PlayerRankingClub {
#[serde(default)]
pub name: String,
}
impl PlayerRankingClub {
pub fn new(name: &str) -> PlayerRankingClub {
PlayerRankingClub { name: name.to_owned() }
}
}
impl Default for PlayerRankingClub {
fn default() -> PlayerRankingClub {
PlayerRankingClub {
name: String::from(""),
}
}
}
#[cfg(test)]
mod tests {
use serde_json;
use super::{PlayerLeaderboard, PlayerRanking, PlayerRankingClub};
use crate::error::Error;
#[test]
fn rankings_players_deser() -> Result<(), Box<dyn ::std::error::Error>> {
let rp_json_s = r##"{
"items": [
{
"tag": "#AAAAAAAAA",
"name": "Player",
"nameColor": "0xfff05637",
"trophies": 30000,
"rank": 1,
"club": {
"name": "Scary Club"
}
},
{
"tag": "#EEEEEEE",
"name": "Also Player",
"nameColor": "0xffa2e3fe",
"trophies": 25000,
"rank": 2,
"club": {
"name": "Another Club"
}
},
{
"tag": "#QQQQQQQ",
"name": "Youtuber",
"nameColor": "0xfff05637",
"trophies": 23000,
"rank": 3,
"club": {
"name": "Different Club"
}
},
{
"tag": "#55555553Q",
"name": "Not a valid player",
"nameColor": "0xfff9cf08",
"trophies": 20000,
"rank": 4,
"club": {
"name": "Different Club"
}
}
],
"paging": {
"cursors": {}
}
}"##;
let p_leaders = serde_json::from_str::<PlayerLeaderboard>(rp_json_s)
.map_err(Error::Json)?;
assert_eq!(
p_leaders,
PlayerLeaderboard {
items: vec![
PlayerRanking {
tag: String::from("#AAAAAAAAA"),
name: String::from("Player"),
name_color: 0xfff05637,
trophies: 30000,
rank: 1,
club: PlayerRankingClub {
name: String::from("Scary Club")
}
},
PlayerRanking {
tag: String::from("#EEEEEEE"),
name: String::from("Also Player"),
name_color: 0xffa2e3fe,
trophies: 25000,
rank: 2,
club: PlayerRankingClub {
name: String::from("Another Club")
}
},
PlayerRanking {
tag: String::from("#QQQQQQQ"),
name: String::from("Youtuber"),
name_color: 0xfff05637,
trophies: 23000,
rank: 3,
club: PlayerRankingClub {
name: String::from("Different Club")
}
},
PlayerRanking {
tag: String::from("#55555553Q"),
name: String::from("Not a valid player"),
name_color: 0xfff9cf08,
trophies: 20000,
rank: 4,
club: PlayerRankingClub {
name: String::from("Different Club")
}
}
]
}
);
Ok(())
}
}