coc-rs 0.8.4

A Rust crate wrapper around the Clash of Clans public API
Documentation
use serde::{Deserialize, Serialize};
use time::Month;

#[derive(Debug, Clone)]
pub enum SeasonError {
    InvalidSeason,
    ParseFailed(String),
}

#[derive(Debug, Clone)]
pub struct SeasonBuilder {
    season: Season,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Season {
    #[serde(rename = "id")]
    id: String,
    #[serde(skip_deserializing, skip_serializing)]
    year: i32,
    #[serde(skip_deserializing, skip_serializing, default = "Season::default_month")]
    month: Month,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct PreviousSeasonData {
    pub id: String,
    pub rank: i32,
    pub trophies: i32,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct BestSeasonData {
    pub id: String,
    pub rank: i32,
    pub trophies: i32,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct PreviousVersusSeasonData {
    pub id: String,
    pub rank: i32,
    pub trophies: i32,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct BestVersusSeasonData {
    pub id: String,
    pub rank: i32,
    pub trophies: i32,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct CurrentSeasonData {
    pub id: Option<String>,
    pub rank: Option<i32>,
    pub trophies: i32,
}

impl From<std::num::ParseIntError> for SeasonError {
    fn from(err: std::num::ParseIntError) -> Self {
        Self::ParseFailed(err.to_string())
    }
}

impl SeasonBuilder {
    const fn new() -> Self {
        Self { season: Season { id: String::new(), year: 2015, month: Month::July } }
    }

    #[must_use]
    pub const fn year(mut self, year: i32) -> Self {
        self.season.year = year;
        self
    }

    #[must_use]
    pub const fn month(mut self, month: Month) -> Self {
        self.season.month = month;
        self
    }

    #[must_use]
    pub fn build(mut self) -> Season {
        self.season.id = format!("{}-{:02}", self.season.year, self.season.month as i32);
        self.season
    }
}

impl Season {
    #[must_use]
    pub const fn default_month() -> Month {
        Month::July
    }

    #[must_use]
    pub const fn builder() -> SeasonBuilder {
        SeasonBuilder::new()
    }
}

impl std::str::FromStr for Season {
    type Err = SeasonError;

    fn from_str(season: &str) -> Result<Self, Self::Err> {
        let mut season_split = season.split('-');
        Ok(Self {
            id: season.to_string(),
            year: season_split.next().ok_or(SeasonError::InvalidSeason)?.parse()?,
            month: Month::try_from(
                season_split.next().ok_or(SeasonError::InvalidSeason)?.parse::<u8>()?,
            )
            .unwrap(),
        })
    }
}

impl std::fmt::Display for Season {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        let mut season_split = self.id.split('-');
        let year = season_split.next().unwrap().parse::<i32>().unwrap();
        let month = Month::try_from(season_split.next().unwrap().parse::<u8>().unwrap()).unwrap();
        write!(f, "{year}-{:02}", month as i32)
    }
}