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}