use std::cell::RefCell;
use std::rc::Rc;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct NetworkStatus {
pub online: bool,
pub metered: bool,
}
impl Default for NetworkStatus {
fn default() -> Self {
Self {
online: true,
metered: false,
}
}
}
pub trait NetworkMonitor {
fn status(&self) -> NetworkStatus;
}
pub type NetworkMonitorRef = Rc<dyn NetworkMonitor>;
struct DefaultNetworkMonitor;
impl NetworkMonitor for DefaultNetworkMonitor {
fn status(&self) -> NetworkStatus {
NetworkStatus::default()
}
}
thread_local! {
static PLATFORM_NETWORK_MONITOR: RefCell<Option<NetworkMonitorRef>> = const { RefCell::new(None) };
}
pub fn set_platform_network_monitor(monitor: NetworkMonitorRef) {
PLATFORM_NETWORK_MONITOR.with(|cell| *cell.borrow_mut() = Some(monitor));
}
pub fn clear_platform_network_monitor() {
PLATFORM_NETWORK_MONITOR.with(|cell| *cell.borrow_mut() = None);
}
pub fn network_monitor() -> NetworkMonitorRef {
PLATFORM_NETWORK_MONITOR
.with(|cell| cell.borrow().clone())
.unwrap_or_else(|| Rc::new(DefaultNetworkMonitor))
}
pub fn network_status() -> NetworkStatus {
network_monitor().status()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_is_online_unmetered_and_overridable() {
clear_platform_network_monitor();
assert_eq!(
network_status(),
NetworkStatus {
online: true,
metered: false
}
);
struct Metered;
impl NetworkMonitor for Metered {
fn status(&self) -> NetworkStatus {
NetworkStatus {
online: true,
metered: true,
}
}
}
set_platform_network_monitor(Rc::new(Metered));
assert!(network_status().metered);
clear_platform_network_monitor();
}
}