use serde::{Deserialize, Deserializer, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct HfModelInfo {
pub id: String,
pub model_id: Option<String>,
#[serde(default)]
pub sha: Option<String>,
#[serde(default)]
pub pipeline_tag: Option<String>,
#[serde(default)]
pub library_name: Option<String>,
#[serde(default)]
pub tags: Vec<String>,
#[serde(default)]
pub downloads: u64,
#[serde(default)]
pub likes: u64,
#[serde(default)]
pub private: bool,
#[serde(default, deserialize_with = "deserialize_gated")]
pub gated: Option<String>,
#[serde(default)]
pub last_modified: Option<String>,
#[serde(default)]
pub card_data: Option<serde_json::Value>,
#[serde(default)]
pub siblings: Option<Vec<HfRepoFile>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HfRepoFile {
#[serde(rename = "rfilename")]
pub filename: String,
#[serde(default)]
pub size: Option<u64>,
#[serde(default)]
pub lfs: Option<HfLfsInfo>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct HfLfsInfo {
pub size: u64,
pub oid: String,
#[serde(default)]
pub pointer_size: Option<u64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HfTreeEntry {
#[serde(rename = "type")]
pub entry_type: String,
pub oid: String,
pub size: u64,
pub path: String,
#[serde(default)]
pub lfs: Option<HfLfsInfo>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModelScanResult {
pub model_id: String,
pub total_probes: u64,
pub findings_count: u64,
pub max_severity: String,
pub findings: Vec<ModelFinding>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModelFinding {
pub id: String,
pub severity: String,
pub category: String,
pub title: String,
pub description: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PipelineStatus {
pub id: u64,
pub status: String,
pub r#ref: String,
pub web_url: String,
#[serde(default)]
pub created_at: Option<String>,
#[serde(default)]
pub updated_at: Option<String>,
#[serde(default)]
pub finished_at: Option<String>,
}
fn deserialize_gated<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
where
D: Deserializer<'de>,
{
let value: serde_json::Value = Deserialize::deserialize(deserializer)?;
match value {
serde_json::Value::String(s) => Ok(Some(s)),
serde_json::Value::Bool(false) | serde_json::Value::Null => Ok(None),
serde_json::Value::Bool(true) => Ok(Some("true".to_string())),
_ => Ok(None),
}
}