wasmtime_wasi/host/filesystem/
sync.rs

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        // TODO delete the path flags from this function
160        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}