icecast-stats 0.2.3

Decode icecast server information from JSON
Documentation
use crate::IcecastStatsSource;
use serde::{Deserialize, Serialize};

#[cfg(feature = "chrono")]
use crate::parser::parse_datetime;
#[cfg(feature = "chrono")]
use chrono::{DateTime, FixedOffset};

/// Root element of the icecast information
#[derive(Serialize, Deserialize, Debug)]
pub struct IcecastStatsRoot {
    pub icestats: IcecastStats,
}

/// Basic server information
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct IcecastStats {
    admin: String,
    #[serde(rename = "banned_IPs")]
    banned_ips: Option<u32>,
    client_connections: Option<u32>,
    clients: Option<u32>,
    connections: Option<u32>,
    file_connections: Option<u32>,
    host: String,
    listener_connections: Option<u32>,
    listeners: Option<u32>,
    location: String,
    server_id: String,
    source_client_connections: Option<u32>,
    source_relay_connections: Option<u32>,
    source_total_connections: Option<u32>,
    sources: Option<u32>,
    stats: Option<u32>,
    stats_connections: Option<u32>,
    server_start: Option<String>,
    server_start_iso8601: Option<String>,

    /// List of active streaming sources
    source: Option<IcecastStatsSourceEnum>,
}

impl IcecastStats {
    /// As set in the server config, this should contain contact details for getting in touch
    /// with the server administrator. Usually this will be an email address, but as
    /// this can be an arbitrary string it could also be a phone number.
    ///
    /// Example: icemaster@localhost
    pub fn admin(&self) -> &String {
        &self.admin
    }

    /// Client connections are basically anything that is not a source connection. These include listeners (not concurrent, but cumulative), any admin function accesses, and any static content (file serving) accesses.
    /// This is an accumulating counter.
    pub fn client_connections(&self) -> &Option<u32> {
        &self.client_connections
    }

    /// Number of currently active client connections.
    pub fn clients(&self) -> &Option<u32> {
        &self.clients
    }

    /// The total of all inbound TCP connections since start-up.
    /// This is an accumulating counter.
    pub fn connections(&self) -> &Option<u32> {
        &self.connections
    }

    /// This is an accumulating counter.
    pub fn file_connections(&self) -> &Option<u32> {
        &self.file_connections
    }

    /// As set in the server config, this should be the full DNS resolveable name or FQDN for the host on which this Icecast instance is running.
    ///
    /// Example: localhost
    pub fn host(&self) -> &String {
        &self.host
    }

    /// Number of listener connections to mount points.
    /// This is an accumulating counter.
    pub fn listener_connections(&self) -> &Option<u32> {
        &self.listener_connections
    }

    /// Number of currently active listener connections.
    pub fn listeners(&self) -> &Option<u32> {
        &self.listeners
    }

    /// As set in the server config, this is a free form field that should describe e.g. the physical location of this server.
    ///
    /// Example: Earth
    pub fn location(&self) -> &String {
        &self.location
    }

    /// Defaults to the version string of the currently running Icecast server. While not recommended it can be overriden in the server config.
    ///
    /// Example: Icecast 2.4.4
    pub fn server_id(&self) -> &String {
        &self.server_id
    }

    /// Source client connections are the number of times (cumulative since start-up, not just currently connected) a source client has connected to Icecast.
    /// This is an accumulating counter.
    pub fn source_client_connections(&self) -> &Option<u32> {
        &self.source_client_connections
    }

    /// Number of outbound relay connections to (master) icecast servers.
    /// This is an accumulating counter.
    pub fn source_relay_connections(&self) -> &Option<u32> {
        &self.source_relay_connections
    }

    /// Both clients and relays.
    /// This is an accumulating counter.
    pub fn source_total_connections(&self) -> &Option<u32> {
        &self.source_total_connections
    }

    /// The total of currently connected sources.
    pub fn sources(&self) -> &Option<u32> {
        &self.sources
    }

    /// The total of currently connected STATS clients.
    pub fn stats(&self) -> &Option<u32> {
        &self.stats
    }

    /// Number of times a stats client has connected to Icecast.
    /// This is an accumulating counter.
    pub fn stats_connections(&self) -> &Option<u32> {
        &self.stats_connections
    }

    /// Timestamp of server startup as unformated string from the server.
    ///
    /// Example: 2021-04-09T21:49:50+0200
    pub fn server_start(&self) -> Option<&String> {
        if self.server_start_iso8601.is_some() {
            return self.server_start_iso8601.as_ref();
        }
        self.server_start.as_ref()
    }

    /// Timestamp of server startup as decoded Chrono object
    ///
    #[cfg(feature = "chrono")]
    pub fn server_start_decoded(
        &self,
    ) -> Option<Result<DateTime<FixedOffset>, chrono::ParseError>> {
        self.server_start().clone().map(|x| parse_datetime(&x))
    }

    /// Returns clones of all sources
    pub fn sources_vec(&self) -> Vec<IcecastStatsSource> {
        match &self.source {
            Some(source_enum) => match source_enum {
                IcecastStatsSourceEnum::Single(icecast_stats_source) => {
                    vec![icecast_stats_source.clone()]
                }
                IcecastStatsSourceEnum::Multiple(list) => list.clone(),
            },
            None => vec![],
        }
    }
}

/// Multiple variants of sources
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(untagged)]
pub enum IcecastStatsSourceEnum {
    Single(IcecastStatsSource),
    Multiple(Vec<IcecastStatsSource>),
}