6public sealed class NdsFileSystem
9 private readonly Dictionary<string, NdsFile> _filesByPath;
11 private readonly Dictionary<int, NdsFile> _filesById;
13 private readonly Dictionary<string, NdsDirectory> _directoriesByPath;
20 internal NdsFileSystem(
22 IReadOnlyList<NdsDirectory> directories,
23 IReadOnlyList<NdsFile> files,
24 IReadOnlyList<NdsFileAllocation> allocations)
30 _filesByPath = files.ToDictionary(
static file => file.FullPath, StringComparer.Ordinal);
31 _filesById = files.ToDictionary(
static file => file.Id);
32 _directoriesByPath = directories.ToDictionary(
static directory => directory.FullPath, StringComparer.Ordinal);
42 public IReadOnlyList<NdsFile>
Files {
get; }
52 string normalized = NormalizePath(path);
53 return _filesByPath.TryGetValue(normalized, out
NdsFile? file)
55 :
throw new FileNotFoundException($
"NitroFS file '{normalized}' was not found.", normalized);
63 _filesByPath.TryGetValue(NormalizePath(path), out file);
70 string normalized = NormalizeDirectoryPath(path);
71 return _directoriesByPath.TryGetValue(normalized, out
NdsDirectory? directory)
73 :
throw new DirectoryNotFoundException($
"NitroFS directory '{normalized}' was not found.");
81 _directoriesByPath.TryGetValue(NormalizeDirectoryPath(path), out directory);
88 :
throw new KeyNotFoundException($
"No named NitroFS file has ID {fileId}.");
95 _filesById.TryGetValue(fileId, out file);
100 private static string NormalizePath(
string path)
102 ArgumentException.ThrowIfNullOrWhiteSpace(path);
103 string normalized = path.Replace(
'\\',
'/');
104 if (!normalized.StartsWith(
'/'))
106 normalized =
"/" + normalized;
109 if (normalized.EndsWith(
'/') ||
110 normalized.Contains(
"//", StringComparison.Ordinal))
112 throw new ArgumentException(
"NitroFS paths must identify a file and contain no empty segments.", nameof(path));
115 foreach (
string segment
in normalized.Split(
'/', StringSplitOptions.RemoveEmptyEntries))
117 if (segment is
"." or
"..")
119 throw new ArgumentException(
"NitroFS paths cannot contain traversal segments.", nameof(path));
129 private static string NormalizeDirectoryPath(
string path)
131 ArgumentException.ThrowIfNullOrWhiteSpace(path);
132 string normalized = path.Replace(
'\\',
'/');
133 if (!normalized.StartsWith(
'/'))
135 normalized =
"/" + normalized;
138 if (normalized.Length > 1 && normalized.EndsWith(
'/'))
140 normalized = normalized.TrimEnd(
'/');
143 if (normalized.Contains(
"//", StringComparison.Ordinal) ||
144 normalized.Split(
'/', StringSplitOptions.RemoveEmptyEntries).Any(
static segment => segment is
"." or
".."))
146 throw new ArgumentException(
"NitroFS directory paths cannot contain empty or traversal segments.", nameof(path));