use anyhow::{Context, Result};
use chrono::Utc;
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::Path;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IndexMetadata {
pub schema_signature: String,
pub model_id: String,
pub created_at: String,
}
impl IndexMetadata {
pub fn expected(schema_signature: String, model_id: &str) -> Self {
Self {
schema_signature,
model_id: model_id.to_string(),
created_at: Utc::now().to_rfc3339(),
}
}
pub fn matches(&self, other: &IndexMetadata) -> bool {
self.schema_signature == other.schema_signature && self.model_id == other.model_id
}
}
pub fn read_metadata(path: &Path) -> Result<Option<IndexMetadata>> {
if !path.exists() {
return Ok(None);
}
let content = fs::read_to_string(path)
.with_context(|| format!("Failed to read index metadata at {:?}", path))?;
match serde_json::from_str::<IndexMetadata>(&content) {
Ok(meta) => Ok(Some(meta)),
Err(_) => Ok(None),
}
}
pub fn write_metadata(path: &Path, meta: &IndexMetadata) -> Result<()> {
if let Some(parent) = path.parent() {
fs::create_dir_all(parent)?;
}
let content = serde_json::to_string_pretty(meta)?;
fs::write(path, content)
.with_context(|| format!("Failed to write index metadata at {:?}", path))?;
Ok(())
}