Skip to content

Commit

Permalink
Switch to custom FileTypeExt traits.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
sunfishcode authored Aug 23, 2022
1 parent de73972 commit 949f251
Show file tree
Hide file tree
Showing 17 changed files with 97 additions and 70 deletions.
4 changes: 4 additions & 0 deletions cap-async-std/src/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ pub use read_dir::ReadDir;
#[cfg(not(target_os = "wasi"))]
pub use cap_primitives::fs::{DirBuilder, FileType, Metadata, OpenOptions, Permissions};

// Re-export conditional types from `cap_primitives`.
#[cfg(any(unix, target_os = "vxworks", all(windows, windows_file_type_ext)))]
pub use cap_primitives::fs::FileTypeExt;

// Re-export things from `async_std` that we can use as-is.
#[cfg(target_os = "wasi")]
pub use async_std::fs::{DirBuilder, FileType, Metadata, OpenOptions, Permissions};
4 changes: 4 additions & 0 deletions cap-async-std/src/fs_utf8/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ pub use read_dir::ReadDir;
// Re-export things from `cap_std::fs` that we can use as-is.
pub use crate::fs::{DirBuilder, FileType, Metadata, OpenOptions, Permissions};

// Re-export conditional types from `cap_primitives`.
#[cfg(any(unix, target_os = "vxworks", all(windows, windows_file_type_ext)))]
pub use cap_primitives::fs::FileTypeExt;

// Re-export `camino` to make it easy for users to depend on the same
// version we do, because we use its types in our public API.
pub use camino;
Expand Down
8 changes: 4 additions & 4 deletions cap-fs-ext/src/file_type_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,22 +67,22 @@ impl FileTypeExt for std::fs::FileType {
impl FileTypeExt for cap_primitives::fs::FileType {
#[inline]
fn is_block_device(&self) -> bool {
std::os::unix::fs::FileTypeExt::is_block_device(self)
cap_primitives::fs::FileTypeExt::is_block_device(self)
}

#[inline]
fn is_char_device(&self) -> bool {
std::os::unix::fs::FileTypeExt::is_char_device(self)
cap_primitives::fs::FileTypeExt::is_char_device(self)
}

#[inline]
fn is_fifo(&self) -> bool {
std::os::unix::fs::FileTypeExt::is_fifo(self)
cap_primitives::fs::FileTypeExt::is_fifo(self)
}

#[inline]
fn is_socket(&self) -> bool {
std::os::unix::fs::FileTypeExt::is_socket(self)
cap_primitives::fs::FileTypeExt::is_socket(self)
}
}

Expand Down
69 changes: 36 additions & 33 deletions cap-primitives/src/fs/file_type.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! The `FileType` struct.
use crate::fs::FileTypeExt;
use crate::fs::ImplFileTypeExt;

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

/// A `FileTypeExt` type.
Ext(FileTypeExt),
Ext(ImplFileTypeExt),
}

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

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

Expand Down Expand Up @@ -84,62 +84,65 @@ impl FileType {
}
}

#[cfg(unix)]
impl std::os::unix::fs::FileTypeExt for FileType {
#[inline]
fn is_block_device(&self) -> bool {
self.0 == Inner::Ext(crate::fs::FileTypeExt::block_device())
}

#[inline]
fn is_char_device(&self) -> bool {
self.0 == Inner::Ext(FileTypeExt::char_device())
}

#[inline]
fn is_fifo(&self) -> bool {
self.0 == Inner::Ext(FileTypeExt::fifo())
}

#[inline]
fn is_socket(&self) -> bool {
self.0 == Inner::Ext(FileTypeExt::socket())
}
/// Unix-specific extensions for [`FileType`].
///
/// This corresponds to [`std::os::unix::fs::FileTypeExt`].
#[cfg(any(unix, target_os = "vxworks"))]
pub trait FileTypeExt {
/// Returns `true` if this file type is a block device.
fn is_block_device(&self) -> bool;
/// Returns `true` if this file type is a character device.
fn is_char_device(&self) -> bool;
/// Returns `true` if this file type is a fifo.
fn is_fifo(&self) -> bool;
/// Returns `true` if this file type is a socket.
fn is_socket(&self) -> bool;
}

#[cfg(target_os = "vxworks")]
impl std::os::vxworks::fs::FileTypeExt for FileType {
#[cfg(any(unix, target_os = "vxworks"))]
impl FileTypeExt for FileType {
#[inline]
fn is_block_device(&self) -> bool {
self.0 == Inner::Ext(FileTypeExt::BlockDevice)
self.0 == Inner::Ext(ImplFileTypeExt::block_device())
}

#[inline]
fn is_char_device(&self) -> bool {
self.0 == Inner::Ext(FileTypeExt::CharDevice)
self.0 == Inner::Ext(ImplFileTypeExt::char_device())
}

#[inline]
fn is_fifo(&self) -> bool {
self.0 == Inner::Ext(FileTypeExt::Fifo)
self.0 == Inner::Ext(ImplFileTypeExt::fifo())
}

#[inline]
fn is_socket(&self) -> bool {
self.0 == Inner::Ext(FileTypeExt::Socket)
self.0 == Inner::Ext(ImplFileTypeExt::socket())
}
}

/// Windows-specific extensions for [`FileType`].
///
/// This corresponds to [`std::os::windows::fs::FileTypeExt`].
#[cfg(all(windows, windows_file_type_ext))]
pub trait FileTypeExt {
/// Returns `true` if this file type is a symbolic link that is also a directory.
fn is_symlink_dir(&self) -> bool;
/// Returns `true` if this file type is a symbolic link that is also a file.
fn is_symlink_file(&self) -> bool;
}

#[cfg(all(windows, windows_file_type_ext))]
impl std::os::windows::fs::FileTypeExt for FileType {
impl FileTypeExt for FileType {
#[inline]
fn is_symlink_dir(&self) -> bool {
self.0 == Inner::Ext(FileTypeExt::symlink_dir())
self.0 == Inner::Ext(ImplFileTypeExt::symlink_dir())
}

#[inline]
fn is_symlink_file(&self) -> bool {
self.0 == Inner::Ext(FileTypeExt::symlink_file())
self.0 == Inner::Ext(ImplFileTypeExt::symlink_file())
}
}

Expand Down
6 changes: 3 additions & 3 deletions cap-primitives/src/fs/metadata.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::fs::{FileType, FileTypeExt, MetadataExt, Permissions};
use crate::fs::{FileType, ImplFileTypeExt, MetadataExt, Permissions};
use crate::time::SystemTime;
use std::{fs, io};

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

Expand All @@ -42,7 +42,7 @@ impl Metadata {
#[inline]
pub fn from_just_metadata(std: fs::Metadata) -> Self {
let ext = MetadataExt::from_just_metadata(&std);
let file_type = FileTypeExt::from_just_metadata(&std);
let file_type = ImplFileTypeExt::from_just_metadata(&std);
Self::from_parts(std, ext, file_type)
}

Expand Down
2 changes: 2 additions & 0 deletions cap-primitives/src/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ pub use dir_entry::DirEntry;
pub use dir_entry::_WindowsDirEntryExt;
pub use dir_options::DirOptions;
pub use file_type::FileType;
#[cfg(any(unix, target_os = "vxworks", all(windows, windows_file_type_ext)))]
pub use file_type::FileTypeExt;
#[cfg(windows)]
pub use file_type::_WindowsFileTypeExt;
pub use follow_symlinks::FollowSymlinks;
Expand Down
1 change: 1 addition & 0 deletions cap-primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#![deny(missing_docs)]
#![deny(unsafe_code)]
#![allow(stable_features)]
#![cfg_attr(target_os = "wasi", feature(wasi_ext))]
#![cfg_attr(all(windows, windows_by_handle), feature(windows_by_handle))]
#![cfg_attr(all(windows, windows_file_type_ext), feature(windows_file_type_ext))]
Expand Down
12 changes: 6 additions & 6 deletions cap-primitives/src/rustix/fs/dir_entry_inner.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::fs::{
FileType, FileTypeExt, FollowSymlinks, Metadata, OpenOptions, ReadDir, ReadDirInner,
FileType, FollowSymlinks, ImplFileTypeExt, Metadata, OpenOptions, ReadDir, ReadDirInner,
};
use rustix::fs::DirEntry;
use std::ffi::{OsStr, OsString};
Expand Down Expand Up @@ -46,13 +46,13 @@ impl DirEntryInner {
Ok(match self.rustix.file_type() {
rustix::fs::FileType::Directory => FileType::dir(),
rustix::fs::FileType::RegularFile => FileType::file(),
rustix::fs::FileType::Symlink => FileType::ext(FileTypeExt::symlink()),
rustix::fs::FileType::Symlink => FileType::ext(ImplFileTypeExt::symlink()),
#[cfg(not(target_os = "wasi"))]
rustix::fs::FileType::Fifo => FileType::ext(FileTypeExt::fifo()),
rustix::fs::FileType::Fifo => FileType::ext(ImplFileTypeExt::fifo()),
#[cfg(not(target_os = "wasi"))]
rustix::fs::FileType::Socket => FileType::ext(FileTypeExt::socket()),
rustix::fs::FileType::CharacterDevice => FileType::ext(FileTypeExt::char_device()),
rustix::fs::FileType::BlockDevice => FileType::ext(FileTypeExt::block_device()),
rustix::fs::FileType::Socket => FileType::ext(ImplFileTypeExt::socket()),
rustix::fs::FileType::CharacterDevice => FileType::ext(ImplFileTypeExt::char_device()),
rustix::fs::FileType::BlockDevice => FileType::ext(ImplFileTypeExt::block_device()),
rustix::fs::FileType::Unknown => FileType::unknown(),
})
}
Expand Down
5 changes: 3 additions & 2 deletions cap-primitives/src/rustix/fs/file_type_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ use crate::fs::FileType;
use rustix::fs::RawMode;
use std::{fs, io};

/// A type that implements `FileTypeExt` for this platform.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub(crate) enum FileTypeExt {
pub(crate) enum ImplFileTypeExt {
Symlink,
BlockDevice,
CharDevice,
Fifo,
Socket,
}

impl FileTypeExt {
impl ImplFileTypeExt {
/// Constructs a new instance of `FileType` from the given
/// [`std::fs::File`] and [`std::fs::FileType`].
#[inline]
Expand Down
6 changes: 3 additions & 3 deletions cap-primitives/src/rustix/fs/metadata_ext.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![allow(clippy::useless_conversion)]

use crate::fs::{FileTypeExt, Metadata, PermissionsExt};
use crate::fs::{ImplFileTypeExt, Metadata, PermissionsExt};
use crate::time::{Duration, SystemClock, SystemTime};
#[cfg(any(target_os = "android", target_os = "linux"))]
use rustix::fs::{makedev, Statx, StatxFlags};
Expand Down Expand Up @@ -103,7 +103,7 @@ impl MetadataExt {
#[inline]
pub(crate) fn from_rustix(stat: Stat) -> Metadata {
Metadata {
file_type: FileTypeExt::from_raw_mode(stat.st_mode as RawMode),
file_type: ImplFileTypeExt::from_raw_mode(stat.st_mode as RawMode),
len: u64::try_from(stat.st_size).unwrap(),
#[cfg(not(target_os = "wasi"))]
permissions: PermissionsExt::from_raw_mode(stat.st_mode as RawMode),
Expand Down Expand Up @@ -223,7 +223,7 @@ impl MetadataExt {
#[inline]
pub(crate) fn from_rustix_statx(statx: Statx) -> Metadata {
Metadata {
file_type: FileTypeExt::from_raw_mode(RawMode::from(statx.stx_mode)),
file_type: ImplFileTypeExt::from_raw_mode(RawMode::from(statx.stx_mode)),
len: u64::try_from(statx.stx_size).unwrap(),
permissions: PermissionsExt::from_raw_mode(RawMode::from(statx.stx_mode)),
modified: if statx.stx_mask & StatxFlags::MTIME.bits() != 0 {
Expand Down
2 changes: 1 addition & 1 deletion cap-primitives/src/rustix/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ pub(crate) use dir_entry_inner::DirEntryInner;
#[cfg(not(target_os = "wasi"))]
pub(crate) use dir_options_ext::DirOptionsExt;
pub(crate) use dir_utils::*;
pub(crate) use file_type_ext::FileTypeExt;
pub(crate) use file_type_ext::ImplFileTypeExt;
pub(crate) use hard_link_unchecked::hard_link_unchecked;
pub(crate) use is_file_read_write_impl::is_file_read_write_impl;
pub(crate) use is_root_dir::is_root_dir;
Expand Down
6 changes: 3 additions & 3 deletions cap-primitives/src/windows/fs/dir_entry_inner.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use super::open_options_to_std;
use crate::ambient_authority;
use crate::fs::{
open, open_ambient_dir, FileType, FileTypeExt, FollowSymlinks, Metadata, OpenOptions, ReadDir,
ReadDirInner,
open, open_ambient_dir, FileType, FollowSymlinks, ImplFileTypeExt, Metadata, OpenOptions,
ReadDir, ReadDirInner,
};
use std::ffi::OsString;
use std::os::windows::fs::OpenOptionsExt;
Expand Down Expand Up @@ -83,7 +83,7 @@ impl DirEntryInner {

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

#[inline]
Expand Down
13 changes: 7 additions & 6 deletions cap-primitives/src/windows/fs/file_type_ext.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::fs::FileType;
use std::{fs, io};

/// A type that implements `FileTypeExt` for this platform.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub(crate) enum FileTypeExt {
pub(crate) enum ImplFileTypeExt {
CharacterDevice,
Fifo,
#[cfg(windows_file_type_ext)]
Expand All @@ -12,7 +13,7 @@ pub(crate) enum FileTypeExt {
SymlinkUnknown,
}

impl FileTypeExt {
impl ImplFileTypeExt {
/// Constructs a new instance of `Self` from the given [`std::fs::File`]
/// and [`std::fs::Metadata`].
pub(crate) fn from(file: &fs::File, metadata: &fs::Metadata) -> io::Result<FileType> {
Expand All @@ -25,10 +26,10 @@ impl FileTypeExt {
// Use the open file to check for one of the exotic file types.
let file_type = winapi_util::file::typ(file)?;
if file_type.is_char() {
return Ok(FileType::ext(FileTypeExt::CharacterDevice));
return Ok(FileType::ext(ImplFileTypeExt::CharacterDevice));
}
if file_type.is_pipe() {
return Ok(FileType::ext(FileTypeExt::Fifo));
return Ok(FileType::ext(ImplFileTypeExt::Fifo));
}

Ok(FileType::unknown())
Expand Down Expand Up @@ -105,12 +106,12 @@ impl crate::fs::_WindowsFileTypeExt for crate::fs::FileType {

#[inline]
fn is_char_device(&self) -> bool {
*self == FileType::ext(FileTypeExt::CharacterDevice)
*self == FileType::ext(ImplFileTypeExt::CharacterDevice)
}

#[inline]
fn is_fifo(&self) -> bool {
*self == FileType::ext(FileTypeExt::Fifo)
*self == FileType::ext(ImplFileTypeExt::Fifo)
}

#[inline]
Expand Down
2 changes: 0 additions & 2 deletions cap-primitives/src/windows/fs/remove_dir_all_impl.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use super::get_path::get_path;
use crate::fs::{open_dir, open_dir_nofollow, remove_dir, stat, FollowSymlinks};
#[cfg(windows_file_type_ext)]
use std::os::windows::fs::FileTypeExt;
use std::path::Path;
use std::{fs, io};

Expand Down
4 changes: 4 additions & 0 deletions cap-std/src/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,7 @@ pub use read_dir::ReadDir;

// Re-export types from `cap_primitives`.
pub use cap_primitives::fs::{DirBuilder, FileType, Metadata, OpenOptions, Permissions};

// Re-export conditional types from `cap_primitives`.
#[cfg(any(unix, target_os = "vxworks", all(windows, windows_file_type_ext)))]
pub use cap_primitives::fs::FileTypeExt;
4 changes: 4 additions & 0 deletions cap-std/src/fs_utf8/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ pub use read_dir::ReadDir;
// Re-export things from `cap_std::fs` that we can use as-is.
pub use crate::fs::{DirBuilder, FileType, Metadata, OpenOptions, Permissions};

// Re-export conditional types from `cap_primitives`.
#[cfg(any(unix, target_os = "vxworks", all(windows, windows_file_type_ext)))]
pub use cap_primitives::fs::FileTypeExt;

// Re-export `camino` to make it easy for users to depend on the same
// version we do, because we use its types in our public API.
pub use camino;
Expand Down
Loading

0 comments on commit 949f251

Please sign in to comment.