1use crate::bindings::filesystem::types as async_filesystem;
2use crate::bindings::sync::filesystem::types as sync_filesystem;
3use crate::bindings::sync::io::streams;
4use crate::runtime::in_tokio;
5use crate::{FsError, FsResult, WasiImpl, WasiView};
6use wasmtime::component::Resource;
7
8impl<T> sync_filesystem::Host for WasiImpl<T>
9where
10 T: WasiView,
11{
12 fn convert_error_code(&mut self, err: FsError) -> anyhow::Result<sync_filesystem::ErrorCode> {
13 Ok(async_filesystem::Host::convert_error_code(self, err)?.into())
14 }
15
16 fn filesystem_error_code(
17 &mut self,
18 err: Resource<streams::Error>,
19 ) -> anyhow::Result<Option<sync_filesystem::ErrorCode>> {
20 Ok(async_filesystem::Host::filesystem_error_code(self, err)?.map(|e| e.into()))
21 }
22}
23
24impl<T> sync_filesystem::HostDescriptor for WasiImpl<T>
25where
26 T: WasiView,
27{
28 fn advise(
29 &mut self,
30 fd: Resource<sync_filesystem::Descriptor>,
31 offset: sync_filesystem::Filesize,
32 len: sync_filesystem::Filesize,
33 advice: sync_filesystem::Advice,
34 ) -> FsResult<()> {
35 in_tokio(async {
36 async_filesystem::HostDescriptor::advise(self, fd, offset, len, advice.into()).await
37 })
38 }
39
40 fn sync_data(&mut self, fd: Resource<sync_filesystem::Descriptor>) -> FsResult<()> {
41 in_tokio(async { async_filesystem::HostDescriptor::sync_data(self, fd).await })
42 }
43
44 fn get_flags(
45 &mut self,
46 fd: Resource<sync_filesystem::Descriptor>,
47 ) -> FsResult<sync_filesystem::DescriptorFlags> {
48 Ok(in_tokio(async { async_filesystem::HostDescriptor::get_flags(self, fd).await })?.into())
49 }
50
51 fn get_type(
52 &mut self,
53 fd: Resource<sync_filesystem::Descriptor>,
54 ) -> FsResult<sync_filesystem::DescriptorType> {
55 Ok(in_tokio(async { async_filesystem::HostDescriptor::get_type(self, fd).await })?.into())
56 }
57
58 fn set_size(
59 &mut self,
60 fd: Resource<sync_filesystem::Descriptor>,
61 size: sync_filesystem::Filesize,
62 ) -> FsResult<()> {
63 in_tokio(async { async_filesystem::HostDescriptor::set_size(self, fd, size).await })
64 }
65
66 fn set_times(
67 &mut self,
68 fd: Resource<sync_filesystem::Descriptor>,
69 atim: sync_filesystem::NewTimestamp,
70 mtim: sync_filesystem::NewTimestamp,
71 ) -> FsResult<()> {
72 in_tokio(async {
73 async_filesystem::HostDescriptor::set_times(self, fd, atim.into(), mtim.into()).await
74 })
75 }
76
77 fn read(
78 &mut self,
79 fd: Resource<sync_filesystem::Descriptor>,
80 len: sync_filesystem::Filesize,
81 offset: sync_filesystem::Filesize,
82 ) -> FsResult<(Vec<u8>, bool)> {
83 in_tokio(async { async_filesystem::HostDescriptor::read(self, fd, len, offset).await })
84 }
85
86 fn write(
87 &mut self,
88 fd: Resource<sync_filesystem::Descriptor>,
89 buf: Vec<u8>,
90 offset: sync_filesystem::Filesize,
91 ) -> FsResult<sync_filesystem::Filesize> {
92 in_tokio(async { async_filesystem::HostDescriptor::write(self, fd, buf, offset).await })
93 }
94
95 fn read_directory(
96 &mut self,
97 fd: Resource<sync_filesystem::Descriptor>,
98 ) -> FsResult<Resource<sync_filesystem::DirectoryEntryStream>> {
99 in_tokio(async { async_filesystem::HostDescriptor::read_directory(self, fd).await })
100 }
101
102 fn sync(&mut self, fd: Resource<sync_filesystem::Descriptor>) -> FsResult<()> {
103 in_tokio(async { async_filesystem::HostDescriptor::sync(self, fd).await })
104 }
105
106 fn create_directory_at(
107 &mut self,
108 fd: Resource<sync_filesystem::Descriptor>,
109 path: String,
110 ) -> FsResult<()> {
111 in_tokio(async {
112 async_filesystem::HostDescriptor::create_directory_at(self, fd, path).await
113 })
114 }
115
116 fn stat(
117 &mut self,
118 fd: Resource<sync_filesystem::Descriptor>,
119 ) -> FsResult<sync_filesystem::DescriptorStat> {
120 Ok(in_tokio(async { async_filesystem::HostDescriptor::stat(self, fd).await })?.into())
121 }
122
123 fn stat_at(
124 &mut self,
125 fd: Resource<sync_filesystem::Descriptor>,
126 path_flags: sync_filesystem::PathFlags,
127 path: String,
128 ) -> FsResult<sync_filesystem::DescriptorStat> {
129 Ok(in_tokio(async {
130 async_filesystem::HostDescriptor::stat_at(self, fd, path_flags.into(), path).await
131 })?
132 .into())
133 }
134
135 fn set_times_at(
136 &mut self,
137 fd: Resource<sync_filesystem::Descriptor>,
138 path_flags: sync_filesystem::PathFlags,
139 path: String,
140 atim: sync_filesystem::NewTimestamp,
141 mtim: sync_filesystem::NewTimestamp,
142 ) -> FsResult<()> {
143 in_tokio(async {
144 async_filesystem::HostDescriptor::set_times_at(
145 self,
146 fd,
147 path_flags.into(),
148 path,
149 atim.into(),
150 mtim.into(),
151 )
152 .await
153 })
154 }
155
156 fn link_at(
157 &mut self,
158 fd: Resource<sync_filesystem::Descriptor>,
159 old_path_flags: sync_filesystem::PathFlags,
161 old_path: String,
162 new_descriptor: Resource<sync_filesystem::Descriptor>,
163 new_path: String,
164 ) -> FsResult<()> {
165 in_tokio(async {
166 async_filesystem::HostDescriptor::link_at(
167 self,
168 fd,
169 old_path_flags.into(),
170 old_path,
171 new_descriptor,
172 new_path,
173 )
174 .await
175 })
176 }
177
178 fn open_at(
179 &mut self,
180 fd: Resource<sync_filesystem::Descriptor>,
181 path_flags: sync_filesystem::PathFlags,
182 path: String,
183 oflags: sync_filesystem::OpenFlags,
184 flags: sync_filesystem::DescriptorFlags,
185 ) -> FsResult<Resource<sync_filesystem::Descriptor>> {
186 in_tokio(async {
187 async_filesystem::HostDescriptor::open_at(
188 self,
189 fd,
190 path_flags.into(),
191 path,
192 oflags.into(),
193 flags.into(),
194 )
195 .await
196 })
197 }
198
199 fn drop(&mut self, fd: Resource<sync_filesystem::Descriptor>) -> anyhow::Result<()> {
200 async_filesystem::HostDescriptor::drop(self, fd)
201 }
202
203 fn readlink_at(
204 &mut self,
205 fd: Resource<sync_filesystem::Descriptor>,
206 path: String,
207 ) -> FsResult<String> {
208 in_tokio(async { async_filesystem::HostDescriptor::readlink_at(self, fd, path).await })
209 }
210
211 fn remove_directory_at(
212 &mut self,
213 fd: Resource<sync_filesystem::Descriptor>,
214 path: String,
215 ) -> FsResult<()> {
216 in_tokio(async {
217 async_filesystem::HostDescriptor::remove_directory_at(self, fd, path).await
218 })
219 }
220
221 fn rename_at(
222 &mut self,
223 fd: Resource<sync_filesystem::Descriptor>,
224 old_path: String,
225 new_fd: Resource<sync_filesystem::Descriptor>,
226 new_path: String,
227 ) -> FsResult<()> {
228 in_tokio(async {
229 async_filesystem::HostDescriptor::rename_at(self, fd, old_path, new_fd, new_path).await
230 })
231 }
232
233 fn symlink_at(
234 &mut self,
235 fd: Resource<sync_filesystem::Descriptor>,
236 src_path: String,
237 dest_path: String,
238 ) -> FsResult<()> {
239 in_tokio(async {
240 async_filesystem::HostDescriptor::symlink_at(self, fd, src_path, dest_path).await
241 })
242 }
243
244 fn unlink_file_at(
245 &mut self,
246 fd: Resource<sync_filesystem::Descriptor>,
247 path: String,
248 ) -> FsResult<()> {
249 in_tokio(async { async_filesystem::HostDescriptor::unlink_file_at(self, fd, path).await })
250 }
251
252 fn read_via_stream(
253 &mut self,
254 fd: Resource<sync_filesystem::Descriptor>,
255 offset: sync_filesystem::Filesize,
256 ) -> FsResult<Resource<streams::InputStream>> {
257 Ok(async_filesystem::HostDescriptor::read_via_stream(
258 self, fd, offset,
259 )?)
260 }
261
262 fn write_via_stream(
263 &mut self,
264 fd: Resource<sync_filesystem::Descriptor>,
265 offset: sync_filesystem::Filesize,
266 ) -> FsResult<Resource<streams::OutputStream>> {
267 Ok(async_filesystem::HostDescriptor::write_via_stream(
268 self, fd, offset,
269 )?)
270 }
271
272 fn append_via_stream(
273 &mut self,
274 fd: Resource<sync_filesystem::Descriptor>,
275 ) -> FsResult<Resource<streams::OutputStream>> {
276 Ok(async_filesystem::HostDescriptor::append_via_stream(
277 self, fd,
278 )?)
279 }
280
281 fn is_same_object(
282 &mut self,
283 a: Resource<sync_filesystem::Descriptor>,
284 b: Resource<sync_filesystem::Descriptor>,
285 ) -> anyhow::Result<bool> {
286 in_tokio(async { async_filesystem::HostDescriptor::is_same_object(self, a, b).await })
287 }
288 fn metadata_hash(
289 &mut self,
290 fd: Resource<sync_filesystem::Descriptor>,
291 ) -> FsResult<sync_filesystem::MetadataHashValue> {
292 Ok(
293 in_tokio(async { async_filesystem::HostDescriptor::metadata_hash(self, fd).await })?
294 .into(),
295 )
296 }
297 fn metadata_hash_at(
298 &mut self,
299 fd: Resource<sync_filesystem::Descriptor>,
300 path_flags: sync_filesystem::PathFlags,
301 path: String,
302 ) -> FsResult<sync_filesystem::MetadataHashValue> {
303 Ok(in_tokio(async {
304 async_filesystem::HostDescriptor::metadata_hash_at(self, fd, path_flags.into(), path)
305 .await
306 })?
307 .into())
308 }
309}
310
311impl<T> sync_filesystem::HostDirectoryEntryStream for WasiImpl<T>
312where
313 T: WasiView,
314{
315 fn read_directory_entry(
316 &mut self,
317 stream: Resource<sync_filesystem::DirectoryEntryStream>,
318 ) -> FsResult<Option<sync_filesystem::DirectoryEntry>> {
319 Ok(in_tokio(async {
320 async_filesystem::HostDirectoryEntryStream::read_directory_entry(self, stream).await
321 })?
322 .map(|e| e.into()))
323 }
324
325 fn drop(
326 &mut self,
327 stream: Resource<sync_filesystem::DirectoryEntryStream>,
328 ) -> anyhow::Result<()> {
329 async_filesystem::HostDirectoryEntryStream::drop(self, stream)
330 }
331}
332
333impl From<async_filesystem::ErrorCode> for sync_filesystem::ErrorCode {
334 fn from(other: async_filesystem::ErrorCode) -> Self {
335 use async_filesystem::ErrorCode;
336 match other {
337 ErrorCode::Access => Self::Access,
338 ErrorCode::WouldBlock => Self::WouldBlock,
339 ErrorCode::Already => Self::Already,
340 ErrorCode::BadDescriptor => Self::BadDescriptor,
341 ErrorCode::Busy => Self::Busy,
342 ErrorCode::Deadlock => Self::Deadlock,
343 ErrorCode::Quota => Self::Quota,
344 ErrorCode::Exist => Self::Exist,
345 ErrorCode::FileTooLarge => Self::FileTooLarge,
346 ErrorCode::IllegalByteSequence => Self::IllegalByteSequence,
347 ErrorCode::InProgress => Self::InProgress,
348 ErrorCode::Interrupted => Self::Interrupted,
349 ErrorCode::Invalid => Self::Invalid,
350 ErrorCode::Io => Self::Io,
351 ErrorCode::IsDirectory => Self::IsDirectory,
352 ErrorCode::Loop => Self::Loop,
353 ErrorCode::TooManyLinks => Self::TooManyLinks,
354 ErrorCode::MessageSize => Self::MessageSize,
355 ErrorCode::NameTooLong => Self::NameTooLong,
356 ErrorCode::NoDevice => Self::NoDevice,
357 ErrorCode::NoEntry => Self::NoEntry,
358 ErrorCode::NoLock => Self::NoLock,
359 ErrorCode::InsufficientMemory => Self::InsufficientMemory,
360 ErrorCode::InsufficientSpace => Self::InsufficientSpace,
361 ErrorCode::NotDirectory => Self::NotDirectory,
362 ErrorCode::NotEmpty => Self::NotEmpty,
363 ErrorCode::NotRecoverable => Self::NotRecoverable,
364 ErrorCode::Unsupported => Self::Unsupported,
365 ErrorCode::NoTty => Self::NoTty,
366 ErrorCode::NoSuchDevice => Self::NoSuchDevice,
367 ErrorCode::Overflow => Self::Overflow,
368 ErrorCode::NotPermitted => Self::NotPermitted,
369 ErrorCode::Pipe => Self::Pipe,
370 ErrorCode::ReadOnly => Self::ReadOnly,
371 ErrorCode::InvalidSeek => Self::InvalidSeek,
372 ErrorCode::TextFileBusy => Self::TextFileBusy,
373 ErrorCode::CrossDevice => Self::CrossDevice,
374 }
375 }
376}
377
378impl From<sync_filesystem::Advice> for async_filesystem::Advice {
379 fn from(other: sync_filesystem::Advice) -> Self {
380 use sync_filesystem::Advice;
381 match other {
382 Advice::Normal => Self::Normal,
383 Advice::Sequential => Self::Sequential,
384 Advice::Random => Self::Random,
385 Advice::WillNeed => Self::WillNeed,
386 Advice::DontNeed => Self::DontNeed,
387 Advice::NoReuse => Self::NoReuse,
388 }
389 }
390}
391
392impl From<async_filesystem::DescriptorFlags> for sync_filesystem::DescriptorFlags {
393 fn from(other: async_filesystem::DescriptorFlags) -> Self {
394 let mut out = Self::empty();
395 if other.contains(async_filesystem::DescriptorFlags::READ) {
396 out |= Self::READ;
397 }
398 if other.contains(async_filesystem::DescriptorFlags::WRITE) {
399 out |= Self::WRITE;
400 }
401 if other.contains(async_filesystem::DescriptorFlags::FILE_INTEGRITY_SYNC) {
402 out |= Self::FILE_INTEGRITY_SYNC;
403 }
404 if other.contains(async_filesystem::DescriptorFlags::DATA_INTEGRITY_SYNC) {
405 out |= Self::DATA_INTEGRITY_SYNC;
406 }
407 if other.contains(async_filesystem::DescriptorFlags::REQUESTED_WRITE_SYNC) {
408 out |= Self::REQUESTED_WRITE_SYNC;
409 }
410 if other.contains(async_filesystem::DescriptorFlags::MUTATE_DIRECTORY) {
411 out |= Self::MUTATE_DIRECTORY;
412 }
413 out
414 }
415}
416
417impl From<async_filesystem::DescriptorType> for sync_filesystem::DescriptorType {
418 fn from(other: async_filesystem::DescriptorType) -> Self {
419 use async_filesystem::DescriptorType;
420 match other {
421 DescriptorType::RegularFile => Self::RegularFile,
422 DescriptorType::Directory => Self::Directory,
423 DescriptorType::BlockDevice => Self::BlockDevice,
424 DescriptorType::CharacterDevice => Self::CharacterDevice,
425 DescriptorType::Fifo => Self::Fifo,
426 DescriptorType::Socket => Self::Socket,
427 DescriptorType::SymbolicLink => Self::SymbolicLink,
428 DescriptorType::Unknown => Self::Unknown,
429 }
430 }
431}
432
433impl From<async_filesystem::DirectoryEntry> for sync_filesystem::DirectoryEntry {
434 fn from(other: async_filesystem::DirectoryEntry) -> Self {
435 Self {
436 type_: other.type_.into(),
437 name: other.name,
438 }
439 }
440}
441
442impl From<async_filesystem::DescriptorStat> for sync_filesystem::DescriptorStat {
443 fn from(other: async_filesystem::DescriptorStat) -> Self {
444 Self {
445 type_: other.type_.into(),
446 link_count: other.link_count,
447 size: other.size,
448 data_access_timestamp: other.data_access_timestamp,
449 data_modification_timestamp: other.data_modification_timestamp,
450 status_change_timestamp: other.status_change_timestamp,
451 }
452 }
453}
454
455impl From<sync_filesystem::PathFlags> for async_filesystem::PathFlags {
456 fn from(other: sync_filesystem::PathFlags) -> Self {
457 let mut out = Self::empty();
458 if other.contains(sync_filesystem::PathFlags::SYMLINK_FOLLOW) {
459 out |= Self::SYMLINK_FOLLOW;
460 }
461 out
462 }
463}
464
465impl From<sync_filesystem::NewTimestamp> for async_filesystem::NewTimestamp {
466 fn from(other: sync_filesystem::NewTimestamp) -> Self {
467 use sync_filesystem::NewTimestamp;
468 match other {
469 NewTimestamp::NoChange => Self::NoChange,
470 NewTimestamp::Now => Self::Now,
471 NewTimestamp::Timestamp(datetime) => Self::Timestamp(datetime),
472 }
473 }
474}
475
476impl From<sync_filesystem::OpenFlags> for async_filesystem::OpenFlags {
477 fn from(other: sync_filesystem::OpenFlags) -> Self {
478 let mut out = Self::empty();
479 if other.contains(sync_filesystem::OpenFlags::CREATE) {
480 out |= Self::CREATE;
481 }
482 if other.contains(sync_filesystem::OpenFlags::DIRECTORY) {
483 out |= Self::DIRECTORY;
484 }
485 if other.contains(sync_filesystem::OpenFlags::EXCLUSIVE) {
486 out |= Self::EXCLUSIVE;
487 }
488 if other.contains(sync_filesystem::OpenFlags::TRUNCATE) {
489 out |= Self::TRUNCATE;
490 }
491 out
492 }
493}
494impl From<sync_filesystem::DescriptorFlags> for async_filesystem::DescriptorFlags {
495 fn from(other: sync_filesystem::DescriptorFlags) -> Self {
496 let mut out = Self::empty();
497 if other.contains(sync_filesystem::DescriptorFlags::READ) {
498 out |= Self::READ;
499 }
500 if other.contains(sync_filesystem::DescriptorFlags::WRITE) {
501 out |= Self::WRITE;
502 }
503 if other.contains(sync_filesystem::DescriptorFlags::FILE_INTEGRITY_SYNC) {
504 out |= Self::FILE_INTEGRITY_SYNC;
505 }
506 if other.contains(sync_filesystem::DescriptorFlags::DATA_INTEGRITY_SYNC) {
507 out |= Self::DATA_INTEGRITY_SYNC;
508 }
509 if other.contains(sync_filesystem::DescriptorFlags::REQUESTED_WRITE_SYNC) {
510 out |= Self::REQUESTED_WRITE_SYNC;
511 }
512 if other.contains(sync_filesystem::DescriptorFlags::MUTATE_DIRECTORY) {
513 out |= Self::MUTATE_DIRECTORY;
514 }
515 out
516 }
517}
518impl From<async_filesystem::MetadataHashValue> for sync_filesystem::MetadataHashValue {
519 fn from(other: async_filesystem::MetadataHashValue) -> Self {
520 Self {
521 lower: other.lower,
522 upper: other.upper,
523 }
524 }
525}