using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.CompilerServices; using System.Text; namespace pkNX.Containers.VFS; public class LayeredFileSystem : IFileSystem { public IEnumerable FileSystems { get; } public LayeredFileSystem(IEnumerable fileSystems) { FileSystems = fileSystems; } public LayeredFileSystem(params IFileSystem[] fileSystems) : this(fileSystems.AsEnumerable()) { } public void Dispose() { foreach (var fs in FileSystems) fs.Dispose(); GC.SuppressFinalize(this); } public IEnumerable GetEntityPaths(FileSystemPath path) { var entities = new HashSet(); foreach (var fs in FileSystems.Where(fs => fs.Exists(path))) entities.UnionWith(fs.GetEntityPaths(path)); return entities; } public IEnumerable GetDirectoryPaths(FileSystemPath path) { var directories = new HashSet(); foreach (var fs in FileSystems.Where(fs => fs.Exists(path))) directories.UnionWith(fs.GetDirectoryPaths(path)); return directories; } public IEnumerable GetFilePaths(FileSystemPath path) { var files = new HashSet(); foreach (var fs in FileSystems.Where(fs => fs.Exists(path))) files.UnionWith(fs.GetFilePaths(path)); return files; } public bool Exists(FileSystemPath path) { return FileSystems.Any(fs => fs.Exists(path)); } public IFileSystem? GetFirst(FileSystemPath path) { return FileSystems.FirstOrDefault(fs => fs.Exists(path)); } public Stream CreateFile(FileSystemPath path) { IFileSystem fs = GetFirst(path) ?? FileSystems.First(); return fs.CreateFile(path); } public Stream OpenFile(FileSystemPath path, FileAccess access) { IFileSystem? fs = GetFirst(path); if (fs == null) throw new FileNotFoundException($"Unable to find {path.Path}"); return fs.OpenFile(path, access); } public void CreateDirectory(FileSystemPath path) { if (Exists(path)) throw new ArgumentException("The specified directory already exists."); IFileSystem? fs = GetFirst(path.ParentPath); if (fs == null) throw new ArgumentException("The directory-parent does not exist."); fs.CreateDirectory(path); } public void Delete(FileSystemPath path) { foreach (var fs in FileSystems.Where(fs => fs.Exists(path))) fs.Delete(path); } }