CompositeLoaderFileSystem.cs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. namespace Lua.IO;
  2. public class CompositeLoaderFileSystem(ILuaFileLoader[] loaders, ILuaFileSystem? system = null) : ILuaFileSystem
  3. {
  4. public static CompositeLoaderFileSystem Create(ILuaFileSystem system, params ILuaFileLoader[] loaders)
  5. {
  6. if (loaders == null || loaders.Length == 0)
  7. {
  8. throw new ArgumentException("Loaders cannot be null or empty", nameof(loaders));
  9. }
  10. return new(loaders, system);
  11. }
  12. public static CompositeLoaderFileSystem Create(params ILuaFileLoader[] loaders)
  13. {
  14. return new(loaders);
  15. }
  16. private (int index, string path)? cached;
  17. public bool IsReadable(string path)
  18. {
  19. for (int index = 0; index < loaders.Length; index++)
  20. {
  21. ILuaFileLoader? loader = loaders[index];
  22. if (loader.Exists(path))
  23. {
  24. cached = (index, path);
  25. return true;
  26. }
  27. }
  28. if (system != null)
  29. {
  30. cached = (loaders.Length, path);
  31. return system.IsReadable(path);
  32. }
  33. return false;
  34. }
  35. public async ValueTask<ILuaStream> Open(string path, LuaFileMode mode, CancellationToken cancellationToken)
  36. {
  37. if (cached != null)
  38. {
  39. var cachedValue = cached.Value;
  40. if (path == cachedValue.path)
  41. {
  42. if (cachedValue.index < loaders.Length)
  43. {
  44. if (mode.CanWrite())
  45. throw new NotSupportedException("Cannot write to a file opened with a loader.");
  46. return ILuaStream.CreateFromFileContent(await loaders[cachedValue.index].LoadAsync(path, cancellationToken));
  47. }
  48. }
  49. }
  50. else
  51. {
  52. foreach (var loader in loaders)
  53. {
  54. if (loader.Exists(path))
  55. {
  56. if (mode.CanWrite())
  57. throw new NotSupportedException("Cannot write to a file opened with a loader.");
  58. return ILuaStream.CreateFromFileContent(await loader.LoadAsync(path, cancellationToken));
  59. }
  60. }
  61. }
  62. return system != null ? await system.Open(path, mode, cancellationToken) : throw new NotSupportedException();
  63. }
  64. public ValueTask Rename(string oldName, string newName, CancellationToken cancellationToken)
  65. {
  66. return system?.Rename(oldName, newName, cancellationToken) ?? throw new NotSupportedException();
  67. }
  68. public ValueTask Remove(string path, CancellationToken cancellationToken)
  69. {
  70. return system?.Remove(path, cancellationToken) ?? throw new NotSupportedException();
  71. }
  72. public string DirectorySeparator => system?.DirectorySeparator ?? "/";
  73. public string GetTempFileName()
  74. {
  75. return system?.GetTempFileName() ?? throw new NotSupportedException();
  76. }
  77. public ValueTask<ILuaStream> OpenTempFileStream(CancellationToken cancellationToken)
  78. {
  79. return system?.OpenTempFileStream(cancellationToken) ?? throw new NotSupportedException();
  80. }
  81. }