Skip to main content

weft_core/app/
registry.rs

1use crate::app::state::ResolvedAppMap;
2use crate::package::DiscoveredPackage;
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7pub struct CapabilityProviderRecord {
8    pub provider: String,
9    pub runtime: String,
10    #[serde(default)]
11    pub priority: i32,
12}
13
14#[derive(Debug, Clone, Serialize, Deserialize, Default)]
15pub struct CapabilityBindingRecord {
16    pub app: String,
17    pub provider: String,
18}
19
20#[derive(Debug, Clone, Serialize, Deserialize, Default)]
21pub struct CapabilityRegistryEntry {
22    pub capability: String,
23    pub providers: Vec<CapabilityProviderRecord>,
24    pub bindings: Vec<CapabilityBindingRecord>,
25}
26
27pub type CapabilityRegistry = HashMap<String, CapabilityRegistryEntry>;
28
29pub fn build_capability_registry(
30    packages: &[DiscoveredPackage],
31    apps: &ResolvedAppMap,
32) -> CapabilityRegistry {
33    let mut registry: CapabilityRegistry = HashMap::new();
34
35    for package in packages {
36        for capability in package.manifest.resolved_provides() {
37            let entry =
38                registry
39                    .entry(capability.clone())
40                    .or_insert_with(|| CapabilityRegistryEntry {
41                        capability: capability.clone(),
42                        ..Default::default()
43                    });
44
45            entry.providers.push(CapabilityProviderRecord {
46                provider: package.manifest.package_info.name.clone(),
47                runtime: package.runtime.as_str().to_string(),
48                priority: package
49                    .manifest
50                    .package
51                    .as_ref()
52                    .and_then(|package| package.priority)
53                    .unwrap_or(0),
54            });
55        }
56    }
57
58    for (app_name, app) in apps {
59        for binding in &app.bindings {
60            let entry = registry
61                .entry(binding.capability.clone())
62                .or_insert_with(|| CapabilityRegistryEntry {
63                    capability: binding.capability.clone(),
64                    ..Default::default()
65                });
66
67            entry.bindings.push(CapabilityBindingRecord {
68                app: app_name.clone(),
69                provider: binding.provider.clone(),
70            });
71        }
72    }
73
74    for entry in registry.values_mut() {
75        entry.providers.sort_by(|left, right| {
76            right
77                .priority
78                .cmp(&left.priority)
79                .then(left.provider.cmp(&right.provider))
80        });
81        entry.providers.dedup_by(|left, right| {
82            left.provider == right.provider && left.runtime == right.runtime
83        });
84
85        entry.bindings.sort_by(|left, right| {
86            left.app
87                .cmp(&right.app)
88                .then(left.provider.cmp(&right.provider))
89        });
90        entry
91            .bindings
92            .dedup_by(|left, right| left.app == right.app && left.provider == right.provider);
93    }
94
95    registry
96}