Skip to main content

loadsmith_registry/
lib.rs

1//! Registry abstraction and built-in sources for the loadsmith mod-manager
2//! library.
3//!
4//! This is an internal crate of the [`loadsmith`] workspace. Most consumers
5//! should depend on the `loadsmith` facade crate instead of using this
6//! crate directly.
7
8use std::{collections::HashMap, fmt::Debug, pin::Pin};
9
10use loadsmith_core::{Checksum, Dependency, FileUrl, PackageId, PackageRef, Version};
11
12mod error;
13
14mod registries;
15
16pub use error::{Error, Result};
17pub use registries::*;
18use serde::de::DeserializeOwned;
19
20#[derive(Debug, Clone)]
21pub struct VersionInfo {
22    pub version: Version,
23}
24
25#[derive(Debug, Clone)]
26pub struct ResolvedVersion {
27    pub url: FileUrl,
28    pub size: Option<u64>,
29    pub checksum: Option<Checksum>,
30    pub deps: Vec<Dependency>,
31}
32
33pub trait Registry: Debug + Send + Sync {
34    fn version_info<'a>(
35        &'a self,
36        id: &'a PackageId,
37        metadata: Option<&'a serde_json::Value>,
38    ) -> Pin<Box<dyn Future<Output = Result<Vec<VersionInfo>>> + 'a>>;
39
40    fn resolve<'a>(
41        &'a self,
42        ref_: &'a PackageRef,
43        metadata: Option<&'a serde_json::Value>,
44    ) -> Pin<Box<dyn Future<Output = Result<ResolvedVersion>> + 'a>>;
45
46    fn revalidate_checksum<'a>(
47        &'a self,
48        ref_: &'a PackageRef,
49        metadata: Option<&'a serde_json::Value>,
50    ) -> Result<Option<Checksum>> {
51        let _ = (ref_, metadata);
52        Ok(None)
53    }
54}
55
56#[derive(Debug)]
57pub struct RegistrySet {
58    registries: HashMap<String, Box<dyn Registry>>,
59}
60
61impl Default for RegistrySet {
62    fn default() -> Self {
63        Self::new()
64    }
65}
66
67impl RegistrySet {
68    pub fn new() -> Self {
69        Self {
70            registries: HashMap::new(),
71        }
72    }
73
74    pub fn add<R: Registry + 'static>(&mut self, id: impl Into<String>, registry: R) {
75        self.registries.insert(id.into(), Box::new(registry));
76    }
77
78    pub fn get(&self, id: &str) -> Option<&dyn Registry> {
79        self.registries.get(id).map(|r| r.as_ref())
80    }
81}
82
83pub fn read_metadata_or_default<T: DeserializeOwned + Default>(
84    metadata: Option<&serde_json::Value>,
85) -> Result<T> {
86    match metadata {
87        Some(metadata) => read_metadata_some(metadata),
88        None => Ok(T::default()),
89    }
90}
91
92pub fn read_metadata<T: DeserializeOwned>(metadata: Option<&serde_json::Value>) -> Result<T> {
93    match metadata {
94        Some(metadata) => read_metadata_some(metadata),
95        None => Err(Error::MissingMetadata),
96    }
97}
98
99fn read_metadata_some<T: DeserializeOwned>(metadata: &serde_json::Value) -> Result<T> {
100    serde_json::from_value(metadata.clone()).map_err(Error::InvalidMetadata)
101}