chore: 🤖 remove generic in FileSystem trait (#1163)

generic will make the Trait non-object safe, so use a specific type
instead a generic instead.
```rs
// Examples of non-object safe traits.
trait NotObjectSafe {
    const CONST: i32 = 1;  // ERROR: cannot have associated const

    fn foo() {}  // ERROR: associated function without Sized
    fn returns(&self) -> Self; // ERROR: Self in return type
    fn typed<T>(&self, x: T) {} // ERROR: has generic type parameters
    fn nested(self: Rc<Box<Self>>) {} // ERROR: nested receiver not yet supported
}

struct S;
impl NotObjectSafe for S {
    fn returns(&self) -> Self { S }
}
let obj: Box<dyn NotObjectSafe> = Box::new(S); // ERROR

```
This commit is contained in:
IWANABETHATGUY 2023-11-06 11:19:48 +08:00 committed by GitHub
parent 58f8225e08
commit cedd2e904c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 15 deletions

View file

@ -10,28 +10,47 @@ pub trait FileSystem: Send + Sync {
/// # Errors
///
/// * See [std::fs::read_to_string]
fn read_to_string<P: AsRef<Path>>(&self, path: P) -> io::Result<String>;
/// ## Warning
/// Use `&Path` instead of a generic `P: AsRef<Path>` here,
/// because object safety requirements, it is especially useful, when
/// you want to store multiple `dyn FileSystem` in a `Vec` or use a `ResolverGeneric<Fs>` in
/// napi env.
fn read_to_string(&self, path: &Path) -> io::Result<String>;
/// See [std::fs::metadata]
///
/// # Errors
///
/// See [std::fs::metadata]
fn metadata<P: AsRef<Path>>(&self, path: P) -> io::Result<FileMetadata>;
/// ## Warning
/// Use `&Path` instead of a generic `P: AsRef<Path>` here,
/// because object safety requirements, it is especially useful, when
/// you want to store multiple `dyn FileSystem` in a `Vec` or use a `ResolverGeneric<Fs>` in
/// napi env.
fn metadata(&self, path: &Path) -> io::Result<FileMetadata>;
/// See [std::fs::symlink_metadata]
///
/// # Errors
///
/// See [std::fs::symlink_metadata]
fn symlink_metadata<P: AsRef<Path>>(&self, path: P) -> io::Result<FileMetadata>;
/// ## Warning
/// Use `&Path` instead of a generic `P: AsRef<Path>` here,
/// because object safety requirements, it is especially useful, when
/// you want to store multiple `dyn FileSystem` in a `Vec` or use a `ResolverGeneric<Fs>` in
/// napi env.
fn symlink_metadata(&self, path: &Path) -> io::Result<FileMetadata>;
/// See [std::fs::canonicalize]
///
/// # Errors
///
/// See [std::fs::read_link]
fn canonicalize<P: AsRef<Path>>(&self, path: P) -> io::Result<PathBuf>;
/// ## Warning
/// Use `&Path` instead of a generic `P: AsRef<Path>` here,
/// because object safety requirements, it is especially useful, when
/// you want to store multiple `dyn FileSystem` in a `Vec` or use a `ResolverGeneric<Fs>` in
/// napi env.
fn canonicalize(&self, path: &Path) -> io::Result<PathBuf>;
}
/// Metadata information about a file.
@ -59,19 +78,19 @@ impl From<fs::Metadata> for FileMetadata {
pub struct FileSystemOs;
impl FileSystem for FileSystemOs {
fn read_to_string<P: AsRef<Path>>(&self, path: P) -> io::Result<String> {
fn read_to_string(&self, path: &Path) -> io::Result<String> {
fs::read_to_string(path)
}
fn metadata<P: AsRef<Path>>(&self, path: P) -> io::Result<FileMetadata> {
fn metadata(&self, path: &Path) -> io::Result<FileMetadata> {
fs::metadata(path).map(FileMetadata::from)
}
fn symlink_metadata<P: AsRef<Path>>(&self, path: P) -> io::Result<FileMetadata> {
fn symlink_metadata(&self, path: &Path) -> io::Result<FileMetadata> {
fs::symlink_metadata(path).map(FileMetadata::from)
}
fn canonicalize<P: AsRef<Path>>(&self, path: P) -> io::Result<PathBuf> {
fn canonicalize(&self, path: &Path) -> io::Result<PathBuf> {
dunce::canonicalize(path)
}
}

View file

@ -40,33 +40,33 @@ impl MemoryFS {
}
impl FileSystem for MemoryFS {
fn read_to_string<P: AsRef<Path>>(&self, path: P) -> io::Result<String> {
fn read_to_string(&self, path: &Path) -> io::Result<String> {
use vfs::FileSystem;
let mut file = self
.fs
.open_file(path.as_ref().to_string_lossy().as_ref())
.open_file(path.to_string_lossy().as_ref())
.map_err(|err| io::Error::new(io::ErrorKind::NotFound, err))?;
let mut buffer = String::new();
file.read_to_string(&mut buffer).unwrap();
Ok(buffer)
}
fn metadata<P: AsRef<Path>>(&self, path: P) -> io::Result<FileMetadata> {
fn metadata(&self, path: &Path) -> io::Result<FileMetadata> {
use vfs::FileSystem;
let metadata = self
.fs
.metadata(path.as_ref().to_string_lossy().as_ref())
.metadata(path.to_string_lossy().as_ref())
.map_err(|err| io::Error::new(io::ErrorKind::NotFound, err))?;
let is_file = metadata.file_type == vfs::VfsFileType::File;
let is_dir = metadata.file_type == vfs::VfsFileType::Directory;
Ok(FileMetadata::new(is_file, is_dir, false))
}
fn symlink_metadata<P: AsRef<Path>>(&self, path: P) -> io::Result<FileMetadata> {
fn symlink_metadata(&self, path: &Path) -> io::Result<FileMetadata> {
self.metadata(path)
}
fn canonicalize<P: AsRef<Path>>(&self, _path: P) -> io::Result<PathBuf> {
fn canonicalize(&self, _path: &Path) -> io::Result<PathBuf> {
Err(io::Error::new(io::ErrorKind::NotFound, "not a symlink"))
}
}