//! Types for the F-Droid repository index. use std::collections::HashMap; use serde::{Deserialize, Deserializer}; pub(super) const PHONE_DEVICE_TYPE: &str = "phone"; pub(super) const EN_LOCALE: &str = "en-US"; #[derive(Debug, Deserialize)] pub(super) struct Index { pub(super) repo: Repo, pub(super) packages: HashMap, } #[derive(Debug, Deserialize)] pub(super) struct Repo { pub(super) timestamp: u64, } #[derive(Debug, Deserialize)] pub(super) struct Package { pub(super) metadata: Metadata, /// Releases keyed by the APK's SHA-256 digest. pub(super) versions: HashMap, } #[derive(Debug, Deserialize)] pub(super) struct Version { /// Anti-feature explanations keyed first by anti-feature name and then by locale. #[serde(default, rename = "antiFeatures")] pub(super) anti_features: HashMap>, } /// An [anti-feature](https://f-droid.org/docs/Anti-Features/). #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub(super) enum AntiFeature { Ads, DisabledAlgorithm, KnownVuln, NoSourceSince, NonFreeAdd, NonFreeAssets, NonFreeDep, NonFreeNet, TetheredNet, Tracking, Other(String), } impl<'de> Deserialize<'de> for AntiFeature { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { let name = String::deserialize(deserializer)?; Ok(match name.as_str() { "Ads" => Self::Ads, "DisabledAlgorithm" => Self::DisabledAlgorithm, "KnownVuln" => Self::KnownVuln, "NoSourceSince" => Self::NoSourceSince, "NonFreeAdd" => Self::NonFreeAdd, "NonFreeAssets" => Self::NonFreeAssets, "NonFreeDep" => Self::NonFreeDep, "NonFreeNet" => Self::NonFreeNet, "TetheredNet" => Self::TetheredNet, "Tracking" => Self::Tracking, _ => { tracing::warn!("observed unknown F-Droid anti-feature {name}"); Self::Other(name) } }) } } #[derive(Debug, Deserialize)] pub(super) struct Metadata { pub(super) added: u64, /// App names keyed by locale. Every package has an `en-US` name. #[serde(default)] pub(super) name: HashMap, /// Short app descriptions keyed by locale. #[serde(default)] pub(super) summary: HashMap, /// Screenshots keyed first by device type and then by locale. #[serde(default)] pub(super) screenshots: HashMap>>, } #[derive(Debug, Deserialize)] pub(super) struct Screenshot { /// Path to the screenshot relative to the repository address. pub(super) name: String, /// Screenshot file size in bytes, retained for enforcing upload limits. #[allow(dead_code)] pub(super) size: u64, }