use std::sync::OnceLock;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum UnsupportedOptionPolicy {
Ignore,
Warn,
Strict,
}
static POLICY: OnceLock<UnsupportedOptionPolicy> = OnceLock::new();
pub fn set_unsupported_option_policy(policy: UnsupportedOptionPolicy) {
let _ = POLICY.set(policy);
}
pub fn unsupported_option_policy() -> UnsupportedOptionPolicy {
POLICY
.get()
.copied()
.unwrap_or(UnsupportedOptionPolicy::Warn)
}
pub fn report_unsupported(
backend: &str,
plot_type: &str,
option: &str,
collector: &mut Vec<String>,
) {
let key = format!("{plot_type}.{option}");
if collector.contains(&key) {
return;
}
let policy = unsupported_option_policy();
match policy {
UnsupportedOptionPolicy::Ignore => {}
UnsupportedOptionPolicy::Warn | UnsupportedOptionPolicy::Strict => {
eprintln!("{backend}: `{option}` on {plot_type} not supported; ignored");
}
}
collector.push(key);
}
pub fn enforce_strict(backend: &str, collector: &[String]) {
if unsupported_option_policy() == UnsupportedOptionPolicy::Strict && !collector.is_empty() {
panic!(
"{backend}: unsupported options encountered in Strict mode:\n - {}",
collector.join("\n - ")
);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_policy_is_warn() {
assert_eq!(unsupported_option_policy(), UnsupportedOptionPolicy::Warn);
}
#[test]
fn test_report_unsupported_deduplicates() {
let mut collector = Vec::new();
report_unsupported("test", "Scatter", "fill", &mut collector);
report_unsupported("test", "Scatter", "fill", &mut collector);
assert_eq!(collector.len(), 1);
}
#[test]
fn test_report_unsupported_different_options() {
let mut collector = Vec::new();
report_unsupported("test", "Scatter", "fill", &mut collector);
report_unsupported("test", "Scatter", "hover", &mut collector);
assert_eq!(collector.len(), 2);
}
#[test]
fn test_enforce_strict_with_empty_collector() {
enforce_strict("test", &[]);
}
}