1use core::str;
2use std::borrow::Cow;
3use std::env::VarError;
4use std::ffi::OsStr;
5use std::ffi::OsString;
6use std::io;
7use std::io::Error;
8use std::io::ErrorKind;
9use std::path::Path;
10use std::path::PathBuf;
11use std::time::SystemTime;
12
13pub mod boxed;
14pub mod ctx;
15pub mod impls;
16
17pub use sys_traits_macros::auto_impl;
18
19pub use self::ctx::FsFileWithPathsInErrors;
20pub use self::ctx::OperationError;
21pub use self::ctx::OperationErrorKind;
22pub use self::ctx::PathsInErrorsExt;
23pub use self::ctx::SysWithPathsInErrors;
24
25use self::boxed::BoxedFsFile;
26use self::boxed::BoxedFsMetadataValue;
27
28pub trait EnvCurrentDir {
33 fn env_current_dir(&self) -> io::Result<PathBuf>;
34}
35
36pub trait BaseEnvSetCurrentDir {
39 #[doc(hidden)]
40 fn base_env_set_current_dir(&self, path: &Path) -> io::Result<()>;
41}
42
43pub trait EnvSetCurrentDir: BaseEnvSetCurrentDir {
44 #[inline]
45 fn env_set_current_dir(&self, path: impl AsRef<Path>) -> io::Result<()> {
46 self.base_env_set_current_dir(path.as_ref())
47 }
48}
49
50impl<T: BaseEnvSetCurrentDir> EnvSetCurrentDir for T {}
51
52pub trait BaseEnvVar {
55 #[doc(hidden)]
56 fn base_env_var_os(&self, key: &OsStr) -> Option<OsString>;
57}
58
59pub trait EnvVar: BaseEnvVar {
60 #[inline]
61 fn env_var_os(&self, key: impl AsRef<OsStr>) -> Option<OsString> {
62 self.base_env_var_os(key.as_ref())
63 }
64
65 fn env_var(&self, key: impl AsRef<OsStr>) -> Result<String, VarError> {
66 match self.env_var_os(key) {
67 Some(val) => val.into_string().map_err(VarError::NotUnicode),
68 None => Err(VarError::NotPresent),
69 }
70 }
71
72 fn env_var_path(&self, key: impl AsRef<OsStr>) -> Option<PathBuf> {
74 self
75 .env_var_os(key)
76 .and_then(|h| if h.is_empty() { None } else { Some(h) })
77 .map(|value| {
78 #[cfg(all(target_arch = "wasm32", feature = "wasm"))]
79 {
80 impls::wasm_string_to_path(value.to_string_lossy().to_string())
81 }
82 #[cfg(any(not(target_arch = "wasm32"), not(feature = "wasm")))]
83 {
84 PathBuf::from(value)
85 }
86 })
87 }
88}
89
90impl<T: BaseEnvVar> EnvVar for T {}
91
92pub trait BaseEnvRemoveVar {
95 #[doc(hidden)]
96 fn base_env_remove_var(&self, key: &OsStr);
97}
98
99pub trait EnvRemoveVar: BaseEnvRemoveVar {
100 fn env_remove_var(&self, key: impl AsRef<OsStr>) {
101 self.base_env_remove_var(key.as_ref())
102 }
103}
104
105impl<T: BaseEnvRemoveVar> EnvRemoveVar for T {}
106
107pub trait BaseEnvSetVar {
110 #[doc(hidden)]
111 fn base_env_set_var(&self, key: &OsStr, value: &OsStr);
112}
113
114pub trait EnvSetVar: BaseEnvSetVar {
115 fn env_set_var(&self, key: impl AsRef<OsStr>, value: impl AsRef<OsStr>) {
116 self.base_env_set_var(key.as_ref(), value.as_ref())
117 }
118}
119
120impl<T: BaseEnvSetVar> EnvSetVar for T {}
121
122pub trait EnvUmask {
125 fn env_umask(&self) -> io::Result<u32>;
126}
127
128pub trait EnvSetUmask {
131 fn env_set_umask(&self, umask: u32) -> io::Result<u32>;
132}
133
134pub trait EnvCacheDir {
137 fn env_cache_dir(&self) -> Option<PathBuf>;
138}
139
140pub trait EnvHomeDir {
143 fn env_home_dir(&self) -> Option<PathBuf>;
144}
145
146pub trait EnvProgramsDir {
149 fn env_programs_dir(&self) -> Option<PathBuf>;
150}
151
152pub trait EnvTempDir {
155 fn env_temp_dir(&self) -> io::Result<PathBuf>;
156}
157
158#[cfg(windows)]
161type CustomFlagsValue = u32;
162#[cfg(not(windows))]
163type CustomFlagsValue = i32;
164
165#[derive(Default, Debug, Clone)]
166#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
167#[cfg_attr(feature = "serde", serde(default, rename_all = "camelCase"))]
168#[non_exhaustive] pub struct OpenOptions {
170 pub read: bool,
171 pub write: bool,
172 pub create: bool,
173 pub truncate: bool,
174 pub append: bool,
175 pub create_new: bool,
176 pub mode: Option<u32>,
178 pub custom_flags: Option<CustomFlagsValue>,
184 pub access_mode: Option<u32>,
186 pub share_mode: Option<u32>,
188 pub attributes: Option<u32>,
190 pub security_qos_flags: Option<u32>,
192}
193
194impl OpenOptions {
195 pub fn new() -> Self {
196 Self::default()
197 }
198
199 pub fn new_read() -> Self {
200 Self {
201 read: true,
202 write: false,
203 create: false,
204 truncate: false,
205 append: false,
206 create_new: false,
207 ..Default::default()
208 }
209 }
210
211 #[deprecated(note = "use `new_write` instead")]
213 pub fn write() -> Self {
214 Self::new_write()
215 }
216
217 pub fn new_write() -> Self {
218 Self {
219 read: false,
220 write: true,
221 create: true,
222 truncate: true,
223 append: false,
224 create_new: false,
225 ..Default::default()
226 }
227 }
228
229 pub fn new_append() -> Self {
230 Self {
231 read: false,
232 write: true,
233 create: false,
234 truncate: false,
235 append: true,
236 create_new: false,
237 ..Default::default()
238 }
239 }
240
241 #[inline]
242 pub fn read(&mut self) -> &mut Self {
243 self.read = true;
244 self
245 }
246
247 #[inline]
248 pub fn create(&mut self) -> &mut Self {
249 self.create = true;
250 self
251 }
252
253 #[inline]
254 pub fn truncate(&mut self) -> &mut Self {
255 self.truncate = true;
256 self
257 }
258
259 #[inline]
260 pub fn append(&mut self) -> &mut Self {
261 self.append = true;
262 self
263 }
264
265 #[inline]
266 pub fn create_new(&mut self) -> &mut Self {
267 self.create_new = true;
268 self
269 }
270
271 #[inline]
272 pub fn mode(&mut self, mode: u32) -> &mut Self {
273 self.mode = Some(mode);
274 self
275 }
276
277 #[inline]
278 pub fn custom_flags(&mut self, flags: CustomFlagsValue) -> &mut Self {
279 self.custom_flags = Some(flags);
280 self
281 }
282
283 #[inline]
284 pub fn access_mode(&mut self, value: u32) -> &mut Self {
285 self.access_mode = Some(value);
286 self
287 }
288
289 #[inline]
290 pub fn share_mode(&mut self, value: u32) -> &mut Self {
291 self.share_mode = Some(value);
292 self
293 }
294
295 #[inline]
296 pub fn attributes(&mut self, value: u32) -> &mut Self {
297 self.attributes = Some(value);
298 self
299 }
300
301 #[inline]
302 pub fn security_qos_flags(&mut self, value: u32) -> &mut Self {
303 self.security_qos_flags = Some(value);
304 self
305 }
306}
307
308pub trait BaseFsCanonicalize {
311 #[doc(hidden)]
312 fn base_fs_canonicalize(&self, path: &Path) -> io::Result<PathBuf>;
313}
314
315pub trait FsCanonicalize: BaseFsCanonicalize {
316 #[inline]
317 fn fs_canonicalize(&self, path: impl AsRef<Path>) -> io::Result<PathBuf> {
318 self.base_fs_canonicalize(path.as_ref())
319 }
320}
321
322impl<T: BaseFsCanonicalize> FsCanonicalize for T {}
323
324pub trait BaseFsChown {
327 #[doc(hidden)]
328 fn base_fs_chown(
329 &self,
330 path: &Path,
331 uid: Option<u32>,
332 gid: Option<u32>,
333 ) -> io::Result<()>;
334}
335
336pub trait FsChown: BaseFsChown {
337 #[inline]
338 fn fs_chown(
339 &self,
340 path: impl AsRef<Path>,
341 uid: Option<u32>,
342 gid: Option<u32>,
343 ) -> io::Result<()> {
344 self.base_fs_chown(path.as_ref(), uid, gid)
345 }
346}
347
348impl<T: BaseFsChown> FsChown for T {}
349
350pub trait BaseFsSymlinkChown {
353 #[doc(hidden)]
354 fn base_fs_symlink_chown(
355 &self,
356 path: &Path,
357 uid: Option<u32>,
358 gid: Option<u32>,
359 ) -> io::Result<()>;
360}
361
362pub trait FsSymlinkChown: BaseFsSymlinkChown {
363 #[inline]
364 fn fs_symlink_chown(
365 &self,
366 path: impl AsRef<Path>,
367 uid: Option<u32>,
368 gid: Option<u32>,
369 ) -> io::Result<()> {
370 self.base_fs_symlink_chown(path.as_ref(), uid, gid)
371 }
372}
373
374impl<T: BaseFsSymlinkChown> FsSymlinkChown for T {}
375
376pub trait BaseFsCloneFile {
379 #[doc(hidden)]
380 fn base_fs_clone_file(&self, from: &Path, to: &Path) -> io::Result<()>;
381}
382
383pub trait FsCloneFile: BaseFsCloneFile {
384 #[inline]
385 fn fs_clone_file(
386 &self,
387 from: impl AsRef<Path>,
388 to: impl AsRef<Path>,
389 ) -> io::Result<()> {
390 self.base_fs_clone_file(from.as_ref(), to.as_ref())
391 }
392}
393
394impl<T: BaseFsCloneFile> FsCloneFile for T {}
395
396pub trait BaseFsCopy {
399 #[doc(hidden)]
400 fn base_fs_copy(&self, from: &Path, to: &Path) -> io::Result<u64>;
401}
402
403pub trait FsCopy: BaseFsCopy {
404 #[inline]
405 fn fs_copy(
406 &self,
407 from: impl AsRef<Path>,
408 to: impl AsRef<Path>,
409 ) -> io::Result<u64> {
410 self.base_fs_copy(from.as_ref(), to.as_ref())
411 }
412}
413
414impl<T: BaseFsCopy> FsCopy for T {}
415
416#[derive(Default, Debug, Clone, Copy)]
419#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
420#[cfg_attr(feature = "serde", serde(default, rename_all = "camelCase"))]
421#[non_exhaustive] pub struct CreateDirOptions {
423 pub recursive: bool,
424 pub mode: Option<u32>,
426}
427
428impl CreateDirOptions {
429 pub fn new() -> Self {
430 Self::default()
431 }
432
433 pub fn new_recursive() -> Self {
434 Self {
435 recursive: true,
436 ..Default::default()
437 }
438 }
439
440 #[inline]
441 pub fn recursive(&mut self) -> &mut Self {
442 self.recursive = true;
443 self
444 }
445
446 #[inline]
447 pub fn mode(&mut self, mode: u32) -> &mut Self {
448 self.mode = Some(mode);
449 self
450 }
451}
452
453pub trait BaseFsCreateDir {
454 #[doc(hidden)]
455 fn base_fs_create_dir(
456 &self,
457 path: &Path,
458 options: &CreateDirOptions,
459 ) -> io::Result<()>;
460}
461
462pub trait FsCreateDir: BaseFsCreateDir {
463 fn fs_create_dir(
464 &self,
465 path: impl AsRef<Path>,
466 options: &CreateDirOptions,
467 ) -> io::Result<()> {
468 self.base_fs_create_dir(path.as_ref(), options)
469 }
470}
471
472impl<T: BaseFsCreateDir> FsCreateDir for T {}
473
474pub trait FsCreateDirAll: BaseFsCreateDir {
477 fn fs_create_dir_all(&self, path: impl AsRef<Path>) -> io::Result<()> {
478 self.base_fs_create_dir(
479 path.as_ref(),
480 &CreateDirOptions {
481 recursive: true,
482 mode: None,
483 },
484 )
485 }
486}
487
488impl<T: BaseFsCreateDir> FsCreateDirAll for T {}
489
490pub trait BaseFsHardLink {
493 #[doc(hidden)]
494 fn base_fs_hard_link(&self, src: &Path, dst: &Path) -> io::Result<()>;
495}
496
497pub trait FsHardLink: BaseFsHardLink {
498 fn fs_hard_link(
499 &self,
500 src: impl AsRef<Path>,
501 dst: impl AsRef<Path>,
502 ) -> io::Result<()> {
503 self.base_fs_hard_link(src.as_ref(), dst.as_ref())
504 }
505}
506
507impl<T: BaseFsHardLink> FsHardLink for T {}
508
509pub trait BaseFsCreateJunction {
512 #[doc(hidden)]
513 fn base_fs_create_junction(
514 &self,
515 original: &Path,
516 junction: &Path,
517 ) -> io::Result<()>;
518}
519
520pub trait FsCreateJunction: BaseFsCreateJunction {
521 fn fs_create_junction(
523 &self,
524 original: impl AsRef<Path>,
525 junction: impl AsRef<Path>,
526 ) -> io::Result<()> {
527 self.base_fs_create_junction(original.as_ref(), junction.as_ref())
528 }
529}
530
531impl<T: BaseFsCreateJunction> FsCreateJunction for T {}
532
533#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
536pub enum FileType {
537 File,
538 Dir,
539 Symlink,
540 Unknown,
541}
542
543impl FileType {
544 pub fn is_dir(&self) -> bool {
545 *self == Self::Dir
546 }
547
548 pub fn is_file(&self) -> bool {
549 *self == Self::File
550 }
551
552 pub fn is_symlink(&self) -> bool {
553 *self == Self::Symlink
554 }
555}
556
557impl From<std::fs::FileType> for FileType {
558 fn from(file_type: std::fs::FileType) -> Self {
559 if file_type.is_file() {
560 FileType::File
561 } else if file_type.is_dir() {
562 FileType::Dir
563 } else if file_type.is_symlink() {
564 FileType::Symlink
565 } else {
566 FileType::Unknown
567 }
568 }
569}
570
571#[allow(clippy::len_without_is_empty)]
572pub trait FsMetadataValue: std::fmt::Debug {
573 fn file_type(&self) -> FileType;
574 fn len(&self) -> u64;
575 fn accessed(&self) -> io::Result<SystemTime>;
576 fn created(&self) -> io::Result<SystemTime>;
577 fn changed(&self) -> io::Result<SystemTime>;
578 fn modified(&self) -> io::Result<SystemTime>;
579 fn dev(&self) -> io::Result<u64>;
580 fn ino(&self) -> io::Result<u64>;
581 fn mode(&self) -> io::Result<u32>;
582 fn nlink(&self) -> io::Result<u64>;
583 fn uid(&self) -> io::Result<u32>;
584 fn gid(&self) -> io::Result<u32>;
585 fn rdev(&self) -> io::Result<u64>;
586 fn blksize(&self) -> io::Result<u64>;
587 fn blocks(&self) -> io::Result<u64>;
588 fn is_block_device(&self) -> io::Result<bool>;
589 fn is_char_device(&self) -> io::Result<bool>;
590 fn is_fifo(&self) -> io::Result<bool>;
591 fn is_socket(&self) -> io::Result<bool>;
592 fn file_attributes(&self) -> io::Result<u32>;
593}
594
595pub trait BaseFsMetadata {
596 type Metadata: FsMetadataValue;
597
598 #[doc(hidden)]
599 fn base_fs_metadata(&self, path: &Path) -> io::Result<Self::Metadata>;
600
601 #[doc(hidden)]
602 fn base_fs_symlink_metadata(&self, path: &Path)
603 -> io::Result<Self::Metadata>;
604
605 #[doc(hidden)]
606 fn base_fs_exists(&self, path: &Path) -> io::Result<bool> {
607 match self.base_fs_symlink_metadata(path) {
608 Ok(_) => Ok(true),
609 Err(err) => {
610 if err.kind() == ErrorKind::NotFound {
611 Ok(false)
612 } else {
613 Err(err)
614 }
615 }
616 }
617 }
618
619 #[doc(hidden)]
620 fn base_fs_exists_no_err(&self, path: &Path) -> bool {
621 self.base_fs_exists(path).unwrap_or(false)
622 }
623}
624
625pub trait FsMetadata: BaseFsMetadata {
628 #[inline]
629 fn fs_metadata(&self, path: impl AsRef<Path>) -> io::Result<Self::Metadata> {
630 self.base_fs_metadata(path.as_ref())
631 }
632
633 #[inline]
634 fn fs_symlink_metadata(
635 &self,
636 path: impl AsRef<Path>,
637 ) -> io::Result<Self::Metadata> {
638 self.base_fs_symlink_metadata(path.as_ref())
639 }
640
641 #[inline]
642 fn fs_is_file(&self, path: impl AsRef<Path>) -> io::Result<bool> {
643 Ok(self.fs_metadata(path)?.file_type() == FileType::File)
644 }
645
646 #[inline]
647 fn fs_is_file_no_err(&self, path: impl AsRef<Path>) -> bool {
648 self.fs_is_file(path).unwrap_or(false)
649 }
650
651 #[inline]
652 fn fs_is_dir(&self, path: impl AsRef<Path>) -> io::Result<bool> {
653 Ok(self.fs_metadata(path)?.file_type() == FileType::Dir)
654 }
655
656 #[inline]
657 fn fs_is_dir_no_err(&self, path: impl AsRef<Path>) -> bool {
658 self.fs_is_dir(path).unwrap_or(false)
659 }
660
661 #[inline]
662 fn fs_exists(&self, path: impl AsRef<Path>) -> io::Result<bool> {
663 self.base_fs_exists(path.as_ref())
664 }
665
666 #[inline]
667 fn fs_exists_no_err(&self, path: impl AsRef<Path>) -> bool {
668 self.base_fs_exists_no_err(path.as_ref())
669 }
670
671 #[inline]
672 fn fs_is_symlink(&self, path: impl AsRef<Path>) -> io::Result<bool> {
673 Ok(self.fs_symlink_metadata(path)?.file_type() == FileType::Symlink)
674 }
675
676 #[inline]
677 fn fs_is_symlink_no_err(&self, path: impl AsRef<Path>) -> bool {
678 self.fs_is_symlink(path).unwrap_or(false)
679 }
680}
681
682impl<T: BaseFsMetadata> FsMetadata for T {}
683
684pub trait FsFile:
687 std::io::Read
688 + std::io::Write
689 + std::io::Seek
690 + FsFileIsTerminal
691 + FsFileLock
692 + FsFileMetadata
693 + FsFileSetPermissions
694 + FsFileSetTimes
695 + FsFileSetLen
696 + FsFileSyncAll
697 + FsFileSyncData
698 + FsFileAsRaw
699{
700}
701
702pub trait BoxableFsFile: Sized {
703 fn into_boxed(self) -> BoxedFsFile;
704}
705
706impl<T> BoxableFsFile for T
707where
708 T: FsFile + Sized + 'static,
709{
710 fn into_boxed(self) -> BoxedFsFile {
711 BoxedFsFile(Box::new(self))
712 }
713}
714
715pub trait BaseFsOpen {
716 type File: FsFile + Sized + 'static;
719
720 #[doc(hidden)]
721 fn base_fs_open(
722 &self,
723 path: &Path,
724 options: &OpenOptions,
725 ) -> io::Result<Self::File>;
726}
727
728pub trait FsOpen: BaseFsOpen {
729 #[inline]
730 fn fs_open(
731 &self,
732 path: impl AsRef<Path>,
733 options: &OpenOptions,
734 ) -> io::Result<Self::File> {
735 self.base_fs_open(path.as_ref(), options)
736 }
737}
738
739impl<T: BaseFsOpen> FsOpen for T {}
740
741pub trait BaseFsRead {
744 #[doc(hidden)]
745 fn base_fs_read(&self, path: &Path) -> io::Result<Cow<'static, [u8]>>;
746}
747
748pub trait FsRead: BaseFsRead {
749 #[inline]
750 fn fs_read(&self, path: impl AsRef<Path>) -> io::Result<Cow<'static, [u8]>> {
751 self.base_fs_read(path.as_ref())
752 }
753
754 fn fs_read_to_string(
755 &self,
756 path: impl AsRef<Path>,
757 ) -> io::Result<Cow<'static, str>> {
758 let bytes = self.fs_read(path)?;
759 match bytes {
760 Cow::Borrowed(bytes) => str::from_utf8(bytes)
761 .map(Cow::Borrowed)
762 .map_err(|e| e.to_string()),
763 Cow::Owned(bytes) => String::from_utf8(bytes)
764 .map(Cow::Owned)
765 .map_err(|e| e.to_string()),
766 }
767 .map_err(|error_text| Error::new(ErrorKind::InvalidData, error_text))
768 }
769
770 fn fs_read_to_string_lossy(
771 &self,
772 path: impl AsRef<Path>,
773 ) -> io::Result<Cow<'static, str>> {
774 #[inline(always)]
776 fn string_from_utf8_lossy(buf: Vec<u8>) -> String {
777 match String::from_utf8_lossy(&buf) {
778 Cow::Owned(s) => s,
780 Cow::Borrowed(_) => unsafe { String::from_utf8_unchecked(buf) },
783 }
784 }
785
786 let bytes = self.fs_read(path)?;
787 match bytes {
788 Cow::Borrowed(bytes) => Ok(String::from_utf8_lossy(bytes)),
789 Cow::Owned(bytes) => Ok(Cow::Owned(string_from_utf8_lossy(bytes))),
790 }
791 }
792}
793
794impl<T: BaseFsRead> FsRead for T {}
795
796pub trait FsDirEntry: std::fmt::Debug {
799 type Metadata: FsMetadataValue;
800
801 fn file_name(&self) -> Cow<'_, OsStr>;
802 fn file_type(&self) -> io::Result<FileType>;
803 fn metadata(&self) -> io::Result<Self::Metadata>;
804 fn path(&self) -> Cow<'_, Path>;
805}
806
807pub trait BaseFsReadDir {
808 type ReadDirEntry: FsDirEntry + 'static;
809
810 #[doc(hidden)]
811 fn base_fs_read_dir(
812 &self,
813 path: &Path,
814 ) -> io::Result<Box<dyn Iterator<Item = io::Result<Self::ReadDirEntry>>>>;
815}
816
817pub trait FsReadDir: BaseFsReadDir {
818 #[inline]
819 fn fs_read_dir(
820 &self,
821 path: impl AsRef<Path>,
822 ) -> io::Result<Box<dyn Iterator<Item = io::Result<Self::ReadDirEntry>>>> {
823 self.base_fs_read_dir(path.as_ref())
824 }
825}
826
827impl<T: BaseFsReadDir> FsReadDir for T {}
828
829pub trait BaseFsReadLink {
832 #[doc(hidden)]
833 fn base_fs_read_link(&self, path: &Path) -> io::Result<PathBuf>;
834}
835
836pub trait FsReadLink: BaseFsReadLink {
837 #[inline]
838 fn fs_read_link(&self, path: impl AsRef<Path>) -> io::Result<PathBuf> {
839 self.base_fs_read_link(path.as_ref())
840 }
841}
842
843impl<T: BaseFsReadLink> FsReadLink for T {}
844
845pub trait BaseFsRemoveDir {
848 #[doc(hidden)]
849 fn base_fs_remove_dir(&self, path: &Path) -> io::Result<()>;
850}
851
852pub trait FsRemoveDir: BaseFsRemoveDir {
853 #[inline]
854 fn fs_remove_dir(&self, path: impl AsRef<Path>) -> io::Result<()> {
855 self.base_fs_remove_dir(path.as_ref())
856 }
857}
858
859impl<T: BaseFsRemoveDir> FsRemoveDir for T {}
860
861pub trait BaseFsRemoveDirAll {
864 #[doc(hidden)]
865 fn base_fs_remove_dir_all(&self, path: &Path) -> io::Result<()>;
866}
867
868pub trait FsRemoveDirAll: BaseFsRemoveDirAll {
869 #[inline]
870 fn fs_remove_dir_all(&self, path: impl AsRef<Path>) -> io::Result<()> {
871 self.base_fs_remove_dir_all(path.as_ref())
872 }
873}
874
875impl<T: BaseFsRemoveDirAll> FsRemoveDirAll for T {}
876
877pub trait BaseFsRemoveFile {
880 #[doc(hidden)]
881 fn base_fs_remove_file(&self, path: &Path) -> io::Result<()>;
882}
883
884pub trait FsRemoveFile: BaseFsRemoveFile {
885 #[inline]
886 fn fs_remove_file(&self, path: impl AsRef<Path>) -> io::Result<()> {
887 self.base_fs_remove_file(path.as_ref())
888 }
889}
890
891impl<T: BaseFsRemoveFile> FsRemoveFile for T {}
892
893pub trait BaseFsRename {
896 #[doc(hidden)]
897 fn base_fs_rename(&self, from: &Path, to: &Path) -> io::Result<()>;
898}
899
900pub trait FsRename: BaseFsRename {
901 #[inline]
902 fn fs_rename(
903 &self,
904 from: impl AsRef<Path>,
905 to: impl AsRef<Path>,
906 ) -> io::Result<()> {
907 self.base_fs_rename(from.as_ref(), to.as_ref())
908 }
909}
910
911impl<T: BaseFsRename> FsRename for T {}
912
913pub trait BaseFsSetFileTimes {
916 #[doc(hidden)]
917 fn base_fs_set_file_times(
918 &self,
919 path: &Path,
920 atime: SystemTime,
921 mtime: SystemTime,
922 ) -> io::Result<()>;
923}
924
925pub trait FsSetFileTimes: BaseFsSetFileTimes {
926 #[inline]
927 fn fs_set_file_times(
928 &self,
929 path: impl AsRef<Path>,
930 atime: SystemTime,
931 mtime: SystemTime,
932 ) -> io::Result<()> {
933 self.base_fs_set_file_times(path.as_ref(), atime, mtime)
934 }
935}
936
937impl<T: BaseFsSetFileTimes> FsSetFileTimes for T {}
938
939pub trait BaseFsSetSymlinkFileTimes {
942 #[doc(hidden)]
943 fn base_fs_set_symlink_file_times(
944 &self,
945 path: &Path,
946 atime: SystemTime,
947 mtime: SystemTime,
948 ) -> io::Result<()>;
949}
950
951pub trait FsSetSymlinkFileTimes: BaseFsSetSymlinkFileTimes {
952 #[inline]
953 fn fs_set_symlink_file_times(
954 &self,
955 path: impl AsRef<Path>,
956 atime: SystemTime,
957 mtime: SystemTime,
958 ) -> io::Result<()> {
959 self.base_fs_set_symlink_file_times(path.as_ref(), atime, mtime)
960 }
961}
962
963impl<T: BaseFsSetSymlinkFileTimes> FsSetSymlinkFileTimes for T {}
964
965pub trait BaseFsSetPermissions {
968 #[doc(hidden)]
969 fn base_fs_set_permissions(&self, path: &Path, mode: u32) -> io::Result<()>;
970}
971
972pub trait FsSetPermissions: BaseFsSetPermissions {
973 fn fs_set_permissions(
974 &self,
975 path: impl AsRef<Path>,
976 mode: u32,
977 ) -> io::Result<()> {
978 self.base_fs_set_permissions(path.as_ref(), mode)
979 }
980}
981
982impl<T: BaseFsSetPermissions> FsSetPermissions for T {}
983
984pub trait BaseFsSymlinkDir {
987 #[doc(hidden)]
988 fn base_fs_symlink_dir(&self, original: &Path, link: &Path)
989 -> io::Result<()>;
990}
991
992pub trait FsSymlinkDir: BaseFsSymlinkDir {
993 #[inline]
994 fn fs_symlink_dir(
995 &self,
996 original: impl AsRef<Path>,
997 link: impl AsRef<Path>,
998 ) -> io::Result<()> {
999 self.base_fs_symlink_dir(original.as_ref(), link.as_ref())
1000 }
1001}
1002
1003impl<T: BaseFsSymlinkDir> FsSymlinkDir for T {}
1004
1005pub trait BaseFsSymlinkFile {
1008 #[doc(hidden)]
1009 fn base_fs_symlink_file(
1010 &self,
1011 original: &Path,
1012 link: &Path,
1013 ) -> io::Result<()>;
1014}
1015
1016pub trait FsSymlinkFile: BaseFsSymlinkFile {
1017 #[inline]
1018 fn fs_symlink_file(
1019 &self,
1020 original: impl AsRef<Path>,
1021 link: impl AsRef<Path>,
1022 ) -> io::Result<()> {
1023 self.base_fs_symlink_file(original.as_ref(), link.as_ref())
1024 }
1025}
1026
1027impl<T: BaseFsSymlinkFile> FsSymlinkFile for T {}
1028
1029pub trait BaseFsWrite {
1032 #[doc(hidden)]
1033 fn base_fs_write(&self, path: &Path, data: &[u8]) -> io::Result<()>;
1034}
1035
1036pub trait FsWrite: BaseFsWrite {
1037 #[inline]
1038 fn fs_write(
1039 &self,
1040 path: impl AsRef<Path>,
1041 data: impl AsRef<[u8]>,
1042 ) -> io::Result<()> {
1043 self.base_fs_write(path.as_ref(), data.as_ref())
1044 }
1045}
1046
1047impl<T: BaseFsWrite> FsWrite for T {}
1048
1049pub trait FsFileAsRaw {
1052 #[cfg(windows)]
1055 fn fs_file_as_raw_handle(&self) -> Option<std::os::windows::io::RawHandle>;
1056
1057 #[cfg(unix)]
1060 fn fs_file_as_raw_fd(&self) -> Option<std::os::fd::RawFd>;
1061}
1062
1063pub trait FsFileIsTerminal {
1064 fn fs_file_is_terminal(&self) -> bool;
1065}
1066
1067pub enum FsFileLockMode {
1068 Shared,
1069 Exclusive,
1070}
1071
1072pub trait FsFileLock {
1073 fn fs_file_lock(&mut self, mode: FsFileLockMode) -> io::Result<()>;
1074 fn fs_file_try_lock(&mut self, mode: FsFileLockMode) -> io::Result<()>;
1075 fn fs_file_unlock(&mut self) -> io::Result<()>;
1076}
1077
1078pub trait FsFileMetadata {
1079 fn fs_file_metadata(&self) -> io::Result<BoxedFsMetadataValue>;
1084}
1085
1086pub trait FsFileSetLen {
1087 fn fs_file_set_len(&mut self, size: u64) -> io::Result<()>;
1088}
1089
1090pub trait FsFileSetPermissions {
1091 fn fs_file_set_permissions(&mut self, mode: u32) -> io::Result<()>;
1092}
1093
1094#[derive(Debug, Clone, Default)]
1095pub struct FsFileTimes {
1096 pub accessed: Option<SystemTime>,
1097 pub modified: Option<SystemTime>,
1098}
1099
1100impl FsFileTimes {
1101 pub fn new() -> Self {
1102 Self::default()
1103 }
1104
1105 pub fn accessed(&mut self, accessed: SystemTime) -> &mut Self {
1106 self.accessed = Some(accessed);
1107 self
1108 }
1109
1110 pub fn modified(&mut self, accessed: SystemTime) -> &mut Self {
1111 self.modified = Some(accessed);
1112 self
1113 }
1114}
1115
1116pub trait FsFileSetTimes {
1117 fn fs_file_set_times(&mut self, times: FsFileTimes) -> io::Result<()>;
1118}
1119
1120pub trait FsFileSyncAll {
1121 fn fs_file_sync_all(&mut self) -> io::Result<()>;
1122}
1123
1124pub trait FsFileSyncData {
1125 fn fs_file_sync_data(&mut self) -> io::Result<()>;
1126}
1127
1128pub trait SystemTimeNow {
1131 fn sys_time_now(&self) -> std::time::SystemTime;
1132}
1133
1134pub trait SystemRandom {
1135 fn sys_random(&self, buf: &mut [u8]) -> io::Result<()>;
1136
1137 fn sys_random_u8(&self) -> io::Result<u8> {
1138 let mut buf = [0; 1];
1139 self.sys_random(&mut buf)?;
1140 Ok(buf[0])
1141 }
1142
1143 fn sys_random_u32(&self) -> io::Result<u32> {
1144 let mut buf = [0; 4];
1145 self.sys_random(&mut buf)?;
1146 Ok(u32::from_le_bytes(buf))
1147 }
1148
1149 fn sys_random_u64(&self) -> io::Result<u64> {
1150 let mut buf = [0; 8];
1151 self.sys_random(&mut buf)?;
1152 Ok(u64::from_le_bytes(buf))
1153 }
1154}
1155
1156pub trait ThreadSleep {
1157 fn thread_sleep(&self, duration: std::time::Duration);
1158}