wasmer_wasix/runtime/resolver/
source.rs1use std::{
2 fmt::{Debug, Display},
3 sync::Arc,
4};
5
6use wasmer_config::package::{PackageIdent, PackageSource};
7
8use crate::runtime::resolver::PackageSummary;
9
10#[async_trait::async_trait]
12pub trait Source: Sync + Debug {
13 async fn query(&self, package: &PackageSource) -> Result<Vec<PackageSummary>, QueryError>;
24
25 async fn latest(&self, pkg: &PackageSource) -> Result<PackageSummary, QueryError> {
28 let candidates = self.query(pkg).await?;
29
30 match pkg {
31 PackageSource::Ident(PackageIdent::Named(_)) => candidates
32 .into_iter()
33 .max_by(|left, right| {
34 let left_version = left.pkg.id.as_named().map(|x| &x.version);
35 let right_version = right.pkg.id.as_named().map(|x| &x.version);
36
37 left_version.cmp(&right_version)
38 })
39 .ok_or(QueryError::NoMatches {
40 query: pkg.clone(),
41 archived_versions: Vec::new(),
42 }),
43 _ => candidates
44 .into_iter()
45 .next()
46 .ok_or_else(|| QueryError::NotFound { query: pkg.clone() }),
47 }
48 }
49}
50
51#[async_trait::async_trait]
52impl<D, S> Source for D
53where
54 D: std::ops::Deref<Target = S> + Debug + Send + Sync,
55 S: Source + ?Sized + Send + Sync + 'static,
56{
57 async fn query(&self, package: &PackageSource) -> Result<Vec<PackageSummary>, QueryError> {
58 (**self).query(package).await
59 }
60}
61
62#[derive(Clone, Debug)]
63pub enum QueryError {
64 Unsupported {
65 query: PackageSource,
66 },
67 NotFound {
68 query: PackageSource,
69 },
70 NoMatches {
71 query: PackageSource,
72 archived_versions: Vec<semver::Version>,
73 },
74 Timeout {
75 query: PackageSource,
76 },
77 Other {
78 query: PackageSource,
79 error: Arc<anyhow::Error>,
82 },
83}
84
85impl QueryError {
86 pub fn query(&self) -> &PackageSource {
87 match self {
88 Self::Unsupported { query }
89 | Self::NotFound { query }
90 | Self::NoMatches { query, .. }
91 | Self::Timeout { query }
92 | Self::Other { query, .. } => query,
93 }
94 }
95
96 pub fn new_other(err: anyhow::Error, query: &PackageSource) -> Self {
97 Self::Other {
98 query: query.clone(),
99 error: Arc::new(err),
100 }
101 }
102}
103
104impl Display for QueryError {
105 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
106 write!(f, "failed to query package '{}': ", self.query())?;
107
108 match self {
109 Self::Unsupported { .. } => f.write_str("unsupported package specifier"),
110 Self::NotFound { .. } => f.write_str("not found"),
111 Self::Timeout { .. } => f.write_str("timeout"),
112 Self::NoMatches {
113 query: _,
114 archived_versions,
115 } => match archived_versions.as_slice() {
116 [] => f.write_str(
117 "the package was found, but no published versions matched the constraint",
118 ),
119 [version] => write!(
120 f,
121 "the only version satisfying the constraint, {version}, is archived"
122 ),
123 [first, rest @ ..] => {
124 let num_others = rest.len();
125 write!(
126 f,
127 "unable to satisfy the request - version {first}, and {num_others} are all archived"
128 )
129 }
130 },
131 Self::Other { error: e, query: _ } => Display::fmt(e, f),
132 }
133 }
134}
135
136impl std::error::Error for QueryError {
137 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
138 match self {
139 Self::Other { error, query: _ } => Some(&***error),
140 Self::Unsupported { .. }
141 | Self::NotFound { .. }
142 | Self::NoMatches { .. }
143 | Self::Timeout { .. } => None,
144 }
145 }
146}