summaryrefslogtreecommitdiff
path: root/src/model/player.rs
blob: bd765a1f7d02f7d7de355dbe27b8609cc5560d35 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use std::ops::{Deref, DerefMut};

use compact_str::CompactString;
use serde::Deserialize;
use time::{Date, OffsetDateTime};

use crate::model::{team::CompactTeam, VideoGame};

#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize)]
#[non_exhaustive]
pub struct Player {
    #[serde(flatten)]
    pub inner: CompactPlayer,

    pub current_team: Option<CompactTeam>,
    #[serde(rename = "current_videogame")]
    pub current_video_game: Option<VideoGame>,
}

#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize)]
#[non_exhaustive]
pub struct CompactPlayer {
    /// Whether player is active.
    pub active: bool,
    /// Age of the player, null if unknown. When `birthday` is null, age is an approxiamation.
    /// Note: this field is only present for users running the Historical plan or up.
    pub age: Option<u8>,
    /// Birthday of the player.
    /// Note: this field is only present for users running the Historical plan or up.
    #[serde(with = "birthday_format", default)]
    pub birthday: Option<Date>,
    /// First name of the player.
    pub first_name: Option<CompactString>,
    /// ID of the player.
    pub id: u64,
    /// URL to the photo of the player.
    pub image_url: Option<String>,
    /// Last name of the player.
    pub last_name: Option<CompactString>,
    #[serde(with = "time::serde::iso8601")]
    pub modified_at: OffsetDateTime,
    /// Professional name of the player.
    pub name: String,
    /// Country code matching the nationality of the player according to the ISO 3166-1 standard (Alpha-2 code).
    /// In addition to the standard, the XK code is used for Kosovo.
    pub nationality: Option<CompactString>,
    /// Role/position of the player. Field value varies depending on the video game.
    /// Note: role is only available for DOTA 2, League of Legends, and Overwatch players.
    pub role: Option<CompactString>,
    /// Unique, human-readable identifier for the player.
    /// `id` and `slug` can be used interchangeably throughout the API.
    pub slug: Option<CompactString>,
}

/// Equivalent to below, but works when `null` is present in the JSON.
/// ```
/// time::serde::format_description!(birthday_format, Date, "[year]-[month]-[day]");
/// ```
mod birthday_format {
    use serde::Deserialize;
    use time::{format_description::BorrowedFormatItem, Date};

    const FORMAT: &[BorrowedFormatItem<'static>] =
        time::macros::format_description!("[year]-[month]-[day]");

    pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Date>, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let s: Option<&'de str> = Deserialize::deserialize(deserializer)?;
        s.map(|s| Date::parse(s, FORMAT).map_err(serde::de::Error::custom))
            .transpose()
    }
}

impl Deref for Player {
    type Target = CompactPlayer;

    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}

impl DerefMut for Player {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.inner
    }
}

impl AsRef<CompactPlayer> for Player {
    fn as_ref(&self) -> &CompactPlayer {
        &self.inner
    }
}

impl AsMut<CompactPlayer> for Player {
    fn as_mut(&mut self) -> &mut CompactPlayer {
        &mut self.inner
    }
}

impl From<Player> for CompactPlayer {
    fn from(player: Player) -> Self {
        player.inner
    }
}