weft_core/app/
registry.rs1use 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}