wasmer_wasix/runtime/resolver/
outputs.rs1use std::{collections::BTreeMap, ops::Index, path::PathBuf};
2
3use petgraph::{
4 graph::{DiGraph, NodeIndex},
5 visit::EdgeRef,
6};
7use wasmer_config::package::PackageId;
8
9use crate::runtime::resolver::{DistributionInfo, PackageInfo};
10
11#[derive(Debug, Clone)]
12pub struct Resolution {
13 pub package: ResolvedPackage,
14 pub graph: DependencyGraph,
15}
16
17#[derive(Debug, Clone, PartialEq, Eq)]
18pub struct ItemLocation {
19 pub name: String,
21 pub package: PackageId,
23}
24
25#[derive(Debug, Clone)]
27pub struct DependencyGraph {
28 root: NodeIndex,
29 graph: DiGraph<Node, Edge>,
30 packages: BTreeMap<PackageId, NodeIndex>,
31}
32
33impl DependencyGraph {
34 pub(crate) fn new(
35 root: NodeIndex,
36 graph: DiGraph<Node, Edge>,
37 packages: BTreeMap<PackageId, NodeIndex>,
38 ) -> Self {
39 if cfg!(debug_assertions) {
40 for (id, index) in &packages {
43 let node = &graph[*index];
44 assert_eq!(*id, node.id, "Mismatch for node {index:?}");
45 }
46 }
47 debug_assert!(
48 packages.values().any(|ix| *ix == root),
49 "The packages mapping doesn't contain the root node"
50 );
51
52 DependencyGraph {
53 root,
54 graph,
55 packages,
56 }
57 }
58
59 pub fn root_info(&self) -> &PackageInfo {
60 let Node { pkg, .. } = &self.graph[self.root];
61 pkg
62 }
63
64 pub fn id(&self) -> &PackageId {
65 let Node { id, .. } = &self.graph[self.root];
66 id
67 }
68
69 pub fn root(&self) -> NodeIndex {
70 self.root
71 }
72
73 pub fn graph(&self) -> &DiGraph<Node, Edge> {
74 &self.graph
75 }
76
77 pub fn packages(&self) -> &BTreeMap<PackageId, NodeIndex> {
79 &self.packages
80 }
81
82 pub fn iter_dependencies(
85 &self,
86 ) -> impl Iterator<Item = (&'_ PackageId, BTreeMap<&'_ str, &'_ PackageId>)> + '_ {
87 self.packages.iter().map(move |(id, index)| {
88 let dependencies: BTreeMap<_, _> = self
89 .graph
90 .edges(*index)
91 .map(|edge_ref| {
92 (
93 edge_ref.weight().alias.as_str(),
94 &self.graph[edge_ref.target()].id,
95 )
96 })
97 .collect();
98 (id, dependencies)
99 })
100 }
101
102 pub fn visualise(&self) -> String {
104 let graph = self.graph.map(|_, node| &node.id, |_, edge| &edge.alias);
105 petgraph::dot::Dot::new(&graph).to_string()
106 }
107}
108
109impl Index<NodeIndex> for DependencyGraph {
110 type Output = Node;
111
112 #[track_caller]
113 fn index(&self, index: NodeIndex) -> &Self::Output {
114 &self.graph[index]
115 }
116}
117
118impl Index<&NodeIndex> for DependencyGraph {
119 type Output = Node;
120
121 #[track_caller]
122 fn index(&self, index: &NodeIndex) -> &Self::Output {
123 &self[*index]
124 }
125}
126
127impl Index<&PackageId> for DependencyGraph {
128 type Output = Node;
129
130 #[track_caller]
131 fn index(&self, index: &PackageId) -> &Self::Output {
132 let index = self.packages[index];
133 &self[index]
134 }
135}
136
137impl PartialEq for DependencyGraph {
138 fn eq(&self, other: &Self) -> bool {
139 let DependencyGraph {
140 root,
141 graph,
142 packages,
143 } = self;
144
145 let this_root = graph.node_weight(*root);
147 let other_root = other.graph.node_weight(other.root);
148
149 match (this_root, other_root) {
150 (Some(lhs), Some(rhs)) if lhs == rhs => {}
151 _ => return false,
152 }
153
154 let _ = packages;
158
159 petgraph::algo::is_isomorphic_matching(graph, &other.graph, Node::eq, Edge::eq)
163 }
164}
165
166impl Eq for DependencyGraph {}
167
168#[derive(Debug, Clone, PartialEq, Eq)]
170pub struct Node {
171 pub id: PackageId,
172 pub pkg: PackageInfo,
173 pub dist: Option<DistributionInfo>,
177}
178
179#[derive(Debug, Clone, PartialEq, Eq)]
181pub struct Edge {
182 pub alias: String,
184}
185
186#[derive(Debug, Clone, PartialEq, Eq)]
187pub struct ResolvedFileSystemMapping {
188 pub mount_path: PathBuf,
190 pub volume_name: String,
191 pub original_path: Option<String>,
192 pub package: PackageId,
193}
194
195#[derive(Debug, Clone, PartialEq, Eq)]
197pub struct ResolvedPackage {
198 pub root_package: PackageId,
199 pub commands: BTreeMap<String, ItemLocation>,
200 pub entrypoint: Option<String>,
201 pub filesystem: Vec<ResolvedFileSystemMapping>,
205}