pub mod constants;
pub mod refs;
#[cfg(feature = "fetch")]
mod cache;
#[cfg(feature = "fetch")]
mod download;
#[cfg(feature = "fetch")]
pub use download::ProgressCallback;
pub use refs::JplDatasetId;
#[cfg(feature = "fetch")]
use crate::error::ArchiveError;
#[cfg(feature = "fetch")]
use refs::JplDatasetMeta;
#[cfg(feature = "fetch")]
use std::path::{Path, PathBuf};
#[cfg(feature = "fetch")]
pub struct DatasetManager {
data_dir: PathBuf,
}
#[cfg(feature = "fetch")]
impl DatasetManager {
pub fn new() -> Result<Self, ArchiveError> {
let data_dir = cache::resolve_data_dir()?;
cache::ensure_data_dir(&data_dir)?;
Ok(Self { data_dir })
}
pub fn with_dir(dir: impl Into<PathBuf>) -> Result<Self, ArchiveError> {
let data_dir = dir.into();
cache::ensure_data_dir(&data_dir)?;
Ok(Self { data_dir })
}
pub fn data_dir(&self) -> &Path {
&self.data_dir
}
pub fn is_available(&self, id: JplDatasetId) -> bool {
cache::is_cached(&self.data_dir, id.meta())
}
pub fn load_path(&self, id: JplDatasetId) -> Option<PathBuf> {
if cache::is_cached(&self.data_dir, id.meta()) {
Some(cache::dataset_path(&self.data_dir, id.meta()))
} else {
None
}
}
pub fn ensure(&self, id: JplDatasetId) -> Result<PathBuf, ArchiveError> {
let meta = id.meta();
let path = cache::dataset_path(&self.data_dir, meta);
if cache::is_cached(&self.data_dir, meta) {
cache::verify(meta.name, &path, meta)?;
return Ok(path);
}
self.download_inner(meta, &path, None)?;
Ok(path)
}
pub fn download(
&self,
id: JplDatasetId,
progress: Option<ProgressCallback>,
) -> Result<PathBuf, ArchiveError> {
let meta = id.meta();
let path = cache::dataset_path(&self.data_dir, meta);
self.download_inner(meta, &path, progress)?;
Ok(path)
}
pub fn list(&self) -> Vec<(JplDatasetId, bool)> {
refs::ALL_DATASETS
.iter()
.map(|&id| (id, self.is_available(id)))
.collect()
}
fn download_inner(
&self,
meta: &'static JplDatasetMeta,
path: &Path,
progress: Option<ProgressCallback>,
) -> Result<(), ArchiveError> {
download::download(meta.name, meta, path, progress)?;
cache::verify(meta.name, path, meta)?;
Ok(())
}
}
#[cfg(all(feature = "fetch", test))]
mod tests {
use super::*;
fn temp_dir(suffix: &str) -> PathBuf {
std::env::temp_dir().join(format!("siderust_archive_jpl_{suffix}"))
}
#[test]
fn with_dir_creates_manager() {
let dir = temp_dir("with_dir");
let _ = std::fs::remove_dir_all(&dir);
let dm = DatasetManager::with_dir(&dir).unwrap();
assert_eq!(dm.data_dir(), dir.as_path());
std::fs::remove_dir_all(&dir).ok();
}
#[test]
fn is_available_returns_false_when_not_cached() {
let dir = temp_dir("not_cached");
let _ = std::fs::remove_dir_all(&dir);
let dm = DatasetManager::with_dir(&dir).unwrap();
assert!(!dm.is_available(JplDatasetId::De440));
std::fs::remove_dir_all(&dir).ok();
}
#[test]
fn list_returns_de440_and_de441() {
let dir = temp_dir("list_test");
let dm = DatasetManager::with_dir(&dir).unwrap();
let items = dm.list();
assert_eq!(items.len(), 2);
assert!(items.iter().any(|(id, _)| *id == JplDatasetId::De440));
assert!(items.iter().any(|(id, _)| *id == JplDatasetId::De441));
std::fs::remove_dir_all(&dir).ok();
}
}