url-sanitize-core 2.0.2

Pure-Rust library for removing tracking parameters and unwrapping tracking redirects.
Documentation
use serde::Deserialize;

use crate::compile::Sanitizer;
use crate::types::{RuleSource, SanitizerOptions, SanitizerRule};

#[derive(Debug, Deserialize)]
pub struct Catalog {
    pub version: String,
    #[serde(rename = "generatedAt")]
    pub generated_at: String,
    pub sources: Vec<CatalogSource>,
    pub rules: Vec<SanitizerRule>,
}

#[derive(Debug, Deserialize)]
pub struct CatalogSource {
    pub name: RuleSource,
    #[serde(default)]
    pub version: Option<String>,
    #[serde(default)]
    pub hash: Option<String>,
    #[serde(default)]
    pub license: Option<String>,
    #[serde(default)]
    pub upstream: Option<String>,
}

#[derive(Debug)]
pub struct CatalogParseError(pub serde_json::Error);

impl std::fmt::Display for CatalogParseError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "catalog parse error: {}", self.0)
    }
}

impl std::error::Error for CatalogParseError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        Some(&self.0)
    }
}

impl Catalog {
    pub fn from_json(s: &str) -> Result<Self, CatalogParseError> {
        serde_json::from_str(s).map_err(CatalogParseError)
    }

    pub fn compile(&self, options: SanitizerOptions) -> Sanitizer {
        Sanitizer::compile(&self.rules, options)
    }

    pub fn catalog_hash(&self) -> Option<&str> {
        self.sources.first().and_then(|s| s.hash.as_deref())
    }

    pub fn catalog_identity(&self) -> String {
        let hashes: Vec<&str> = self
            .sources
            .iter()
            .filter_map(|s| s.hash.as_deref())
            .collect();
        if hashes.is_empty() {
            self.version.clone()
        } else {
            hashes.join(":")
        }
    }

    pub fn generated_at(&self) -> &str {
        &self.generated_at
    }
}