1use crate::fs::{DirBuilder, File, Metadata, OpenOptions, ReadDir};
2#[cfg(target_os = "wasi")]
3use async_std::os::wasi::{
4 fs::OpenOptionsExt,
5 io::{AsRawFd, IntoRawFd},
6};
7use async_std::path::{Path, PathBuf};
8use async_std::task::spawn_blocking;
9use async_std::{fs, io};
10use cap_primitives::fs::{
11 canonicalize, copy, create_dir, hard_link, open, open_ambient_dir, open_dir, open_parent_dir,
12 read_base_dir, read_dir, read_link, remove_dir, remove_dir_all, remove_file, remove_open_dir,
13 remove_open_dir_all, rename, set_permissions, stat, DirOptions, FollowSymlinks, Permissions,
14};
15use cap_primitives::AmbientAuthority;
16use io_lifetimes::raw::{AsRawFilelike, FromRawFilelike};
17#[cfg(not(windows))]
18use io_lifetimes::{AsFd, BorrowedFd, OwnedFd};
19use io_lifetimes::{AsFilelike, FromFilelike};
20#[cfg(windows)]
21use io_lifetimes::{AsHandle, BorrowedHandle, OwnedHandle};
22use std::fmt;
23use std::mem::ManuallyDrop;
24#[cfg(unix)]
25use {
26 crate::os::unix::net::{UnixDatagram, UnixListener, UnixStream},
27 async_std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd},
28 cap_primitives::fs::symlink,
29};
30#[cfg(windows)]
31use {
32 async_std::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle},
33 cap_primitives::fs::{symlink_dir, symlink_file},
34 io_extras::os::windows::{
35 AsHandleOrSocket, AsRawHandleOrSocket, BorrowedHandleOrSocket, IntoRawHandleOrSocket,
36 OwnedHandleOrSocket, RawHandleOrSocket,
37 },
38};
39
40#[derive(Clone)]
51pub struct Dir {
52 std_file: fs::File,
53}
54
55impl Dir {
56 #[inline]
65 pub fn from_std_file(std_file: fs::File) -> Self {
66 Self { std_file }
67 }
68
69 #[inline]
71 pub fn into_std_file(self) -> fs::File {
72 self.std_file
73 }
74
75 #[inline]
80 pub async fn open<P: AsRef<Path>>(&self, path: P) -> io::Result<File> {
81 self.open_with(path, OpenOptions::new().read(true)).await
82 }
83
84 #[inline]
91 pub async fn open_with<P: AsRef<Path>>(
92 &self,
93 path: P,
94 options: &OpenOptions,
95 ) -> io::Result<File> {
96 self._open_with(path.as_ref(), options).await
97 }
98
99 #[cfg(not(target_os = "wasi"))]
100 async fn _open_with(&self, path: &Path, options: &OpenOptions) -> io::Result<File> {
101 let path = path.to_path_buf();
102 let clone = self.clone();
103 let options = options.clone();
104 let file = spawn_blocking(move || {
105 open(
106 &*clone.as_filelike_view::<std::fs::File>(),
107 path.as_ref(),
108 &options,
109 )
110 })
111 .await?
112 .into();
113 Ok(File::from_std(file))
114 }
115
116 #[cfg(target_os = "wasi")]
117 async fn _open_with(
118 file: &std::fs::File,
119 path: &Path,
120 options: &OpenOptions,
121 ) -> io::Result<File> {
122 let file = options.open_at(&self.std_file, path)?.into();
123 Ok(File::from_std(file))
124 }
125
126 #[inline]
128 pub async fn open_dir<P: AsRef<Path>>(&self, path: P) -> io::Result<Self> {
129 let path = path.as_ref().to_path_buf();
130 let clone = self.clone();
131 let dir = spawn_blocking(move || {
132 open_dir(&clone.as_filelike_view::<std::fs::File>(), path.as_ref())
133 })
134 .await?
135 .into();
136 Ok(Self::from_std_file(dir))
137 }
138
139 #[inline]
146 pub fn create_dir<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
147 self._create_dir_one(path.as_ref(), &DirOptions::new())
148 }
149
150 #[inline]
158 pub fn create_dir_all<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
159 self._create_dir_all(path.as_ref(), &DirOptions::new())
160 }
161
162 #[inline]
169 pub fn create_dir_with<P: AsRef<Path>>(
170 &self,
171 path: P,
172 dir_builder: &DirBuilder,
173 ) -> io::Result<()> {
174 let options = dir_builder.options();
175 if dir_builder.is_recursive() {
176 self._create_dir_all(path.as_ref(), options)
177 } else {
178 self._create_dir_one(path.as_ref(), options)
179 }
180 }
181
182 #[inline]
183 fn _create_dir_one(&self, path: &Path, dir_options: &DirOptions) -> io::Result<()> {
184 create_dir(
185 &self.as_filelike_view::<std::fs::File>(),
186 path.as_ref(),
187 dir_options,
188 )
189 }
190
191 fn _create_dir_all(&self, path: &Path, dir_options: &DirOptions) -> io::Result<()> {
192 if path == Path::new("") {
193 return Ok(());
194 }
195
196 match self._create_dir_one(path, dir_options) {
197 Ok(()) => return Ok(()),
198 Err(ref e) if e.kind() == io::ErrorKind::NotFound => {}
199 Err(_) if self.is_dir_blocking(path) => return Ok(()),
200 Err(e) => return Err(e),
201 }
202 match path.parent() {
203 Some(p) => self._create_dir_all(p, dir_options)?,
204 None => {
205 return Err(io::Error::new(
206 io::ErrorKind::Other,
207 "failed to create whole tree",
208 ))
209 }
210 }
211 match self._create_dir_one(path, dir_options) {
212 Ok(()) => Ok(()),
213 Err(_) if self.is_dir_blocking(path) => Ok(()),
214 Err(e) => Err(e),
215 }
216 }
217
218 #[inline]
223 pub async fn create<P: AsRef<Path>>(&self, path: P) -> io::Result<File> {
224 self.open_with(
225 path,
226 OpenOptions::new().write(true).create(true).truncate(true),
227 )
228 .await
229 }
230
231 #[inline]
238 pub async fn canonicalize<P: AsRef<Path>>(&self, path: P) -> io::Result<PathBuf> {
239 let path = path.as_ref().to_path_buf();
240 let clone = self.clone();
241 spawn_blocking(move || {
242 canonicalize(&clone.as_filelike_view::<std::fs::File>(), path.as_ref())
243 })
244 .await
245 .map(PathBuf::from)
246 }
247
248 #[inline]
255 pub async fn copy<P: AsRef<Path>, Q: AsRef<Path>>(
256 &self,
257 from: P,
258 to_dir: &Self,
259 to: Q,
260 ) -> io::Result<u64> {
261 let from = from.as_ref().to_path_buf();
262 let to = to.as_ref().to_path_buf();
263 let from_clone = self.clone();
264 let to_clone = to_dir.clone();
265 spawn_blocking(move || {
266 copy(
267 &from_clone.as_filelike_view::<std::fs::File>(),
268 from.as_ref(),
269 &to_clone.as_filelike_view::<std::fs::File>(),
270 to.as_ref(),
271 )
272 })
273 .await
274 }
275
276 #[inline]
281 pub async fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(
282 &self,
283 src: P,
284 dst_dir: &Self,
285 dst: Q,
286 ) -> io::Result<()> {
287 let dst = dst.as_ref().to_path_buf();
288 let src = src.as_ref().to_path_buf();
289 let src_clone = self.clone();
290 let dst_clone = dst_dir.clone();
291 spawn_blocking(move || {
292 hard_link(
293 &src_clone.as_filelike_view::<std::fs::File>(),
294 src.as_ref(),
295 &dst_clone.as_filelike_view::<std::fs::File>(),
296 dst.as_ref(),
297 )
298 })
299 .await
300 }
301
302 #[inline]
308 pub async fn metadata<P: AsRef<Path>>(&self, path: P) -> io::Result<Metadata> {
309 let path = path.as_ref().to_path_buf();
310 let clone = self.clone();
311 spawn_blocking(move || {
312 stat(
313 &clone.as_filelike_view::<std::fs::File>(),
314 path.as_ref(),
315 FollowSymlinks::Yes,
316 )
317 })
318 .await
319 }
320
321 #[inline]
323 fn metadata_blocking<P: AsRef<Path>>(&self, path: P) -> io::Result<Metadata> {
324 let path = path.as_ref().to_path_buf();
325 stat(
326 &self.as_filelike_view::<std::fs::File>(),
327 path.as_ref(),
328 FollowSymlinks::Yes,
329 )
330 }
331
332 #[inline]
337 pub async fn dir_metadata(&self) -> io::Result<Metadata> {
338 let clone = self.clone();
339 spawn_blocking(move || metadata_from(&*clone.as_filelike_view::<std::fs::File>())).await
340 }
341
342 #[inline]
344 pub async fn entries(&self) -> io::Result<ReadDir> {
345 let clone = self.clone();
346 spawn_blocking(move || read_base_dir(&clone.as_filelike_view::<std::fs::File>()))
347 .await
348 .map(|inner| ReadDir { inner })
349 }
350
351 #[inline]
356 pub async fn read_dir<P: AsRef<Path>>(&self, path: P) -> io::Result<ReadDir> {
357 let path = path.as_ref().to_path_buf();
358 let clone = self.clone();
359 spawn_blocking(move || read_dir(&clone.as_filelike_view::<std::fs::File>(), path.as_ref()))
360 .await
361 .map(|inner| ReadDir { inner })
362 }
363
364 #[inline]
369 pub async fn read<P: AsRef<Path>>(&self, path: P) -> io::Result<Vec<u8>> {
370 use async_std::prelude::*;
371 let mut file = self.open(path).await?;
372 let mut bytes = Vec::with_capacity(initial_buffer_size(&file).await);
373 file.read_to_end(&mut bytes).await?;
374 Ok(bytes)
375 }
376
377 #[inline]
382 pub async fn read_link<P: AsRef<Path>>(&self, path: P) -> io::Result<PathBuf> {
383 let path = path.as_ref().to_path_buf();
384 let clone = self.clone();
385 spawn_blocking(move || read_link(&clone.as_filelike_view::<std::fs::File>(), path.as_ref()))
386 .await
387 .map(PathBuf::from)
388 }
389
390 #[inline]
395 pub async fn read_to_string<P: AsRef<Path>>(&self, path: P) -> io::Result<String> {
396 use async_std::prelude::*;
397 let mut s = String::new();
398 self.open(path).await?.read_to_string(&mut s).await?;
399 Ok(s)
400 }
401
402 #[inline]
407 pub async fn remove_dir<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
408 let path = path.as_ref().to_path_buf();
409 let clone = self.clone();
410 spawn_blocking(move || {
411 remove_dir(&clone.as_filelike_view::<std::fs::File>(), path.as_ref())
412 })
413 .await
414 }
415
416 #[inline]
422 pub async fn remove_dir_all<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
423 let path = path.as_ref().to_path_buf();
424 let clone = self.clone();
425 spawn_blocking(move || {
426 remove_dir_all(&clone.as_filelike_view::<std::fs::File>(), path.as_ref())
427 })
428 .await
429 }
430
431 #[inline]
437 pub async fn remove_open_dir(self) -> io::Result<()> {
438 let file = std::fs::File::from_into_filelike(self.std_file);
439 spawn_blocking(move || remove_open_dir(file)).await
440 }
441
442 #[inline]
449 pub async fn remove_open_dir_all(self) -> io::Result<()> {
450 let file = std::fs::File::from_into_filelike(self.std_file);
451 spawn_blocking(move || remove_open_dir_all(file)).await
452 }
453
454 #[inline]
459 pub async fn remove_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
460 let path = path.as_ref().to_path_buf();
461 let clone = self.clone();
462 spawn_blocking(move || {
463 remove_file(&clone.as_filelike_view::<std::fs::File>(), path.as_ref())
464 })
465 .await
466 }
467
468 #[inline]
474 pub async fn rename<P: AsRef<Path>, Q: AsRef<Path>>(
475 &self,
476 from: P,
477 to_dir: &Self,
478 to: Q,
479 ) -> io::Result<()> {
480 let from = from.as_ref().to_path_buf();
481 let to = to.as_ref().to_path_buf();
482 let clone = self.clone();
483 let to_clone = to_dir.clone();
484 spawn_blocking(move || {
485 rename(
486 &clone.as_filelike_view::<std::fs::File>(),
487 from.as_ref(),
488 &to_clone.as_filelike_view::<std::fs::File>(),
489 to.as_ref(),
490 )
491 })
492 .await
493 }
494
495 pub async fn set_permissions<P: AsRef<Path>>(
502 &self,
503 path: P,
504 perm: Permissions,
505 ) -> io::Result<()> {
506 let path = path.as_ref().to_path_buf();
507 let clone = self.clone();
508 spawn_blocking(move || {
509 set_permissions(
510 &clone.as_filelike_view::<std::fs::File>(),
511 path.as_ref(),
512 perm,
513 )
514 })
515 .await
516 }
517
518 #[inline]
523 pub async fn symlink_metadata<P: AsRef<Path>>(&self, path: P) -> io::Result<Metadata> {
524 let path = path.as_ref().to_path_buf();
525 let clone = self.clone();
526 spawn_blocking(move || {
527 stat(
528 &clone.as_filelike_view::<std::fs::File>(),
529 path.as_ref(),
530 FollowSymlinks::No,
531 )
532 })
533 .await
534 }
535
536 #[inline]
541 pub async fn write<P: AsRef<Path>, C: AsRef<[u8]>>(
542 &self,
543 path: P,
544 contents: C,
545 ) -> io::Result<()> {
546 use async_std::prelude::*;
547 let mut file = self.create(path).await?;
548 file.write_all(contents.as_ref()).await
549 }
550
551 #[cfg(not(windows))]
568 #[inline]
569 pub async fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(
570 &self,
571 original: P,
572 link: Q,
573 ) -> io::Result<()> {
574 let original = original.as_ref().to_path_buf();
575 let link = link.as_ref().to_path_buf();
576 let clone = self.clone();
577 spawn_blocking(move || {
578 symlink(
579 original.as_ref(),
580 &clone.as_filelike_view::<std::fs::File>(),
581 link.as_ref(),
582 )
583 })
584 .await
585 }
586
587 #[cfg(windows)]
604 #[inline]
605 pub async fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(
606 &self,
607 original: P,
608 link: Q,
609 ) -> io::Result<()> {
610 let original = original.as_ref().to_path_buf();
611 let link = link.as_ref().to_path_buf();
612 let clone = self.clone();
613 spawn_blocking(move || {
614 symlink_file(
615 original.as_ref(),
616 &clone.as_filelike_view::<std::fs::File>(),
617 link.as_ref(),
618 )
619 })
620 .await
621 }
622
623 #[cfg(windows)]
640 #[inline]
641 pub async fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>>(
642 &self,
643 original: P,
644 link: Q,
645 ) -> io::Result<()> {
646 let original = original.as_ref().to_path_buf();
647 let link = link.as_ref().to_path_buf();
648 let clone = self.clone();
649 spawn_blocking(move || {
650 symlink_dir(
651 original.as_ref(),
652 &clone.as_filelike_view::<std::fs::File>(),
653 link.as_ref(),
654 )
655 })
656 .await
657 }
658
659 #[doc(alias = "bind")]
668 #[cfg(unix)]
669 #[inline]
670 pub async fn bind_unix_listener<P: AsRef<Path>>(&self, path: P) -> io::Result<UnixListener> {
671 todo!(
672 "Dir::bind_unix_listener({:?}, {})",
673 self.std_file,
674 path.as_ref().display()
675 )
676 }
677
678 #[doc(alias = "connect")]
687 #[cfg(unix)]
688 #[inline]
689 pub async fn connect_unix_stream<P: AsRef<Path>>(&self, path: P) -> io::Result<UnixStream> {
690 todo!(
691 "Dir::connect_unix_stream({:?}, {})",
692 self.std_file,
693 path.as_ref().display()
694 )
695 }
696
697 #[doc(alias = "bind")]
706 #[cfg(unix)]
707 #[inline]
708 pub async fn bind_unix_datagram<P: AsRef<Path>>(&self, path: P) -> io::Result<UnixDatagram> {
709 todo!(
710 "Dir::bind_unix_datagram({:?}, {})",
711 self.std_file,
712 path.as_ref().display()
713 )
714 }
715
716 #[doc(alias = "connect")]
726 #[cfg(unix)]
727 #[inline]
728 pub async fn connect_unix_datagram<P: AsRef<Path>>(
729 &self,
730 _unix_datagram: &UnixDatagram,
731 path: P,
732 ) -> io::Result<()> {
733 todo!(
734 "Dir::connect_unix_datagram({:?}, {})",
735 self.std_file,
736 path.as_ref().display()
737 )
738 }
739
740 #[doc(alias = "send_to")]
750 #[cfg(unix)]
751 #[inline]
752 pub async fn send_to_unix_datagram_addr<P: AsRef<Path>>(
753 &self,
754 _unix_datagram: &UnixDatagram,
755 buf: &[u8],
756 path: P,
757 ) -> io::Result<usize> {
758 todo!(
759 "Dir::send_to_unix_datagram_addr({:?}, {:?}, {})",
760 self.std_file,
761 buf,
762 path.as_ref().display()
763 )
764 }
765
766 #[inline]
773 pub async fn exists<P: AsRef<Path>>(&self, path: P) -> bool {
774 self.metadata(path).await.is_ok()
775 }
776
777 #[inline]
784 pub async fn try_exists<P: AsRef<Path>>(&self, path: P) -> io::Result<bool> {
785 match self.metadata(path.as_ref()).await {
786 Ok(_) => Ok(true),
787 Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(false),
788 Err(e) => Err(e),
789 }
790 }
791
792 #[inline]
798 pub async fn is_file<P: AsRef<Path>>(&self, path: P) -> bool {
799 self.metadata(path)
800 .await
801 .map(|m| m.is_file())
802 .unwrap_or(false)
803 }
804
805 #[inline]
812 pub async fn is_dir<P: AsRef<Path>>(&self, path: P) -> bool {
813 self.metadata(path)
814 .await
815 .map(|m| m.is_dir())
816 .unwrap_or(false)
817 }
818
819 #[inline]
821 fn is_dir_blocking<P: AsRef<Path>>(&self, path: P) -> bool {
822 self.metadata_blocking(path)
823 .map(|m| m.is_dir())
824 .unwrap_or(false)
825 }
826
827 #[inline]
835 pub async fn open_ambient_dir<P: AsRef<Path>>(
836 path: P,
837 ambient_authority: AmbientAuthority,
838 ) -> io::Result<Self> {
839 let path = path.as_ref().to_path_buf();
840 spawn_blocking(move || open_ambient_dir(path.as_ref(), ambient_authority))
841 .await
842 .map(|f| Self::from_std_file(f.into()))
843 }
844
845 #[inline]
852 pub async fn open_parent_dir(&self, ambient_authority: AmbientAuthority) -> io::Result<Self> {
853 let clone = self.clone();
854 let dir = spawn_blocking(move || {
855 open_parent_dir(
856 &*clone.as_filelike_view::<std::fs::File>(),
857 ambient_authority,
858 )
859 })
860 .await?
861 .into();
862 Ok(Self::from_std_file(dir))
863 }
864
865 #[inline]
873 pub async fn create_ambient_dir_all<P: AsRef<Path>>(
874 path: P,
875 ambient_authority: AmbientAuthority,
876 ) -> io::Result<()> {
877 let _ = ambient_authority;
878 let path = path.as_ref().to_path_buf();
879 fs::create_dir_all(path).await
880 }
881
882 pub async fn reopen_dir<Filelike: AsFilelike + Send>(dir: &Filelike) -> io::Result<Self> {
889 let raw_filelike = dir.as_filelike_view::<std::fs::File>().as_raw_filelike();
893 let file = ManuallyDrop::new(unsafe { std::fs::File::from_raw_filelike(raw_filelike) });
896 let dir = spawn_blocking(move || {
897 cap_primitives::fs::open_dir(&*file, std::path::Component::CurDir.as_ref())
898 })
899 .await?
900 .into();
901 Ok(Self::from_std_file(dir))
902 }
903}
904
905#[cfg(not(target_os = "wasi"))]
906#[inline]
907fn metadata_from(file: &std::fs::File) -> io::Result<Metadata> {
908 Metadata::from_file(file)
909}
910
911#[cfg(target_os = "wasi")]
912#[inline]
913fn metadata_from(file: &std::fs::File) -> io::Result<Metadata> {
914 file.metadata()
915}
916
917unsafe impl io_lifetimes::views::FilelikeViewType for Dir {}
919
920#[cfg(not(windows))]
921impl FromRawFd for Dir {
922 #[inline]
923 unsafe fn from_raw_fd(fd: RawFd) -> Self {
924 Self::from_std_file(fs::File::from_raw_fd(fd))
925 }
926}
927
928#[cfg(not(windows))]
929impl From<OwnedFd> for Dir {
930 #[inline]
931 fn from(fd: OwnedFd) -> Self {
932 Self::from_std_file(fs::File::from(fd))
933 }
934}
935
936#[cfg(windows)]
937impl FromRawHandle for Dir {
938 #[inline]
941 unsafe fn from_raw_handle(handle: RawHandle) -> Self {
942 Self::from_std_file(fs::File::from_raw_handle(handle))
943 }
944}
945
946#[cfg(windows)]
947impl From<OwnedHandle> for Dir {
948 #[inline]
949 fn from(handle: OwnedHandle) -> Self {
950 Self::from_std_file(fs::File::from(handle))
951 }
952}
953
954#[cfg(not(windows))]
955impl AsRawFd for Dir {
956 #[inline]
957 fn as_raw_fd(&self) -> RawFd {
958 self.std_file.as_raw_fd()
959 }
960}
961
962#[cfg(not(windows))]
963impl AsFd for Dir {
964 #[inline]
965 fn as_fd(&self) -> BorrowedFd<'_> {
966 self.std_file.as_fd()
967 }
968}
969
970#[cfg(windows)]
971impl AsRawHandle for Dir {
972 #[inline]
973 fn as_raw_handle(&self) -> RawHandle {
974 self.std_file.as_raw_handle()
975 }
976}
977
978#[cfg(windows)]
979impl AsHandle for Dir {
980 #[inline]
981 fn as_handle(&self) -> BorrowedHandle<'_> {
982 self.std_file.as_handle()
983 }
984}
985
986#[cfg(windows)]
987impl AsRawHandleOrSocket for Dir {
988 #[inline]
989 fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {
990 self.std_file.as_raw_handle_or_socket()
991 }
992}
993
994#[cfg(windows)]
995impl AsHandleOrSocket for Dir {
996 #[inline]
997 fn as_handle_or_socket(&self) -> BorrowedHandleOrSocket<'_> {
998 self.std_file.as_handle_or_socket()
999 }
1000}
1001
1002#[cfg(not(windows))]
1003impl IntoRawFd for Dir {
1004 #[inline]
1005 fn into_raw_fd(self) -> RawFd {
1006 self.std_file.into_raw_fd()
1007 }
1008}
1009
1010#[cfg(not(windows))]
1011impl From<Dir> for OwnedFd {
1012 #[inline]
1013 fn from(dir: Dir) -> OwnedFd {
1014 dir.std_file.into()
1015 }
1016}
1017
1018#[cfg(windows)]
1019impl IntoRawHandle for Dir {
1020 #[inline]
1021 fn into_raw_handle(self) -> RawHandle {
1022 self.std_file.into_raw_handle()
1023 }
1024}
1025
1026#[cfg(windows)]
1027impl From<Dir> for OwnedHandle {
1028 #[inline]
1029 fn from(dir: Dir) -> OwnedHandle {
1030 dir.std_file.into()
1031 }
1032}
1033
1034#[cfg(windows)]
1035impl IntoRawHandleOrSocket for Dir {
1036 #[inline]
1037 fn into_raw_handle_or_socket(self) -> RawHandleOrSocket {
1038 self.std_file.into_raw_handle_or_socket()
1039 }
1040}
1041
1042#[cfg(windows)]
1043impl From<Dir> for OwnedHandleOrSocket {
1044 #[inline]
1045 fn from(dir: Dir) -> Self {
1046 dir.std_file.into()
1047 }
1048}
1049
1050async fn initial_buffer_size(file: &File) -> usize {
1056 file.metadata()
1060 .await
1061 .map(|m| m.len() as usize + 1)
1062 .unwrap_or(0)
1063}
1064
1065impl fmt::Debug for Dir {
1066 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1068 let mut b = f.debug_struct("Dir");
1069 #[cfg(not(windows))]
1070 b.field("fd", &self.std_file.as_raw_fd());
1071 #[cfg(windows)]
1072 b.field("handle", &self.std_file.as_raw_handle());
1073 b.finish()
1074 }
1075}