using System.IO; using System.Collections.Generic; using System; using System.Linq; namespace pkNX.Containers.VFS; public enum DeleteMode { TopMostLayer, TopMostWriteableLayer, AllWritable, All } public interface IFileSystem : IDisposable { bool IsReadOnly => false; 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. /// /// The path to check. /// True if the path exists, false otherwise. bool Exists(FileSystemPath path); /// /// Opens a stream to the location of the specified file with the specified mode and access. /// /// The path and name of the file to open. /// A FileMode value that specifies whether a file is created if one does not exist, and determines whether the contents of existing files are retained or overwritten. /// The access mode to use when opening the file. /// A stream to the location of the opened file. Stream OpenFile(FileSystemPath path, FileMode mode = FileMode.Open, FileAccess access = FileAccess.Read); /// /// Creates or overwrites a file in the specified path /// /// The path and name of the file to create. /// A stream to the location of the new file. public Stream CreateFile(FileSystemPath path) => OpenFile(path, FileMode.Create, FileAccess.Write); /// /// Opens a stream to the location of the specified file using FileMode.OpenOrCreate and FileAccess.Write. /// /// The path and name of the file to open. /// A stream to the location of the opened file. public Stream OpenWrite(FileSystemPath path) => OpenFile(path, FileMode.OpenOrCreate, FileAccess.Write); /// /// Creates a directory in the specified path. /// /// The path and name of the directory to create. void CreateDirectory(FileSystemPath path); /// /// Deletes the specified file or directory. Does not throw an exception if the specified file or directory does not exist. /// /// The path and name of the file or directory to delete. /// The method to use when deleting the file or directory. void Delete(FileSystemPath path, DeleteMode mode = DeleteMode.TopMostLayer); public void Move(FileSystemPath sourcePath, IFileSystem destinationFileSystem, FileSystemPath destinationPath) { throw new NotImplementedException(); } public void Copy(FileSystemPath sourcePath, IFileSystem destinationFileSystem, FileSystemPath destinationPath) { throw new NotImplementedException(); } public IEnumerable GetEntitiesRecursive(FileSystemPath path, Func? filter = null) { if (!path.IsDirectory) throw new ArgumentException("The specified path is not a directory."); foreach (var entity in GetEntitiesInDirectory(path, filter)) { yield return entity; if (!entity.IsDirectory) continue; foreach (var subEntity in GetEntitiesRecursive(entity, filter)) yield return subEntity; } } public void CreateDirectoryRecursive(FileSystemPath path) { if (!path.IsDirectory) throw new ArgumentException("The specified path is not a directory."); var currentDirectoryPath = FileSystemPath.Root; foreach (var dirName in path.GetDirectorySegments()) { currentDirectoryPath = currentDirectoryPath.AppendDirectory(dirName); if (!Exists(currentDirectoryPath)) CreateDirectory(currentDirectoryPath); } } public string ReadAllText(FileSystemPath path) { if (!Exists(path)) return string.Empty; using var stream = OpenFile(path); using var reader = new StreamReader(stream); return reader.ReadToEnd(); } public void WriteAllText(FileSystemPath path, string content) { using var stream = OpenWrite(path); using var writer = new StreamWriter(stream); writer.Write(content); } } public static class IFileSystemExtensions { public static ReadOnlyFileSystem AsReadOnlyFileSystem(this IFileSystem self) => new(self); public static RelativeFileSystem AsRelativeFileSystem(this IFileSystem self, PathTransformation toAbsolutePath, PathTransformation toRelativePath) { return new(self, toAbsolutePath, toRelativePath); } public static IEnumerable GetEntities(this IFileSystem self, FileSystemPath path, Func? filter = null) { 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.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.GetFilesInDirectory(path, filter).Select(p => VirtualFile.Create(self, p)).OrderBy(x => x.Path); } }