wasmer_wasix/utils/
mod.rs1mod dummy_waker;
2mod owned_mutex_guard;
3pub mod store;
4mod thread_parker;
5
6#[cfg(feature = "js")]
7pub(crate) mod web;
8
9pub use self::{dummy_waker::WasiDummyWaker, thread_parker::WasiParkingLot};
10
11pub(crate) use owned_mutex_guard::{
12 OwnedRwLockReadGuard, OwnedRwLockWriteGuard, read_owned, write_owned,
13};
14
15use std::collections::BTreeSet;
16
17use wasmer::Module;
18use wasmer_wasix_types::wasi::Errno;
19
20pub fn is_wasi_module(module: &Module) -> bool {
23 get_wasi_version(module, false).is_some()
24}
25
26pub fn is_wasix_module(module: &Module) -> bool {
28 match get_wasi_versions(module, false).ok_or(false) {
29 Ok(wasi_versions) => {
30 wasi_versions.contains(&WasiVersion::Wasix32v1)
31 || wasi_versions.contains(&WasiVersion::Wasix64v1)
32 }
33 Err(_) => false,
34 }
35}
36
37pub fn map_io_err(err: std::io::Error) -> Errno {
38 From::<std::io::Error>::from(err)
39}
40
41#[cfg(feature = "journal")]
42pub fn map_snapshot_err(err: anyhow::Error) -> Errno {
43 tracing::warn!("unknown snapshot error: {}", err);
44 Errno::Unknown
45}
46
47#[derive(Debug, Clone, Copy, Eq)]
50pub enum WasiVersion {
51 Snapshot0,
53
54 Snapshot1,
56
57 Wasix32v1,
59
60 Wasix64v1,
62
63 Latest,
74}
75
76impl WasiVersion {
77 pub const fn get_namespace_str(&self) -> &'static str {
79 match *self {
80 WasiVersion::Snapshot0 => SNAPSHOT0_NAMESPACE,
81 WasiVersion::Snapshot1 => SNAPSHOT1_NAMESPACE,
82 WasiVersion::Wasix32v1 => WASIX_32V1_NAMESPACE,
83 WasiVersion::Wasix64v1 => WASIX_64V1_NAMESPACE,
84 WasiVersion::Latest => SNAPSHOT1_NAMESPACE,
85 }
86 }
87}
88
89impl PartialEq<WasiVersion> for WasiVersion {
90 fn eq(&self, other: &Self) -> bool {
91 matches!(
92 (*self, *other),
93 (Self::Snapshot1, Self::Latest)
94 | (Self::Latest, Self::Snapshot1)
95 | (Self::Latest, Self::Latest)
96 | (Self::Snapshot0, Self::Snapshot0)
97 | (Self::Snapshot1, Self::Snapshot1)
98 | (Self::Wasix32v1, Self::Wasix32v1)
99 | (Self::Wasix64v1, Self::Wasix64v1)
100 )
101 }
102}
103
104impl PartialOrd for WasiVersion {
105 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
106 Some(self.cmp(other))
107 }
108}
109
110impl Ord for WasiVersion {
111 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
112 if self == other {
113 return std::cmp::Ordering::Equal;
114 }
115 match (*self, *other) {
116 (Self::Snapshot1, Self::Snapshot0) => std::cmp::Ordering::Greater,
117 (Self::Wasix32v1, Self::Snapshot1) | (Self::Wasix32v1, Self::Snapshot0) => {
118 std::cmp::Ordering::Greater
119 }
120 (Self::Wasix64v1, Self::Wasix32v1)
121 | (Self::Wasix64v1, Self::Snapshot1)
122 | (Self::Wasix64v1, Self::Snapshot0) => std::cmp::Ordering::Greater,
123 (Self::Latest, Self::Wasix64v1)
124 | (Self::Latest, Self::Wasix32v1)
125 | (Self::Latest, Self::Snapshot1)
126 | (Self::Latest, Self::Snapshot0) => std::cmp::Ordering::Greater,
127 (_, _) => std::cmp::Ordering::Less,
129 }
130 }
131}
132
133const SNAPSHOT0_NAMESPACE: &str = "wasi_unstable";
135
136const SNAPSHOT1_NAMESPACE: &str = "wasi_snapshot_preview1";
138
139const WASIX_32V1_NAMESPACE: &str = "wasix_32v1";
141
142const WASIX_64V1_NAMESPACE: &str = "wasix_64v1";
144
145const WASIX_HTTP_V1_NAMESPACE: &str = "wasix_http_client_v1";
147
148pub fn get_wasi_version(module: &Module, strict: bool) -> Option<WasiVersion> {
156 let mut imports = module.imports().functions().map(|f| f.module().to_owned());
157
158 if strict {
159 let first_module = imports.next()?;
160 if imports.all(|module| module == first_module) {
161 match first_module.as_str() {
162 SNAPSHOT0_NAMESPACE => Some(WasiVersion::Snapshot0),
163 SNAPSHOT1_NAMESPACE => Some(WasiVersion::Snapshot1),
164 WASIX_32V1_NAMESPACE => Some(WasiVersion::Wasix32v1),
165 WASIX_64V1_NAMESPACE => Some(WasiVersion::Wasix64v1),
166 _ => None,
167 }
168 } else {
169 None
170 }
171 } else {
172 imports.find_map(|module| match module.as_str() {
175 SNAPSHOT0_NAMESPACE => Some(WasiVersion::Snapshot0),
176 SNAPSHOT1_NAMESPACE => Some(WasiVersion::Snapshot1),
177 WASIX_32V1_NAMESPACE => Some(WasiVersion::Wasix32v1),
178 WASIX_64V1_NAMESPACE => Some(WasiVersion::Wasix64v1),
179 _ => None,
180 })
181 }
182}
183
184pub fn get_wasi_versions(module: &Module, strict: bool) -> Option<BTreeSet<WasiVersion>> {
189 let mut out = BTreeSet::new();
190 let imports = module.imports().functions().map(|f| f.module().to_owned());
191
192 let mut non_wasi_seen = false;
193 for ns in imports {
194 match ns.as_str() {
195 SNAPSHOT0_NAMESPACE => {
196 out.insert(WasiVersion::Snapshot0);
197 }
198 SNAPSHOT1_NAMESPACE => {
199 out.insert(WasiVersion::Snapshot1);
200 }
201 WASIX_32V1_NAMESPACE => {
202 out.insert(WasiVersion::Wasix32v1);
203 }
204 WASIX_64V1_NAMESPACE => {
205 out.insert(WasiVersion::Wasix64v1);
206 }
207 WASIX_HTTP_V1_NAMESPACE => {
208 out.insert(WasiVersion::Wasix64v1);
209 }
210 _ => {
211 non_wasi_seen = true;
212 }
213 }
214 }
215 if strict && non_wasi_seen {
216 None
217 } else {
218 Some(out)
219 }
220}
221
222#[cfg(test)]
223mod test {
224 use super::*;
225
226 #[test]
227 fn wasi_version_equality() {
228 assert_eq!(WasiVersion::Snapshot0, WasiVersion::Snapshot0);
229 assert_eq!(WasiVersion::Wasix64v1, WasiVersion::Wasix64v1);
230 assert_eq!(WasiVersion::Wasix32v1, WasiVersion::Wasix32v1);
231 assert_eq!(WasiVersion::Snapshot1, WasiVersion::Snapshot1);
232 assert_eq!(WasiVersion::Snapshot1, WasiVersion::Latest);
233 assert_eq!(WasiVersion::Latest, WasiVersion::Snapshot1);
234 assert_eq!(WasiVersion::Latest, WasiVersion::Latest);
235 assert!(WasiVersion::Wasix32v1 != WasiVersion::Wasix64v1);
236 assert!(WasiVersion::Wasix64v1 != WasiVersion::Wasix32v1);
237 assert!(WasiVersion::Snapshot1 != WasiVersion::Wasix64v1);
238 assert!(WasiVersion::Wasix64v1 != WasiVersion::Snapshot1);
239 assert!(WasiVersion::Snapshot1 != WasiVersion::Wasix32v1);
240 assert!(WasiVersion::Wasix32v1 != WasiVersion::Snapshot1);
241 assert!(WasiVersion::Snapshot0 != WasiVersion::Snapshot1);
242 assert!(WasiVersion::Snapshot1 != WasiVersion::Snapshot0);
243 assert!(WasiVersion::Snapshot0 != WasiVersion::Latest);
244 assert!(WasiVersion::Latest != WasiVersion::Snapshot0);
245 assert!(WasiVersion::Snapshot0 != WasiVersion::Latest);
246 assert!(WasiVersion::Latest != WasiVersion::Snapshot0);
247 assert!(WasiVersion::Wasix32v1 != WasiVersion::Latest);
248 assert!(WasiVersion::Wasix64v1 != WasiVersion::Latest);
249 }
250
251 #[test]
252 fn wasi_version_ordering() {
253 assert!(WasiVersion::Snapshot0 <= WasiVersion::Snapshot0);
254 assert!(WasiVersion::Snapshot1 <= WasiVersion::Snapshot1);
255 assert!(WasiVersion::Wasix32v1 <= WasiVersion::Wasix32v1);
256 assert!(WasiVersion::Wasix64v1 <= WasiVersion::Wasix64v1);
257 assert!(WasiVersion::Latest <= WasiVersion::Latest);
258 assert!(WasiVersion::Snapshot0 >= WasiVersion::Snapshot0);
259 assert!(WasiVersion::Snapshot1 >= WasiVersion::Snapshot1);
260 assert!(WasiVersion::Wasix32v1 >= WasiVersion::Wasix32v1);
261 assert!(WasiVersion::Wasix64v1 >= WasiVersion::Wasix64v1);
262 assert!(WasiVersion::Latest >= WasiVersion::Latest);
263
264 assert!(WasiVersion::Snapshot0 < WasiVersion::Latest);
265 assert!(WasiVersion::Snapshot0 < WasiVersion::Wasix32v1);
266 assert!(WasiVersion::Snapshot0 < WasiVersion::Wasix64v1);
267 assert!(WasiVersion::Snapshot0 < WasiVersion::Snapshot1);
268 assert!(WasiVersion::Latest > WasiVersion::Snapshot0);
269 assert!(WasiVersion::Wasix32v1 > WasiVersion::Snapshot0);
270 assert!(WasiVersion::Wasix64v1 > WasiVersion::Snapshot0);
271 assert!(WasiVersion::Snapshot1 > WasiVersion::Snapshot0);
272
273 assert!(WasiVersion::Snapshot1 < WasiVersion::Wasix32v1);
274 assert!(WasiVersion::Snapshot1 < WasiVersion::Wasix64v1);
275 assert!(WasiVersion::Wasix32v1 > WasiVersion::Snapshot1);
276 assert!(WasiVersion::Wasix64v1 > WasiVersion::Snapshot1);
277
278 assert!(WasiVersion::Wasix32v1 < WasiVersion::Latest);
279 assert!(WasiVersion::Wasix32v1 > WasiVersion::Snapshot1);
280 assert!(WasiVersion::Wasix64v1 < WasiVersion::Latest);
281 assert!(WasiVersion::Wasix64v1 > WasiVersion::Snapshot1);
282 assert!(WasiVersion::Latest > WasiVersion::Wasix32v1);
283 assert!(WasiVersion::Snapshot1 < WasiVersion::Wasix32v1);
284 assert!(WasiVersion::Latest > WasiVersion::Wasix64v1);
285 assert!(WasiVersion::Snapshot1 < WasiVersion::Wasix32v1);
286
287 assert!(WasiVersion::Wasix32v1 < WasiVersion::Wasix64v1);
288 assert!(WasiVersion::Wasix64v1 > WasiVersion::Wasix32v1);
289 }
290}