Skip to content

Commit 949f251

Browse files
authored
Switch to custom FileTypeExt traits.
std has recently sealed its `FileTypeExt` traits, so cap-primitives can no longer implement them for its own types. Fortunately, these traits are just used as extension traits, so we can just define our own copies of them, and implement those instead. Fixes #270.
1 parent de73972 commit 949f251

File tree

17 files changed

+97
-70
lines changed

17 files changed

+97
-70
lines changed

cap-async-std/src/fs/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ pub use read_dir::ReadDir;
3737
#[cfg(not(target_os = "wasi"))]
3838
pub use cap_primitives::fs::{DirBuilder, FileType, Metadata, OpenOptions, Permissions};
3939

40+
// Re-export conditional types from `cap_primitives`.
41+
#[cfg(any(unix, target_os = "vxworks", all(windows, windows_file_type_ext)))]
42+
pub use cap_primitives::fs::FileTypeExt;
43+
4044
// Re-export things from `async_std` that we can use as-is.
4145
#[cfg(target_os = "wasi")]
4246
pub use async_std::fs::{DirBuilder, FileType, Metadata, OpenOptions, Permissions};

cap-async-std/src/fs_utf8/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ pub use read_dir::ReadDir;
2222
// Re-export things from `cap_std::fs` that we can use as-is.
2323
pub use crate::fs::{DirBuilder, FileType, Metadata, OpenOptions, Permissions};
2424

25+
// Re-export conditional types from `cap_primitives`.
26+
#[cfg(any(unix, target_os = "vxworks", all(windows, windows_file_type_ext)))]
27+
pub use cap_primitives::fs::FileTypeExt;
28+
2529
// Re-export `camino` to make it easy for users to depend on the same
2630
// version we do, because we use its types in our public API.
2731
pub use camino;

cap-fs-ext/src/file_type_ext.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -67,22 +67,22 @@ impl FileTypeExt for std::fs::FileType {
6767
impl FileTypeExt for cap_primitives::fs::FileType {
6868
#[inline]
6969
fn is_block_device(&self) -> bool {
70-
std::os::unix::fs::FileTypeExt::is_block_device(self)
70+
cap_primitives::fs::FileTypeExt::is_block_device(self)
7171
}
7272

7373
#[inline]
7474
fn is_char_device(&self) -> bool {
75-
std::os::unix::fs::FileTypeExt::is_char_device(self)
75+
cap_primitives::fs::FileTypeExt::is_char_device(self)
7676
}
7777

7878
#[inline]
7979
fn is_fifo(&self) -> bool {
80-
std::os::unix::fs::FileTypeExt::is_fifo(self)
80+
cap_primitives::fs::FileTypeExt::is_fifo(self)
8181
}
8282

8383
#[inline]
8484
fn is_socket(&self) -> bool {
85-
std::os::unix::fs::FileTypeExt::is_socket(self)
85+
cap_primitives::fs::FileTypeExt::is_socket(self)
8686
}
8787
}
8888

cap-primitives/src/fs/file_type.rs

+36-33
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! The `FileType` struct.
22
3-
use crate::fs::FileTypeExt;
3+
use crate::fs::ImplFileTypeExt;
44

55
/// `FileType`'s inner state.
66
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
@@ -15,7 +15,7 @@ enum Inner {
1515
Unknown,
1616

1717
/// A `FileTypeExt` type.
18-
Ext(FileTypeExt),
18+
Ext(ImplFileTypeExt),
1919
}
2020

2121
/// A structure representing a type of file with accessors for each file type.
@@ -51,7 +51,7 @@ impl FileType {
5151

5252
/// Creates a `FileType` from extension type.
5353
#[inline]
54-
pub(crate) const fn ext(ext: FileTypeExt) -> Self {
54+
pub(crate) const fn ext(ext: ImplFileTypeExt) -> Self {
5555
Self(Inner::Ext(ext))
5656
}
5757

@@ -84,62 +84,65 @@ impl FileType {
8484
}
8585
}
8686

87-
#[cfg(unix)]
88-
impl std::os::unix::fs::FileTypeExt for FileType {
89-
#[inline]
90-
fn is_block_device(&self) -> bool {
91-
self.0 == Inner::Ext(crate::fs::FileTypeExt::block_device())
92-
}
93-
94-
#[inline]
95-
fn is_char_device(&self) -> bool {
96-
self.0 == Inner::Ext(FileTypeExt::char_device())
97-
}
98-
99-
#[inline]
100-
fn is_fifo(&self) -> bool {
101-
self.0 == Inner::Ext(FileTypeExt::fifo())
102-
}
103-
104-
#[inline]
105-
fn is_socket(&self) -> bool {
106-
self.0 == Inner::Ext(FileTypeExt::socket())
107-
}
87+
/// Unix-specific extensions for [`FileType`].
88+
///
89+
/// This corresponds to [`std::os::unix::fs::FileTypeExt`].
90+
#[cfg(any(unix, target_os = "vxworks"))]
91+
pub trait FileTypeExt {
92+
/// Returns `true` if this file type is a block device.
93+
fn is_block_device(&self) -> bool;
94+
/// Returns `true` if this file type is a character device.
95+
fn is_char_device(&self) -> bool;
96+
/// Returns `true` if this file type is a fifo.
97+
fn is_fifo(&self) -> bool;
98+
/// Returns `true` if this file type is a socket.
99+
fn is_socket(&self) -> bool;
108100
}
109101

110-
#[cfg(target_os = "vxworks")]
111-
impl std::os::vxworks::fs::FileTypeExt for FileType {
102+
#[cfg(any(unix, target_os = "vxworks"))]
103+
impl FileTypeExt for FileType {
112104
#[inline]
113105
fn is_block_device(&self) -> bool {
114-
self.0 == Inner::Ext(FileTypeExt::BlockDevice)
106+
self.0 == Inner::Ext(ImplFileTypeExt::block_device())
115107
}
116108

117109
#[inline]
118110
fn is_char_device(&self) -> bool {
119-
self.0 == Inner::Ext(FileTypeExt::CharDevice)
111+
self.0 == Inner::Ext(ImplFileTypeExt::char_device())
120112
}
121113

122114
#[inline]
123115
fn is_fifo(&self) -> bool {
124-
self.0 == Inner::Ext(FileTypeExt::Fifo)
116+
self.0 == Inner::Ext(ImplFileTypeExt::fifo())
125117
}
126118

127119
#[inline]
128120
fn is_socket(&self) -> bool {
129-
self.0 == Inner::Ext(FileTypeExt::Socket)
121+
self.0 == Inner::Ext(ImplFileTypeExt::socket())
130122
}
131123
}
132124

125+
/// Windows-specific extensions for [`FileType`].
126+
///
127+
/// This corresponds to [`std::os::windows::fs::FileTypeExt`].
128+
#[cfg(all(windows, windows_file_type_ext))]
129+
pub trait FileTypeExt {
130+
/// Returns `true` if this file type is a symbolic link that is also a directory.
131+
fn is_symlink_dir(&self) -> bool;
132+
/// Returns `true` if this file type is a symbolic link that is also a file.
133+
fn is_symlink_file(&self) -> bool;
134+
}
135+
133136
#[cfg(all(windows, windows_file_type_ext))]
134-
impl std::os::windows::fs::FileTypeExt for FileType {
137+
impl FileTypeExt for FileType {
135138
#[inline]
136139
fn is_symlink_dir(&self) -> bool {
137-
self.0 == Inner::Ext(FileTypeExt::symlink_dir())
140+
self.0 == Inner::Ext(ImplFileTypeExt::symlink_dir())
138141
}
139142

140143
#[inline]
141144
fn is_symlink_file(&self) -> bool {
142-
self.0 == Inner::Ext(FileTypeExt::symlink_file())
145+
self.0 == Inner::Ext(ImplFileTypeExt::symlink_file())
143146
}
144147
}
145148

cap-primitives/src/fs/metadata.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::fs::{FileType, FileTypeExt, MetadataExt, Permissions};
1+
use crate::fs::{FileType, ImplFileTypeExt, MetadataExt, Permissions};
22
use crate::time::SystemTime;
33
use std::{fs, io};
44

@@ -28,7 +28,7 @@ impl Metadata {
2828
pub fn from_file(file: &fs::File) -> io::Result<Self> {
2929
let std = file.metadata()?;
3030
let ext = MetadataExt::from(file, &std)?;
31-
let file_type = FileTypeExt::from(file, &std)?;
31+
let file_type = ImplFileTypeExt::from(file, &std)?;
3232
Ok(Self::from_parts(std, ext, file_type))
3333
}
3434

@@ -42,7 +42,7 @@ impl Metadata {
4242
#[inline]
4343
pub fn from_just_metadata(std: fs::Metadata) -> Self {
4444
let ext = MetadataExt::from_just_metadata(&std);
45-
let file_type = FileTypeExt::from_just_metadata(&std);
45+
let file_type = ImplFileTypeExt::from_just_metadata(&std);
4646
Self::from_parts(std, ext, file_type)
4747
}
4848

cap-primitives/src/fs/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ pub use dir_entry::DirEntry;
6666
pub use dir_entry::_WindowsDirEntryExt;
6767
pub use dir_options::DirOptions;
6868
pub use file_type::FileType;
69+
#[cfg(any(unix, target_os = "vxworks", all(windows, windows_file_type_ext)))]
70+
pub use file_type::FileTypeExt;
6971
#[cfg(windows)]
7072
pub use file_type::_WindowsFileTypeExt;
7173
pub use follow_symlinks::FollowSymlinks;

cap-primitives/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
#![deny(missing_docs)]
44
#![deny(unsafe_code)]
5+
#![allow(stable_features)]
56
#![cfg_attr(target_os = "wasi", feature(wasi_ext))]
67
#![cfg_attr(all(windows, windows_by_handle), feature(windows_by_handle))]
78
#![cfg_attr(all(windows, windows_file_type_ext), feature(windows_file_type_ext))]

cap-primitives/src/rustix/fs/dir_entry_inner.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::fs::{
2-
FileType, FileTypeExt, FollowSymlinks, Metadata, OpenOptions, ReadDir, ReadDirInner,
2+
FileType, FollowSymlinks, ImplFileTypeExt, Metadata, OpenOptions, ReadDir, ReadDirInner,
33
};
44
use rustix::fs::DirEntry;
55
use std::ffi::{OsStr, OsString};
@@ -46,13 +46,13 @@ impl DirEntryInner {
4646
Ok(match self.rustix.file_type() {
4747
rustix::fs::FileType::Directory => FileType::dir(),
4848
rustix::fs::FileType::RegularFile => FileType::file(),
49-
rustix::fs::FileType::Symlink => FileType::ext(FileTypeExt::symlink()),
49+
rustix::fs::FileType::Symlink => FileType::ext(ImplFileTypeExt::symlink()),
5050
#[cfg(not(target_os = "wasi"))]
51-
rustix::fs::FileType::Fifo => FileType::ext(FileTypeExt::fifo()),
51+
rustix::fs::FileType::Fifo => FileType::ext(ImplFileTypeExt::fifo()),
5252
#[cfg(not(target_os = "wasi"))]
53-
rustix::fs::FileType::Socket => FileType::ext(FileTypeExt::socket()),
54-
rustix::fs::FileType::CharacterDevice => FileType::ext(FileTypeExt::char_device()),
55-
rustix::fs::FileType::BlockDevice => FileType::ext(FileTypeExt::block_device()),
53+
rustix::fs::FileType::Socket => FileType::ext(ImplFileTypeExt::socket()),
54+
rustix::fs::FileType::CharacterDevice => FileType::ext(ImplFileTypeExt::char_device()),
55+
rustix::fs::FileType::BlockDevice => FileType::ext(ImplFileTypeExt::block_device()),
5656
rustix::fs::FileType::Unknown => FileType::unknown(),
5757
})
5858
}

cap-primitives/src/rustix/fs/file_type_ext.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,17 @@ use crate::fs::FileType;
22
use rustix::fs::RawMode;
33
use std::{fs, io};
44

5+
/// A type that implements `FileTypeExt` for this platform.
56
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
6-
pub(crate) enum FileTypeExt {
7+
pub(crate) enum ImplFileTypeExt {
78
Symlink,
89
BlockDevice,
910
CharDevice,
1011
Fifo,
1112
Socket,
1213
}
1314

14-
impl FileTypeExt {
15+
impl ImplFileTypeExt {
1516
/// Constructs a new instance of `FileType` from the given
1617
/// [`std::fs::File`] and [`std::fs::FileType`].
1718
#[inline]

cap-primitives/src/rustix/fs/metadata_ext.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![allow(clippy::useless_conversion)]
22

3-
use crate::fs::{FileTypeExt, Metadata, PermissionsExt};
3+
use crate::fs::{ImplFileTypeExt, Metadata, PermissionsExt};
44
use crate::time::{Duration, SystemClock, SystemTime};
55
#[cfg(any(target_os = "android", target_os = "linux"))]
66
use rustix::fs::{makedev, Statx, StatxFlags};
@@ -103,7 +103,7 @@ impl MetadataExt {
103103
#[inline]
104104
pub(crate) fn from_rustix(stat: Stat) -> Metadata {
105105
Metadata {
106-
file_type: FileTypeExt::from_raw_mode(stat.st_mode as RawMode),
106+
file_type: ImplFileTypeExt::from_raw_mode(stat.st_mode as RawMode),
107107
len: u64::try_from(stat.st_size).unwrap(),
108108
#[cfg(not(target_os = "wasi"))]
109109
permissions: PermissionsExt::from_raw_mode(stat.st_mode as RawMode),
@@ -223,7 +223,7 @@ impl MetadataExt {
223223
#[inline]
224224
pub(crate) fn from_rustix_statx(statx: Statx) -> Metadata {
225225
Metadata {
226-
file_type: FileTypeExt::from_raw_mode(RawMode::from(statx.stx_mode)),
226+
file_type: ImplFileTypeExt::from_raw_mode(RawMode::from(statx.stx_mode)),
227227
len: u64::try_from(statx.stx_size).unwrap(),
228228
permissions: PermissionsExt::from_raw_mode(RawMode::from(statx.stx_mode)),
229229
modified: if statx.stx_mask & StatxFlags::MTIME.bits() != 0 {

cap-primitives/src/rustix/fs/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ pub(crate) use dir_entry_inner::DirEntryInner;
8686
#[cfg(not(target_os = "wasi"))]
8787
pub(crate) use dir_options_ext::DirOptionsExt;
8888
pub(crate) use dir_utils::*;
89-
pub(crate) use file_type_ext::FileTypeExt;
89+
pub(crate) use file_type_ext::ImplFileTypeExt;
9090
pub(crate) use hard_link_unchecked::hard_link_unchecked;
9191
pub(crate) use is_file_read_write_impl::is_file_read_write_impl;
9292
pub(crate) use is_root_dir::is_root_dir;

cap-primitives/src/windows/fs/dir_entry_inner.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use super::open_options_to_std;
22
use crate::ambient_authority;
33
use crate::fs::{
4-
open, open_ambient_dir, FileType, FileTypeExt, FollowSymlinks, Metadata, OpenOptions, ReadDir,
5-
ReadDirInner,
4+
open, open_ambient_dir, FileType, FollowSymlinks, ImplFileTypeExt, Metadata, OpenOptions,
5+
ReadDir, ReadDirInner,
66
};
77
use std::ffi::OsString;
88
use std::os::windows::fs::OpenOptionsExt;
@@ -83,7 +83,7 @@ impl DirEntryInner {
8383

8484
#[inline]
8585
pub(crate) fn file_type(&self) -> io::Result<FileType> {
86-
self.std.file_type().map(FileTypeExt::from_std)
86+
self.std.file_type().map(ImplFileTypeExt::from_std)
8787
}
8888

8989
#[inline]

cap-primitives/src/windows/fs/file_type_ext.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use crate::fs::FileType;
22
use std::{fs, io};
33

4+
/// A type that implements `FileTypeExt` for this platform.
45
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
5-
pub(crate) enum FileTypeExt {
6+
pub(crate) enum ImplFileTypeExt {
67
CharacterDevice,
78
Fifo,
89
#[cfg(windows_file_type_ext)]
@@ -12,7 +13,7 @@ pub(crate) enum FileTypeExt {
1213
SymlinkUnknown,
1314
}
1415

15-
impl FileTypeExt {
16+
impl ImplFileTypeExt {
1617
/// Constructs a new instance of `Self` from the given [`std::fs::File`]
1718
/// and [`std::fs::Metadata`].
1819
pub(crate) fn from(file: &fs::File, metadata: &fs::Metadata) -> io::Result<FileType> {
@@ -25,10 +26,10 @@ impl FileTypeExt {
2526
// Use the open file to check for one of the exotic file types.
2627
let file_type = winapi_util::file::typ(file)?;
2728
if file_type.is_char() {
28-
return Ok(FileType::ext(FileTypeExt::CharacterDevice));
29+
return Ok(FileType::ext(ImplFileTypeExt::CharacterDevice));
2930
}
3031
if file_type.is_pipe() {
31-
return Ok(FileType::ext(FileTypeExt::Fifo));
32+
return Ok(FileType::ext(ImplFileTypeExt::Fifo));
3233
}
3334

3435
Ok(FileType::unknown())
@@ -105,12 +106,12 @@ impl crate::fs::_WindowsFileTypeExt for crate::fs::FileType {
105106

106107
#[inline]
107108
fn is_char_device(&self) -> bool {
108-
*self == FileType::ext(FileTypeExt::CharacterDevice)
109+
*self == FileType::ext(ImplFileTypeExt::CharacterDevice)
109110
}
110111

111112
#[inline]
112113
fn is_fifo(&self) -> bool {
113-
*self == FileType::ext(FileTypeExt::Fifo)
114+
*self == FileType::ext(ImplFileTypeExt::Fifo)
114115
}
115116

116117
#[inline]

cap-primitives/src/windows/fs/remove_dir_all_impl.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
use super::get_path::get_path;
22
use crate::fs::{open_dir, open_dir_nofollow, remove_dir, stat, FollowSymlinks};
3-
#[cfg(windows_file_type_ext)]
4-
use std::os::windows::fs::FileTypeExt;
53
use std::path::Path;
64
use std::{fs, io};
75

cap-std/src/fs/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,7 @@ pub use read_dir::ReadDir;
3434

3535
// Re-export types from `cap_primitives`.
3636
pub use cap_primitives::fs::{DirBuilder, FileType, Metadata, OpenOptions, Permissions};
37+
38+
// Re-export conditional types from `cap_primitives`.
39+
#[cfg(any(unix, target_os = "vxworks", all(windows, windows_file_type_ext)))]
40+
pub use cap_primitives::fs::FileTypeExt;

cap-std/src/fs_utf8/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ pub use read_dir::ReadDir;
2424
// Re-export things from `cap_std::fs` that we can use as-is.
2525
pub use crate::fs::{DirBuilder, FileType, Metadata, OpenOptions, Permissions};
2626

27+
// Re-export conditional types from `cap_primitives`.
28+
#[cfg(any(unix, target_os = "vxworks", all(windows, windows_file_type_ext)))]
29+
pub use cap_primitives::fs::FileTypeExt;
30+
2731
// Re-export `camino` to make it easy for users to depend on the same
2832
// version we do, because we use its types in our public API.
2933
pub use camino;

0 commit comments

Comments
 (0)