milsymbol-rs 0.3.2

A Rust wrapper for the milsymbol JavaScript library to generate military symbols (MIL-STD-2525 and APP-6).
use crate::error::MilsymbolError;
use crate::options::MilsymbolOptions;
use crate::types::DrawInstruction;
use crate::{SidcEntitiesAndModifiers, SidcMetadata, SymbolOutput};
use eyre::Result;
use std::collections::HashMap;
use std::sync::{Mutex, OnceLock};
use std::time::Instant;

pub(crate) enum CacheData {
    Output(Box<SymbolOutput>),
    IsValid(Box<bool>),
    ValidationDetails(Box<crate::types::ValidationDetails>),
    Colors(Box<crate::types::SymbolColors>),
    SymbolMetadata(Box<crate::types::SymbolMetadata>),
    Style(Box<crate::types::SymbolStyle>),
    DrawInstructions(Vec<DrawInstruction>),
    #[cfg(feature = "image")]
    Image(Box<image::DynamicImage>),
}

/// Cache item holds timestamped data structure
pub(crate) struct CacheItem {
    pub(crate) data: CacheData,
    pub(crate) last_accessed: Instant,
}

pub(crate) type CacheKey = (&'static str, String, String);

pub(crate) struct SymbolCache {
    pub(crate) map: HashMap<CacheKey, CacheItem>,
}

impl SymbolCache {
    pub fn new() -> Self {
        Self {
            map: HashMap::new(),
        }
    }

    pub fn clear(&mut self) {
        self.map.clear();
    }

    pub fn remove(&mut self, sidc: &str, options: &MilsymbolOptions) -> Result<()> {
        let options_json =
            serde_json::to_string(options).map_err(MilsymbolError::SerializationError)?;
        let sidc_string = sidc.to_string();

        self.map
            .remove(&("output", sidc_string.clone(), options_json.clone()));
        self.map
            .remove(&("is_valid", sidc_string.clone(), options_json.clone()));
        self.map.remove(&(
            "validation_details",
            sidc_string.clone(),
            options_json.clone(),
        ));
        self.map
            .remove(&("colors", sidc_string.clone(), options_json.clone()));
        self.map
            .remove(&("symbol_metadata", sidc_string.clone(), options_json.clone()));
        self.map
            .remove(&("style", sidc_string.clone(), options_json.clone()));
        self.map.remove(&(
            "draw_instructions",
            sidc_string.clone(),
            options_json.clone(),
        ));
        #[cfg(feature = "image")]
        self.map.remove(&("image", sidc_string, options_json));

        Ok(())
    }
}

/// Cache for the version information for the underlying `milsymbol` JavaScript library.
pub(crate) static VERSION_CACHE: OnceLock<String> = OnceLock::new();

/// Cache for the SIDC metadata.
pub(crate) static METADATA_CACHE: OnceLock<SidcMetadata> = OnceLock::new();
/// Cache for the SIDC entities and modifiers.
pub(crate) static ENTITIES_CACHE: OnceLock<Mutex<HashMap<String, SidcEntitiesAndModifiers>>> =
    OnceLock::new();