1use crate::fs::{Metadata, OpenOptions, Permissions};
2use crate::fs_utf8::from_utf8;
3use camino::Utf8Path;
4use cap_primitives::AmbientAuthority;
5#[cfg(not(windows))]
6use io_extras::os::rustix::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
7#[cfg(not(windows))]
8use io_lifetimes::{AsFd, BorrowedFd, OwnedFd};
9#[cfg(windows)]
10use io_lifetimes::{AsHandle, BorrowedHandle, OwnedHandle};
11use std::io::{self, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
12#[cfg(target_os = "wasi")]
13use std::path::Path;
14use std::{fmt, fs, process};
15#[cfg(windows)]
16use {
17 io_extras::os::windows::{
18 AsHandleOrSocket, AsRawHandleOrSocket, BorrowedHandleOrSocket, IntoRawHandleOrSocket,
19 OwnedHandleOrSocket, RawHandleOrSocket,
20 },
21 std::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle},
22};
23
24pub struct File {
36 cap_std: crate::fs::File,
37}
38
39impl File {
40 #[inline]
45 pub fn from_std(std: fs::File) -> Self {
46 Self::from_cap_std(crate::fs::File::from_std(std))
47 }
48
49 #[inline]
51 pub fn from_cap_std(cap_std: crate::fs::File) -> Self {
52 Self { cap_std }
53 }
54
55 #[inline]
57 pub fn into_std(self) -> fs::File {
58 self.cap_std.into_std()
59 }
60
61 #[inline]
65 pub fn sync_all(&self) -> io::Result<()> {
66 self.cap_std.sync_all()
67 }
68
69 #[inline]
74 pub fn sync_data(&self) -> io::Result<()> {
75 self.cap_std.sync_data()
76 }
77
78 #[inline]
83 pub fn set_len(&self, size: u64) -> io::Result<()> {
84 self.cap_std.set_len(size)
85 }
86
87 #[inline]
91 pub fn metadata(&self) -> io::Result<Metadata> {
92 self.cap_std.metadata()
93 }
94
95 #[inline]
100 pub fn try_clone(&self) -> io::Result<Self> {
101 Ok(Self::from_cap_std(self.cap_std.try_clone()?))
102 }
103
104 #[inline]
108 pub fn set_permissions(&self, perm: Permissions) -> io::Result<()> {
109 self.cap_std.set_permissions(perm)
110 }
111
112 #[inline]
120 pub fn open_ambient<P: AsRef<Utf8Path>>(
121 path: P,
122 ambient_authority: AmbientAuthority,
123 ) -> io::Result<Self> {
124 let path = from_utf8(path.as_ref())?;
125 Ok(Self::from_cap_std(crate::fs::File::open_ambient(
126 path,
127 ambient_authority,
128 )?))
129 }
130
131 #[inline]
140 pub fn create_ambient<P: AsRef<Utf8Path>>(
141 path: P,
142 ambient_authority: AmbientAuthority,
143 ) -> io::Result<Self> {
144 let path = from_utf8(path.as_ref())?;
145 Ok(Self::from_cap_std(crate::fs::File::create_ambient(
146 path,
147 ambient_authority,
148 )?))
149 }
150
151 #[inline]
160 pub fn open_ambient_with<P: AsRef<Utf8Path>>(
161 path: P,
162 options: &OpenOptions,
163 ambient_authority: AmbientAuthority,
164 ) -> io::Result<Self> {
165 let path = from_utf8(path.as_ref())?;
166 Ok(Self::from_cap_std(crate::fs::File::open_ambient_with(
167 path,
168 options,
169 ambient_authority,
170 )?))
171 }
172
173 #[must_use]
177 #[inline]
178 pub fn options() -> OpenOptions {
179 OpenOptions::new()
180 }
181}
182
183unsafe impl io_lifetimes::views::FilelikeViewType for File {}
185
186#[cfg(not(windows))]
187impl FromRawFd for File {
188 #[inline]
189 unsafe fn from_raw_fd(fd: RawFd) -> Self {
190 Self::from_std(fs::File::from_raw_fd(fd))
191 }
192}
193
194#[cfg(not(windows))]
195impl From<OwnedFd> for File {
196 #[inline]
197 fn from(fd: OwnedFd) -> Self {
198 Self::from_std(fs::File::from(fd))
199 }
200}
201
202#[cfg(windows)]
203impl FromRawHandle for File {
204 #[inline]
205 unsafe fn from_raw_handle(handle: RawHandle) -> Self {
206 Self::from_std(fs::File::from_raw_handle(handle))
207 }
208}
209
210#[cfg(windows)]
211impl From<OwnedHandle> for File {
212 #[inline]
213 fn from(handle: OwnedHandle) -> Self {
214 Self::from_std(fs::File::from(handle))
215 }
216}
217
218#[cfg(not(windows))]
219impl AsRawFd for File {
220 #[inline]
221 fn as_raw_fd(&self) -> RawFd {
222 self.cap_std.as_raw_fd()
223 }
224}
225
226#[cfg(not(windows))]
227impl AsFd for File {
228 #[inline]
229 fn as_fd(&self) -> BorrowedFd<'_> {
230 self.cap_std.as_fd()
231 }
232}
233
234#[cfg(windows)]
235impl AsRawHandle for File {
236 #[inline]
237 fn as_raw_handle(&self) -> RawHandle {
238 self.cap_std.as_raw_handle()
239 }
240}
241
242#[cfg(windows)]
243impl AsHandle for File {
244 #[inline]
245 fn as_handle(&self) -> BorrowedHandle<'_> {
246 self.cap_std.as_handle()
247 }
248}
249
250#[cfg(windows)]
251impl AsRawHandleOrSocket for File {
252 #[inline]
253 fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {
254 self.cap_std.as_raw_handle_or_socket()
255 }
256}
257
258#[cfg(windows)]
259impl AsHandleOrSocket for File {
260 #[inline]
261 fn as_handle_or_socket(&self) -> BorrowedHandleOrSocket<'_> {
262 self.cap_std.as_handle_or_socket()
263 }
264}
265
266#[cfg(not(windows))]
267impl IntoRawFd for File {
268 #[inline]
269 fn into_raw_fd(self) -> RawFd {
270 self.cap_std.into_raw_fd()
271 }
272}
273
274#[cfg(not(windows))]
275impl From<File> for OwnedFd {
276 #[inline]
277 fn from(file: File) -> OwnedFd {
278 file.cap_std.into()
279 }
280}
281
282#[cfg(windows)]
283impl IntoRawHandle for File {
284 #[inline]
285 fn into_raw_handle(self) -> RawHandle {
286 self.cap_std.into_raw_handle()
287 }
288}
289
290#[cfg(windows)]
291impl From<File> for OwnedHandle {
292 #[inline]
293 fn from(file: File) -> OwnedHandle {
294 file.cap_std.into()
295 }
296}
297
298#[cfg(windows)]
299impl IntoRawHandleOrSocket for File {
300 #[inline]
301 fn into_raw_handle_or_socket(self) -> RawHandleOrSocket {
302 self.cap_std.into_raw_handle_or_socket()
303 }
304}
305
306#[cfg(windows)]
307impl From<File> for OwnedHandleOrSocket {
308 #[inline]
309 fn from(file: File) -> Self {
310 file.cap_std.into()
311 }
312}
313
314impl Read for File {
315 #[inline]
316 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
317 self.cap_std.read(buf)
318 }
319
320 #[inline]
321 fn read_vectored(&mut self, bufs: &mut [IoSliceMut]) -> io::Result<usize> {
322 self.cap_std.read_vectored(bufs)
323 }
324
325 #[inline]
326 fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
327 self.cap_std.read_exact(buf)
328 }
329
330 #[inline]
331 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
332 self.cap_std.read_to_end(buf)
333 }
334
335 #[inline]
336 fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
337 self.cap_std.read_to_string(buf)
338 }
339
340 #[cfg(can_vector)]
341 #[inline]
342 fn is_read_vectored(&self) -> bool {
343 self.cap_std.is_read_vectored()
344 }
345}
346
347impl Read for &File {
348 #[inline]
349 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
350 (&mut &self.cap_std).read(buf)
351 }
352
353 #[inline]
354 fn read_vectored(&mut self, bufs: &mut [IoSliceMut]) -> io::Result<usize> {
355 (&mut &self.cap_std).read_vectored(bufs)
356 }
357
358 #[inline]
359 fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
360 (&mut &self.cap_std).read_exact(buf)
361 }
362
363 #[inline]
364 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
365 (&mut &self.cap_std).read_to_end(buf)
366 }
367
368 #[inline]
369 fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
370 (&mut &self.cap_std).read_to_string(buf)
371 }
372
373 #[cfg(can_vector)]
374 #[inline]
375 fn is_read_vectored(&self) -> bool {
376 self.cap_std.is_read_vectored()
377 }
378}
379
380impl Write for File {
381 #[inline]
382 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
383 self.cap_std.write(buf)
384 }
385
386 #[inline]
387 fn flush(&mut self) -> io::Result<()> {
388 self.cap_std.flush()
389 }
390
391 #[inline]
392 fn write_vectored(&mut self, bufs: &[IoSlice]) -> io::Result<usize> {
393 self.cap_std.write_vectored(bufs)
394 }
395
396 #[inline]
397 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
398 self.cap_std.write_all(buf)
399 }
400
401 #[cfg(can_vector)]
402 #[inline]
403 fn is_write_vectored(&self) -> bool {
404 self.cap_std.is_write_vectored()
405 }
406
407 #[cfg(write_all_vectored)]
408 #[inline]
409 fn write_all_vectored(&mut self, bufs: &mut [IoSlice]) -> io::Result<()> {
410 self.cap_std.write_all_vectored(bufs)
411 }
412}
413
414impl Write for &File {
415 #[inline]
416 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
417 (&mut &self.cap_std).write(buf)
418 }
419
420 #[inline]
421 fn flush(&mut self) -> io::Result<()> {
422 (&mut &self.cap_std).flush()
423 }
424
425 #[inline]
426 fn write_vectored(&mut self, bufs: &[IoSlice]) -> io::Result<usize> {
427 (&mut &self.cap_std).write_vectored(bufs)
428 }
429
430 #[inline]
431 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
432 (&mut &self.cap_std).write_all(buf)
433 }
434
435 #[cfg(can_vector)]
436 #[inline]
437 fn is_write_vectored(&self) -> bool {
438 self.cap_std.is_write_vectored()
439 }
440
441 #[cfg(write_all_vectored)]
442 #[inline]
443 fn write_all_vectored(&mut self, bufs: &mut [IoSlice]) -> io::Result<()> {
444 (&mut &self.cap_std).write_all_vectored(bufs)
445 }
446}
447
448impl Seek for File {
449 #[inline]
450 fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
451 self.cap_std.seek(pos)
452 }
453
454 #[inline]
455 fn stream_position(&mut self) -> io::Result<u64> {
456 self.cap_std.stream_position()
457 }
458}
459
460impl Seek for &File {
461 #[inline]
462 fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
463 (&mut &self.cap_std).seek(pos)
464 }
465
466 #[inline]
467 fn stream_position(&mut self) -> io::Result<u64> {
468 (&mut &self.cap_std).stream_position()
469 }
470}
471
472impl From<File> for process::Stdio {
473 #[inline]
474 fn from(file: File) -> Self {
475 From::<crate::fs::File>::from(file.cap_std)
476 }
477}
478
479#[cfg(unix)]
480impl crate::fs::FileExt for File {
481 #[inline]
482 fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
483 self.cap_std.read_at(buf, offset)
484 }
485
486 #[inline]
487 fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
488 self.cap_std.write_at(buf, offset)
489 }
490
491 #[inline]
492 fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
493 self.cap_std.read_exact_at(buf, offset)
494 }
495
496 #[inline]
497 fn write_all_at(&self, buf: &[u8], offset: u64) -> io::Result<()> {
498 self.cap_std.write_all_at(buf, offset)
499 }
500}
501
502#[cfg(target_os = "wasi")]
503impl crate::fs::FileExt for File {
504 #[inline]
505 fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
506 self.cap_std.read_at(buf, offset)
507 }
508
509 #[inline]
510 fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
511 self.cap_std.write_at(buf, offset)
512 }
513
514 #[inline]
515 fn read_vectored_at(&self, bufs: &mut [IoSliceMut], offset: u64) -> io::Result<usize> {
516 self.cap_std.read_vectored_at(bufs, offset)
517 }
518
519 #[inline]
520 fn write_vectored_at(&self, bufs: &[IoSlice], offset: u64) -> io::Result<usize> {
521 self.cap_std.write_vectored_at(bufs, offset)
522 }
523
524 #[inline]
525 fn tell(&self) -> std::result::Result<u64, io::Error> {
526 self.cap_std.tell()
527 }
528
529 #[inline]
530 fn fdstat_set_flags(&self, flags: u16) -> std::result::Result<(), io::Error> {
531 self.cap_std.fdstat_set_flags(flags)
532 }
533
534 #[inline]
535 fn fdstat_set_rights(
536 &self,
537 rights: u64,
538 inheriting: u64,
539 ) -> std::result::Result<(), io::Error> {
540 self.cap_std.fdstat_set_rights(rights, inheriting)
541 }
542
543 #[inline]
544 fn advise(&self, offset: u64, len: u64, advice: u8) -> std::result::Result<(), io::Error> {
545 self.cap_std.advise(offset, len, advice)
546 }
547
548 #[inline]
549 fn allocate(&self, offset: u64, len: u64) -> std::result::Result<(), io::Error> {
550 self.cap_std.allocate(offset, len)
551 }
552
553 #[inline]
554 fn create_directory<P: AsRef<Path>>(&self, path: P) -> std::result::Result<(), io::Error> {
555 let path = path.as_ref();
556 self.cap_std.create_directory(path)
557 }
558
559 #[inline]
560 fn read_link<P: AsRef<Path>>(
561 &self,
562 path: P,
563 ) -> std::result::Result<std::path::PathBuf, io::Error> {
564 let path = path.as_ref();
565 self.cap_std.read_link(path)
566 }
567
568 #[inline]
569 fn metadata_at<P: AsRef<Path>>(
570 &self,
571 lookup_flags: u32,
572 path: P,
573 ) -> std::result::Result<std::fs::Metadata, io::Error> {
574 let path = path.as_ref();
575 self.cap_std.metadata_at(lookup_flags, path)
576 }
577
578 #[inline]
579 fn remove_file<P: AsRef<Path>>(&self, path: P) -> std::result::Result<(), io::Error> {
580 let path = path.as_ref();
581 self.cap_std.remove_file(path)
582 }
583
584 #[inline]
585 fn remove_directory<P: AsRef<Path>>(&self, path: P) -> std::result::Result<(), io::Error> {
586 let path = path.as_ref();
587 self.cap_std.remove_directory(path)
588 }
589}
590
591#[cfg(windows)]
592impl crate::fs::FileExt for File {
593 #[inline]
594 fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
595 self.cap_std.seek_read(buf, offset)
596 }
597
598 #[inline]
599 fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
600 self.cap_std.seek_write(buf, offset)
601 }
602}
603
604impl fmt::Debug for File {
605 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
606 self.cap_std.fmt(f)
607 }
608}