coc-rs 0.8.4

A Rust crate wrapper around the Clash of Clans public API
Documentation
use base64::{
    alphabet,
    engine::{self, general_purpose},
    Engine as _,
};
use serde::{Deserialize, Serialize};

pub(crate) const BASE64_ENGINE: engine::GeneralPurpose =
    engine::GeneralPurpose::new(&alphabet::URL_SAFE, general_purpose::NO_PAD);

#[derive(Debug, Serialize, Deserialize)]
pub struct Paging {
    #[serde(rename = "cursors")]
    cursor: Cursor,
}

impl std::fmt::Display for Paging {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        writeln!(f, "Paging {{ ")?;
        writeln!(f, "cursor: {}", self.cursor)?;
        writeln!(f, "}}")
    }
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Cursor {
    before: Option<String>,
    after: Option<String>,
}

impl std::fmt::Display for Cursor {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        writeln!(f, "Cursor {{ ")?;
        if let Some(before) = &self.before {
            writeln!(f, "before: {before}")?;
        }
        if let Some(after) = &self.after {
            writeln!(f, "after: {after}")?;
        }
        writeln!(f, "}}")
    }
}

pub struct PagingBuilder {
    paging: Paging,
}

impl PagingBuilder {
    const fn new() -> Self {
        Self { paging: Paging { cursor: Cursor { before: None, after: None } } }
    }

    #[must_use]
    pub fn before(mut self, before: i32) -> Self {
        self.paging.cursor.set_before(before);
        self
    }

    #[must_use]
    pub fn after(mut self, after: i32) -> Self {
        self.paging.cursor.set_after(after);
        self
    }

    #[must_use]
    pub fn build(self) -> Paging {
        self.paging
    }
}

impl Paging {
    #[must_use]
    pub const fn new() -> Self {
        Self { cursor: Cursor::new() }
    }

    #[must_use]
    pub const fn is_some(&self) -> bool {
        self.cursor.is_some()
    }

    #[must_use]
    pub const fn is_none(&self) -> bool {
        self.cursor.is_none()
    }

    #[must_use]
    pub fn to_vec(&self) -> Vec<(&str, String)> {
        self.cursor.to_vec()
    }

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

impl Default for Paging {
    fn default() -> Self {
        Self::new()
    }
}

impl Cursor {
    #[must_use]
    pub const fn new() -> Self {
        Self { before: None, after: None }
    }

    fn set_before(&mut self, before: i32) {
        self.before = Some(BASE64_ENGINE.encode(format!("{{\"pos\":{before}}}")));
    }

    fn set_after(&mut self, after: i32) {
        self.after = Some(BASE64_ENGINE.encode(format!("{{\"pos\":{after}}}")));
    }

    #[must_use]
    pub const fn is_some(&self) -> bool {
        self.before.is_some() || self.after.is_some()
    }

    #[must_use]
    pub const fn is_none(&self) -> bool {
        self.before.is_none() && self.after.is_none()
    }

    #[must_use]
    pub fn to_vec(&self) -> Vec<(&str, String)> {
        let mut vec = Vec::new();
        if let Some(ref before) = self.before {
            vec.push(("before", before.clone()));
        }
        if let Some(ref after) = self.after {
            vec.push(("after", after.clone()));
        }
        vec
    }
}

impl Default for Cursor {
    fn default() -> Self {
        Self::new()
    }
}