busylib 0.0.6

BUSY Bar Rust HTTP client
Documentation
//! BUSY timer schemas

use serde::{Deserialize, Serialize};

/// Timer snapshot and the moment it was taken
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BusySnapshot {
    pub snapshot: Snapshot,
    pub snapshot_timestamp_ms: u64,
}

/// Timer state and the bar settings it runs with
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Snapshot {
    #[serde(flatten)]
    pub state: TimerState,
    pub busy_bar_settings: BusyBarSettings,
}

/// What the timer is currently doing
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum TimerState {
    #[serde(rename = "NOT_STARTED")]
    NotStarted,
    #[serde(rename = "INFINITE")]
    Infinite { card_id: String, is_paused: bool },
    #[serde(rename = "SIMPLE")]
    Simple {
        card_id: String,
        time_left_ms: u64,
        is_paused: bool,
    },
    #[serde(rename = "INTERVAL")]
    Interval {
        card_id: String,
        current_interval: u32,
        current_interval_time_total_ms: u64,
        current_interval_time_left_ms: u64,
        is_paused: bool,
        #[serde(with = "tagged_interval_settings")]
        interval_settings: BusyTimerIntervalSettings,
    },
}

/// Stored timer profile
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BusyProfile {
    pub id: String,
    pub title: String,
    pub sort_order: i32,
    pub timer_settings: TimerSettings,
    pub busy_bar_settings: BusyBarSettings,
    pub profile_timestamp_ms: u64,
}

/// Slot a profile is stored in
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum BusyProfileSlot {
    Busy,
    Custom,
}

impl BusyProfileSlot {
    pub fn as_str(self) -> &'static str {
        match self {
            BusyProfileSlot::Busy => "busy",
            BusyProfileSlot::Custom => "custom",
        }
    }
}

/// How a timer counts
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum TimerSettings {
    #[serde(rename = "INFINITE")]
    Infinite,
    #[serde(rename = "SIMPLE")]
    Simple { total_time_ms: u64 },
    #[serde(rename = "INTERVAL")]
    Interval {
        interval_work_ms: u64,
        interval_rest_ms: u64,
        interval_work_cycles_count: u32,
        is_autostart_enabled: bool,
    },
}

impl TimerSettings {
    pub fn interval(settings: BusyTimerIntervalSettings) -> Self {
        Self::Interval {
            interval_work_ms: settings.interval_work_ms,
            interval_rest_ms: settings.interval_rest_ms,
            interval_work_cycles_count: settings.interval_work_cycles_count,
            is_autostart_enabled: settings.is_autostart_enabled,
        }
    }
}

/// Work and rest intervals of an interval timer
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct BusyTimerIntervalSettings {
    pub interval_work_ms: u64,
    pub interval_rest_ms: u64,
    pub interval_work_cycles_count: u32,
    pub is_autostart_enabled: bool,
}

/// How the bar presents a running timer
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BusyBarSettings {
    pub theme: String,
    pub show_work_phase_only: bool,
    pub trigger_smart_home: bool,
}

// The device tags nested interval settings with the same `type` discriminator as
// standalone timer settings, so the tag is added and checked on the way through.
mod tagged_interval_settings {
    use serde::de::Error as _;
    use serde::{Deserialize, Deserializer, Serialize, Serializer};

    use super::{BusyTimerIntervalSettings, TimerSettings};

    pub fn serialize<S: Serializer>(
        value: &BusyTimerIntervalSettings,
        serializer: S,
    ) -> Result<S::Ok, S::Error> {
        TimerSettings::interval(*value).serialize(serializer)
    }

    pub fn deserialize<'de, D: Deserializer<'de>>(
        deserializer: D,
    ) -> Result<BusyTimerIntervalSettings, D::Error> {
        match TimerSettings::deserialize(deserializer)? {
            TimerSettings::Interval {
                interval_work_ms,
                interval_rest_ms,
                interval_work_cycles_count,
                is_autostart_enabled,
            } => Ok(BusyTimerIntervalSettings {
                interval_work_ms,
                interval_rest_ms,
                interval_work_cycles_count,
                is_autostart_enabled,
            }),
            _ => Err(D::Error::custom("expected INTERVAL timer settings")),
        }
    }
}