using System.Collections.Concurrent; using System.Diagnostics.Metrics; using System.Globalization; using VsRemote.Base; using VsRemote.Exceptions; using VsRemote.Interfaces; using VsRemote.Model; using VsRemote.Enums; using System.Text; using System.Xml.Linq; namespace VsRemote.Sample; public class InMemoryIndexedDictionaryFilesystem : VsRemoteFileSystem { private static readonly IVsRemoteINode _root = new VsRemoteRootINode( Key: 1, CTime: DateTimeOffset.UtcNow.ToUnixTimeSeconds(), MTime: DateTimeOffset.UtcNow.ToUnixTimeSeconds() ); private readonly ConcurrentDictionary> fs = new(new[] { new KeyValuePair>(0, _root) }); private readonly Dictionary> contents = new(); private long _nextId = 2; private long nextId => Interlocked.Increment(ref _nextId); public override IVsRemoteINode RootINode => _root; public InMemoryIndexedDictionaryFilesystem() { var sampleContent = Encoding.ASCII.GetBytes("Sample file"); CreateFile("sample.txt", _root, new ReadOnlyMemory(sampleContent)); } public override Task CreateDirectory(string directoryName, IVsRemoteINode parentDir) { IVsRemoteINode newDir = new VsRemoteINode( Key: nextId, Parent: parentDir.Key, Name: directoryName, FileType: VsRemoteFileType.Directory, CTime: DateTimeOffset.UtcNow.ToUnixTimeSeconds(), MTime: DateTimeOffset.UtcNow.ToUnixTimeSeconds(), ATime: DateTimeOffset.UtcNow.ToUnixTimeSeconds(), Readonly: false ); fs.AddOrUpdate(newDir.Key, newDir, (k, f) => throw new FileExists()); return Task.CompletedTask; } public override Task CreateFile(string file2write, IVsRemoteINode parentDir, ReadOnlyMemory content) { IVsRemoteINode newFile = new VsRemoteINode( Key: nextId, Parent: parentDir.Key, Name: file2write, FileType: VsRemoteFileType.File, CTime: DateTimeOffset.UtcNow.ToUnixTimeSeconds(), MTime: DateTimeOffset.UtcNow.ToUnixTimeSeconds(), ATime: DateTimeOffset.UtcNow.ToUnixTimeSeconds(), Readonly: false, Size: content.Length ); fs.AddOrUpdate(newFile.Key, newFile, (k, f) => throw new FileExists()); contents.Add(newFile.Key, content); return Task.FromResult(content.Length); } public override Task DeleteFile(IVsRemoteINode fileToDelete) { fs.Remove(fileToDelete.Key, out _); contents.Remove(fileToDelete.Key); return Task.CompletedTask; } public override Task> FindByName(string file, IVsRemoteINode parentDir) { var fenum = fs.Values.Where(f => f.Parent == parentDir.Key && f.Name == file); if (fenum.Any()) return Task.FromResult(fenum.First()); else throw new NotFound(); } public override Task>> ListDirectory(IVsRemoteINode dir) { return Task.FromResult(fs.Values.Where(f => f.Parent == dir.Key)); } public override Task> RenameFile(IVsRemoteINode file2rename, string toName) { if (file2rename.Name != toName) { var newFromFile = (file2rename as VsRemoteINode)! with { Name = toName }; if (!fs.TryUpdate(file2rename.Key, newFromFile, file2rename)) { throw new NotFound(); } return Task.FromResult((IVsRemoteINode)newFromFile); } else return Task.FromResult(file2rename); } public override Task> MoveFile(IVsRemoteINode fromFile, IVsRemoteINode toPath) { var newFromFile = (fromFile as VsRemoteINode)! with { Parent = toPath.Key }; if (!fs.TryUpdate(fromFile.Key, newFromFile, fromFile)) { throw new NotFound(); } return Task.FromResult((IVsRemoteINode)newFromFile); } public override Task> ReadFile(IVsRemoteINode fileToRead) { if (contents.TryGetValue(fileToRead.Key, out var content)) { return Task.FromResult(content); } else { throw new NotFound(); } } public override Task RemoveDirectory(IVsRemoteINode dir, bool recursive) { Subs(dir.Key); fs.Remove(dir.Key, out _); return Task.CompletedTask; void Subs(long dir) { foreach (var f in fs.Where(f => f.Value.Parent == dir)) { if (f.Value.IsDirectory()) Subs(f.Value.Key); fs.Remove(f.Value.Key, out _); } } } public override Task RewriteFile(IVsRemoteINode file2rewrite, ReadOnlyMemory content) { contents[file2rewrite.Key] = content; fs[file2rewrite.Key] = (fs[file2rewrite.Key] as VsRemoteINode)!with { Size = content.Length }; return Task.FromResult(content.Length); } }