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