From d5d6057d4c7874ed59cddb3ba83d8fe7bd0f7a23 Mon Sep 17 00:00:00 2001 From: duckdoom4 <60387522+duckdoom4@users.noreply.github.com> Date: Sun, 10 Sep 2023 12:54:19 +0200 Subject: [PATCH] Improve VFS API Rename to match actual behaviour and add throw if invalid --- .../Archives/ZipArchiveFileSystem.cs | 32 ++++----- .../VFS/FileSystems/IFileSystem.cs | 14 ++-- .../VFS/FileSystems/LayeredFileSystem.cs | 65 +++++++++++-------- .../VFS/FileSystems/PhysicalFileSystem.cs | 20 +++--- .../VFS/FileSystems/ReadOnlyFileSystem.cs | 12 ++-- .../VFS/FileSystems/RelativeFileSystem.cs | 12 ++-- pkNX.Containers/VFS/Util/VirtualDirectory.cs | 2 +- pkNX.Containers/VFS/VirtualFileSystem.cs | 18 ++--- .../VFS/FileSystems/ZipArchiveFSTest.cs | 4 +- 9 files changed, 94 insertions(+), 85 deletions(-) diff --git a/pkNX.Containers/VFS/FileSystems/Archives/ZipArchiveFileSystem.cs b/pkNX.Containers/VFS/FileSystems/Archives/ZipArchiveFileSystem.cs index a47ba688..ac3ab43e 100644 --- a/pkNX.Containers/VFS/FileSystems/Archives/ZipArchiveFileSystem.cs +++ b/pkNX.Containers/VFS/FileSystems/Archives/ZipArchiveFileSystem.cs @@ -50,52 +50,52 @@ protected string ToEntryPath(FileSystemPath path) return ZipArchive.GetEntry(ToEntryPath(path)); } - public IEnumerable GetEntityPaths(FileSystemPath path, Func? filter = null) + public IEnumerable GetEntitiesInDirectory(FileSystemPath directory, Func? filter = null) { - var entries = GetZipEntries().Select(ToPath).Where(path.IsParentOf); + var entries = GetZipEntries().Select(ToPath).Where(directory.IsParentOf); if (filter != null) entries = entries.Where(filter); - return entries.Select(entryPath => entryPath.ParentPath == path + return entries.Select(entryPath => entryPath.ParentPath == directory ? entryPath - : path.AppendDirectory(entryPath.MakeRelativeTo(path).GetDirectorySegments().First())) + : directory.AppendDirectory(entryPath.MakeRelativeTo(directory).GetDirectorySegments().First())) .Distinct(); } - public IEnumerable GetDirectoryPaths(FileSystemPath path, Func? filter = null) + public IEnumerable GetDirectoriesInDirectory(FileSystemPath directory, Func? filter = null) { - if (!path.IsDirectory) - throw new ArgumentException("This FileSystemPath is not a directory.", nameof(path)); + if (!directory.IsDirectory) + throw new ArgumentException("This FileSystemPath is not a directory.", nameof(directory)); var entries = GetZipEntries() .Select(ToPath) - .Where(p => path.IsParentOf(p) && p.IsDirectory); + .Where(p => directory.IsParentOf(p) && p.IsDirectory); if (filter != null) entries = entries.Where(filter); return entries.Select(entryPath => - entryPath.ParentPath == path ? entryPath : - path.AppendDirectory(entryPath.MakeRelativeTo(path).GetDirectorySegments().First())) + entryPath.ParentPath == directory ? entryPath : + directory.AppendDirectory(entryPath.MakeRelativeTo(directory).GetDirectorySegments().First())) .Distinct(); } - public IEnumerable GetFilePaths(FileSystemPath path, Func? filter = null) + public IEnumerable GetFilesInDirectory(FileSystemPath directory, Func? filter = null) { - if (!path.IsDirectory) - throw new ArgumentException("The specified path is not a directory.", nameof(path)); + if (!directory.IsDirectory) + throw new ArgumentException("The specified path is not a directory.", nameof(directory)); var entries = GetZipEntries() .Select(ToPath) - .Where(p => path.IsParentOf(p) && p.IsFile); + .Where(p => directory.IsParentOf(p) && p.IsFile); if (filter != null) entries = entries.Where(filter); - return entries.Select(entryPath => entryPath.ParentPath == path + return entries.Select(entryPath => entryPath.ParentPath == directory ? entryPath - : path.AppendDirectory(entryPath.MakeRelativeTo(path).GetDirectorySegments().First())) + : directory.AppendDirectory(entryPath.MakeRelativeTo(directory).GetDirectorySegments().First())) .Distinct(); } diff --git a/pkNX.Containers/VFS/FileSystems/IFileSystem.cs b/pkNX.Containers/VFS/FileSystems/IFileSystem.cs index 9d8a98e7..71a74a96 100644 --- a/pkNX.Containers/VFS/FileSystems/IFileSystem.cs +++ b/pkNX.Containers/VFS/FileSystems/IFileSystem.cs @@ -17,9 +17,9 @@ public interface IFileSystem : IDisposable { bool IsReadOnly => false; - IEnumerable GetEntityPaths(FileSystemPath path, Func? filter = null); - IEnumerable GetDirectoryPaths(FileSystemPath path, Func? filter = null); - IEnumerable GetFilePaths(FileSystemPath path, Func? filter = null); + IEnumerable GetEntitiesInDirectory(FileSystemPath directory, Func? filter = null); + IEnumerable GetDirectoriesInDirectory(FileSystemPath directory, Func? filter = null); + IEnumerable GetFilesInDirectory(FileSystemPath directory, Func? filter = null); /// /// Checks if the specified path exists in the filesystem. @@ -79,7 +79,7 @@ public IEnumerable GetEntitiesRecursive(FileSystemPath path, Fun if (!path.IsDirectory) throw new ArgumentException("The specified path is not a directory."); - foreach (var entity in GetEntityPaths(path, filter)) + foreach (var entity in GetEntitiesInDirectory(path, filter)) { yield return entity; @@ -135,16 +135,16 @@ public static RelativeFileSystem AsRelativeFileSystem(this IFileSystem self, Pat public static IEnumerable GetEntities(this IFileSystem self, FileSystemPath path, Func? filter = null) { - return self.GetEntityPaths(path, filter).Select(p => IFileSystemEntity.Create(self, p)).OrderBy(x => x.Path); + return self.GetEntitiesInDirectory(path, filter).Select(p => IFileSystemEntity.Create(self, p)).OrderBy(x => x.Path); } public static IEnumerable GetDirectories(this IFileSystem self, FileSystemPath path, Func? filter = null) { - return self.GetDirectoryPaths(path, filter).Select(p => VirtualDirectory.Create(self, p)).OrderBy(x => x.Path); + return self.GetDirectoriesInDirectory(path, filter).Select(p => VirtualDirectory.Create(self, p)).OrderBy(x => x.Path); } public static IEnumerable GetFiles(this IFileSystem self, FileSystemPath path, Func? filter = null) { - return self.GetFilePaths(path, filter).Select(p => VirtualFile.Create(self, p)).OrderBy(x => x.Path); + return self.GetFilesInDirectory(path, filter).Select(p => VirtualFile.Create(self, p)).OrderBy(x => x.Path); } } diff --git a/pkNX.Containers/VFS/FileSystems/LayeredFileSystem.cs b/pkNX.Containers/VFS/FileSystems/LayeredFileSystem.cs index 139d58b3..917a2da7 100644 --- a/pkNX.Containers/VFS/FileSystems/LayeredFileSystem.cs +++ b/pkNX.Containers/VFS/FileSystems/LayeredFileSystem.cs @@ -10,75 +10,84 @@ namespace pkNX.Containers.VFS; public class LayeredFileSystem : IFileSystem { - public IReadOnlyList FileSystems { get; } + private readonly IFileSystem[] _fileSystems; - public LayeredFileSystem(IReadOnlyList fileSystems) - { - FileSystems = fileSystems; - - Debug.Assert(FileSystems.Any(), "No filesystems provided."); - Debug.Assert(FileSystems.Any(fs => !fs.IsReadOnly), "Should contain at least one writable filesystem."); - } - - public LayeredFileSystem(params IFileSystem[] fileSystems) : - this(fileSystems.AsReadOnly()) + public LayeredFileSystem(IEnumerable fileSystems) : + this(fileSystems.ToArray()) { } + public LayeredFileSystem(params IFileSystem[] fileSystems) + { + _fileSystems = fileSystems; + + Debug.Assert(_fileSystems.Any(), "At least one file system should be provided."); + Debug.Assert(_fileSystems.Any(fs => !fs.IsReadOnly), "Should contain at least one writable filesystem."); + } + public void Dispose() { - foreach (var fs in FileSystems) + foreach (var fs in _fileSystems) fs.Dispose(); GC.SuppressFinalize(this); } - public IEnumerable GetEntityPaths(FileSystemPath path, Func? filter = null) + public IEnumerable GetEntitiesInDirectory(FileSystemPath directory, Func? filter = null) { + if (!directory.IsDirectory) + throw new ArgumentException("This FileSystemPath is not a directory.", nameof(directory)); + var entities = new HashSet(); - foreach (var fs in FileSystems.Where(fs => fs.Exists(path))) - entities.UnionWith(fs.GetEntityPaths(path, filter)); + foreach (var fs in _fileSystems.Where(fs => fs.Exists(directory))) + entities.UnionWith(fs.GetEntitiesInDirectory(directory, filter)); return entities; } - public IEnumerable GetDirectoryPaths(FileSystemPath path, Func? filter = null) + public IEnumerable GetDirectoriesInDirectory(FileSystemPath directory, Func? filter = null) { + if (!directory.IsDirectory) + throw new ArgumentException("This FileSystemPath is not a directory.", nameof(directory)); + var directories = new HashSet(); - foreach (var fs in FileSystems.Where(fs => fs.Exists(path))) - directories.UnionWith(fs.GetDirectoryPaths(path, filter)); + foreach (var fs in _fileSystems.Where(fs => fs.Exists(directory))) + directories.UnionWith(fs.GetDirectoriesInDirectory(directory, filter)); return directories; } - public IEnumerable GetFilePaths(FileSystemPath path, Func? filter = null) + public IEnumerable GetFilesInDirectory(FileSystemPath directory, Func? filter = null) { + if (!directory.IsDirectory) + throw new ArgumentException("This FileSystemPath is not a directory.", nameof(directory)); + var files = new HashSet(); - foreach (var fs in FileSystems.Where(fs => fs.Exists(path))) - files.UnionWith(fs.GetFilePaths(path, filter)); + foreach (var fs in _fileSystems.Where(fs => fs.Exists(directory))) + files.UnionWith(fs.GetFilesInDirectory(directory, filter)); return files; } public IFileSystem GetFirst() { - return FileSystems.First(); + return _fileSystems[0]; } public IFileSystem GetFirstWritable() { - return FileSystems.First(fs => !fs.IsReadOnly); + return _fileSystems.First(fs => !fs.IsReadOnly); } public bool Exists(FileSystemPath path) { - return FileSystems.Any(fs => fs.Exists(path)); + return _fileSystems.Any(fs => fs.Exists(path)); } public IFileSystem? GetFirstWhereExists(FileSystemPath path) { - return FileSystems.FirstOrDefault(fs => fs.Exists(path)); + return _fileSystems.FirstOrDefault(fs => fs.Exists(path)); } public IFileSystem? GetFirstWritableWhereExists(FileSystemPath path) { - return FileSystems.FirstOrDefault(fs => !fs.IsReadOnly && fs.Exists(path)); + return _fileSystems.FirstOrDefault(fs => !fs.IsReadOnly && fs.Exists(path)); } private bool ValidateOpenMode(FileMode mode = FileMode.Open, FileAccess access = FileAccess.Read) @@ -223,11 +232,11 @@ public void Delete(FileSystemPath path, DeleteMode mode = DeleteMode.TopMostLaye GetFirstWritableWhereExists(path)?.Delete(path); break; case DeleteMode.AllWritable: - foreach (var fs in FileSystems.Where(fs => !fs.IsReadOnly && fs.Exists(path))) + foreach (var fs in _fileSystems.Where(fs => !fs.IsReadOnly && fs.Exists(path))) fs.Delete(path); break; case DeleteMode.All: - foreach (var fs in FileSystems.Where(fs => fs.Exists(path))) + foreach (var fs in _fileSystems.Where(fs => fs.Exists(path))) fs.Delete(path); break; default: diff --git a/pkNX.Containers/VFS/FileSystems/PhysicalFileSystem.cs b/pkNX.Containers/VFS/FileSystems/PhysicalFileSystem.cs index 112ac6b8..de8da14c 100644 --- a/pkNX.Containers/VFS/FileSystems/PhysicalFileSystem.cs +++ b/pkNX.Containers/VFS/FileSystems/PhysicalFileSystem.cs @@ -42,17 +42,17 @@ public FileSystemPath GetVirtualDirectoryPath(string physicalPath) return FileSystemPath.Parse(virtualPath); } - public IEnumerable GetEntityPaths(FileSystemPath path, Func? filter = null) + public IEnumerable GetEntitiesInDirectory(FileSystemPath directory, Func? filter = null) { - return GetDirectoryPaths(path, filter).Concat(GetFilePaths(path, filter)); + return GetDirectoriesInDirectory(directory, filter).Concat(GetFilesInDirectory(directory, filter)); } - public IEnumerable GetDirectoryPaths(FileSystemPath path, Func? filter = null) + public IEnumerable GetDirectoriesInDirectory(FileSystemPath directory, Func? filter = null) { - if (!path.IsDirectory) - throw new ArgumentException("This FileSystemPath is not a directory.", nameof(path)); + if (!directory.IsDirectory) + throw new ArgumentException("This FileSystemPath is not a directory.", nameof(directory)); - var physicalPaths = Directory.GetDirectories(GetPhysicalPath(path)); + var physicalPaths = Directory.GetDirectories(GetPhysicalPath(directory)); var virtualPaths = physicalPaths.Select(GetVirtualDirectoryPath); if (filter == null) @@ -61,12 +61,12 @@ public IEnumerable GetDirectoryPaths(FileSystemPath path, Func GetFilePaths(FileSystemPath path, Func? filter = null) + public IEnumerable GetFilesInDirectory(FileSystemPath directory, Func? filter = null) { - if (!path.IsDirectory) - throw new ArgumentException("The specified path is not a directory.", nameof(path)); + if (!directory.IsDirectory) + throw new ArgumentException("The specified path is not a directory.", nameof(directory)); - var physicalPaths = Directory.GetFiles(GetPhysicalPath(path)); + var physicalPaths = Directory.GetFiles(GetPhysicalPath(directory)); var virtualPaths = physicalPaths.Select(GetVirtualFilePath); if (filter == null) diff --git a/pkNX.Containers/VFS/FileSystems/ReadOnlyFileSystem.cs b/pkNX.Containers/VFS/FileSystems/ReadOnlyFileSystem.cs index d3328aa7..1648eee1 100644 --- a/pkNX.Containers/VFS/FileSystems/ReadOnlyFileSystem.cs +++ b/pkNX.Containers/VFS/FileSystems/ReadOnlyFileSystem.cs @@ -23,21 +23,21 @@ public void Dispose() } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IEnumerable GetEntityPaths(FileSystemPath path, Func? filter = null) + public IEnumerable GetEntitiesInDirectory(FileSystemPath directory, Func? filter = null) { - return FileSystem.GetEntityPaths(path, filter); + return FileSystem.GetEntitiesInDirectory(directory, filter); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IEnumerable GetDirectoryPaths(FileSystemPath path, Func? filter = null) + public IEnumerable GetDirectoriesInDirectory(FileSystemPath directory, Func? filter = null) { - return FileSystem.GetDirectoryPaths(path, filter); + return FileSystem.GetDirectoriesInDirectory(directory, filter); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IEnumerable GetFilePaths(FileSystemPath path, Func? filter = null) + public IEnumerable GetFilesInDirectory(FileSystemPath directory, Func? filter = null) { - return FileSystem.GetFilePaths(path, filter); + return FileSystem.GetFilesInDirectory(directory, filter); } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/pkNX.Containers/VFS/FileSystems/RelativeFileSystem.cs b/pkNX.Containers/VFS/FileSystems/RelativeFileSystem.cs index 34d585a6..65db43a6 100644 --- a/pkNX.Containers/VFS/FileSystems/RelativeFileSystem.cs +++ b/pkNX.Containers/VFS/FileSystems/RelativeFileSystem.cs @@ -31,23 +31,23 @@ public void Dispose() } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IEnumerable GetEntityPaths(FileSystemPath path, Func? filter = null) + public IEnumerable GetEntitiesInDirectory(FileSystemPath directory, Func? filter = null) { - return FileSystem.GetEntityPaths(ToAbsolutePath(path), filter) + return FileSystem.GetEntitiesInDirectory(ToAbsolutePath(directory), filter) .Select(p => ToRelativePath(p)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IEnumerable GetDirectoryPaths(FileSystemPath path, Func? filter = null) + public IEnumerable GetDirectoriesInDirectory(FileSystemPath directory, Func? filter = null) { - return FileSystem.GetDirectoryPaths(ToAbsolutePath(path), filter) + return FileSystem.GetDirectoriesInDirectory(ToAbsolutePath(directory), filter) .Select(p => ToRelativePath(p)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IEnumerable GetFilePaths(FileSystemPath path, Func? filter = null) + public IEnumerable GetFilesInDirectory(FileSystemPath directory, Func? filter = null) { - return FileSystem.GetFilePaths(ToAbsolutePath(path), filter) + return FileSystem.GetFilesInDirectory(ToAbsolutePath(directory), filter) .Select(p => ToRelativePath(p)); } diff --git a/pkNX.Containers/VFS/Util/VirtualDirectory.cs b/pkNX.Containers/VFS/Util/VirtualDirectory.cs index 2f95679f..2b31bdd5 100644 --- a/pkNX.Containers/VFS/Util/VirtualDirectory.cs +++ b/pkNX.Containers/VFS/Util/VirtualDirectory.cs @@ -33,6 +33,6 @@ internal static VirtualDirectory Create(IFileSystem fileSystem, FileSystemPath p public IEnumerable GetEntityPaths(Func? filter = null) { - return FileSystem.GetEntityPaths(Path, filter); + return FileSystem.GetEntitiesInDirectory(Path, filter); } } diff --git a/pkNX.Containers/VFS/VirtualFileSystem.cs b/pkNX.Containers/VFS/VirtualFileSystem.cs index 4c8b8e35..a737c35e 100644 --- a/pkNX.Containers/VFS/VirtualFileSystem.cs +++ b/pkNX.Containers/VFS/VirtualFileSystem.cs @@ -59,24 +59,24 @@ protected MountPoint GetMountPoint(FileSystemPath path) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IEnumerable GetEntityPaths(FileSystemPath path, Func? filter = null) + public IEnumerable GetEntitiesInDirectory(FileSystemPath directory, Func? filter = null) { - var mount = GetMountPoint(path); - return mount.FileSystem.GetEntityPaths(path, filter); + var mount = GetMountPoint(directory); + return mount.FileSystem.GetEntitiesInDirectory(directory, filter); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IEnumerable GetDirectoryPaths(FileSystemPath path, Func? filter = null) + public IEnumerable GetDirectoriesInDirectory(FileSystemPath directory, Func? filter = null) { - var mount = GetMountPoint(path); - return mount.FileSystem.GetDirectoryPaths(path, filter); + var mount = GetMountPoint(directory); + return mount.FileSystem.GetDirectoriesInDirectory(directory, filter); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IEnumerable GetFilePaths(FileSystemPath path, Func? filter = null) + public IEnumerable GetFilesInDirectory(FileSystemPath directory, Func? filter = null) { - var mount = GetMountPoint(path); - return mount.FileSystem.GetFilePaths(path, filter); + var mount = GetMountPoint(directory); + return mount.FileSystem.GetFilesInDirectory(directory, filter); } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/pkNX.Tests/VFS/FileSystems/ZipArchiveFSTest.cs b/pkNX.Tests/VFS/FileSystems/ZipArchiveFSTest.cs index a1d06b22..313e0604 100644 --- a/pkNX.Tests/VFS/FileSystems/ZipArchiveFSTest.cs +++ b/pkNX.Tests/VFS/FileSystems/ZipArchiveFSTest.cs @@ -55,7 +55,7 @@ public void GetEntitiesOfRootTest() textfileAPath, directoryPath, scratchDirectoryPath - }, fileSystem.GetEntityPaths(FileSystemPath.Root).ToArray()); + }, fileSystem.GetEntitiesInDirectory(FileSystemPath.Root).ToArray()); } [Fact] @@ -64,7 +64,7 @@ public void GetEntitiesOfDirectoryTest() Assert.Equal(new[] { fileInDirectoryPath - }, fileSystem.GetEntityPaths(directoryPath).ToArray()); + }, fileSystem.GetEntitiesInDirectory(directoryPath).ToArray()); } [Fact]