brawl-rs 0.1.0

A Rust wrapper for the Brawl Stars API
Documentation
use crate::client::endpoints::Endpoint;
use crate::{BrawlClient, BrawlError};
use serde::Deserialize;

/// Collection of ranked clubs by region.
///
/// Contains a list of top clubs in a specific region, ordered by their trophy count.
/// Use the [`Rankings`] trait to fetch this data.
///
/// # Examples
///
/// ```no_run
/// use brawl_rs::prelude::*;
///
/// #[tokio::main]
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
///     let client = BrawlClient::new(std::env::var("BRAWL_TOKEN")?);
///     let rankings = RankingsClub::get(&client, "US").await?;
///     for club in &rankings.items {
///         println!("#{} - {} ({})", club.rank, club.name, club.trophies);
///     }
///     Ok(())
/// }
/// ```
#[derive(Deserialize)]
pub struct RankingsClub {
    pub items: Vec<RankingClub>,
}

/// Collection of ranked players by region.
///
/// Contains a list of top players in a specific region, ordered by their trophy count.
/// Use the [`Rankings`] trait to fetch this data.
///
/// # Examples
///
/// ```no_run
/// use brawl_rs::prelude::*;
///
/// #[tokio::main]
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
///     let client = BrawlClient::new(std::env::var("BRAWL_TOKEN")?);
///     let rankings = RankingsPlayer::get(&client, "US").await?;
///     for player in &rankings.items {
///         println!("#{} - {} ({})", player.rank, player.name, player.trophies);
///     }
///     Ok(())
/// }
/// ```
#[derive(Deserialize)]
pub struct RankingsPlayer {
    pub items: Vec<RankingPlayer>,
}

/// Information about a club in the rankings.
///
/// Represents a single club's ranking position with its statistics and identification.
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RankingClub {
    pub tag: String,
    pub name: String,
    pub badge_id: u32,
    pub trophies: u32,
    pub rank: u8,
    pub member_count: u8,
}

/// Information about a player in the rankings.
///
/// Represents a single player's ranking position with their statistics and club affiliation.
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RankingPlayer {
    pub tag: String,
    pub name: String,
    pub name_color: String,
    pub trophies: u32,
    pub rank: u8,
    pub club: Option<RankingPlayerClub>,
}

/// Information about a player's club in the rankings.
///
/// Contains basic information about the club that a ranked player belongs to.
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RankingPlayerClub {
    pub name: String,
}

/// Trait for fetching rankings data by region.
///
/// This trait provides a unified interface for fetching rankings of both clubs and players.
/// It's implemented for [`RankingsClub`] and [`RankingsPlayer`] types.
///
/// # Examples
///
/// Fetch club rankings:
/// ```no_run
/// use brawl_rs::prelude::*;
///
/// #[tokio::main]
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
///     let client = BrawlClient::new(std::env::var("BRAWL_TOKEN")?);
///     // Fetch top clubs in United States
///     let rankings = RankingsClub::get(&client, "US").await?;
///     println!("Total ranked clubs: {}", rankings.items.len());
///     Ok(())
/// }
/// ```
///
/// Fetch player rankings:
/// ```no_run
/// use brawl_rs::prelude::*;
///
/// #[tokio::main]
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
///     let client = BrawlClient::new(std::env::var("BRAWL_TOKEN")?);
///     // Fetch top players in Europe
///     let rankings = RankingsPlayer::get(&client, "EU").await?;
///     println!("Total ranked players: {}", rankings.items.len());
///     Ok(())
/// }
/// ```
pub trait Rankings
where
    Self: serde::de::DeserializeOwned,
{
    /// Returns the API endpoint for this ranking type.
    fn get_endpoint(code: String) -> Endpoint;

    /// Fetches rankings for a specific region.
    ///
    /// Retrieves the top-ranked clubs or players in a given region code.
    ///
    /// # Arguments
    ///
    /// * `client` - The [`BrawlClient`] to use for the request
    /// * `code` - The region code (e.g., "US", "EU", "AS", etc.)
    ///
    /// # Errors
    ///
    /// Returns [`BrawlError`] if:
    /// - The region code is invalid
    /// - Network communication fails
    /// - The API response cannot be parsed
    fn get(
        client: &BrawlClient,
        code: &str,
    ) -> impl std::future::Future<Output = Result<Self, BrawlError>> + Send {
        async {
            let endpoint = Self::get_endpoint(code.to_string());

            client.fetch::<Self>(endpoint).await
        }
    }
}

impl Rankings for RankingsClub {
    fn get_endpoint(code: String) -> Endpoint {
        Endpoint::RankingsClubs(code)
    }
}

impl Rankings for RankingsPlayer {
    fn get_endpoint(code: String) -> Endpoint {
        Endpoint::RankingsPlayers(code)
    }
}