src/Bicep.IO/InMemory/InMemoryFileHandle.cs (67 lines of code) (raw):

// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Bicep.IO.Abstraction; namespace Bicep.IO.InMemory { public class InMemoryFileHandle : InMemoryIOHandle, IFileHandle { public InMemoryFileHandle(InMemoryFileExplorer.FileStore store, IOUri uri) : base(store, EnsureNoTrailingSlash(uri)) { } public void Delete() => this.FileStore.DeleteFile(this); public IFileHandle EnsureExists() { this.FileStore.CreateFileIfNotExists(this); return this; } public override bool Exists() => this.FileStore.FileExists(this); public IDirectoryHandle GetParent() { var parentUri = this.Uri.Resolve("."); return new InMemoryDirectoryHandle(this.FileStore, parentUri); } public void MakeExecutable() => throw new NotSupportedException(); public Stream OpenRead() { var text = this.FileStore.ReadFile(this); return new MemoryStream(Encoding.UTF8.GetBytes(text)); } public Stream OpenWrite() => new InMemoryFileStream(text => this.FileStore.WriteFile(this, text)); public IFileLock? TryLock() => DummyFileLock.Instance; private static IOUri EnsureNoTrailingSlash(IOUri uri) { if (uri.Path.EndsWith('/')) { throw new ArgumentException("File path must not end with a slash.", nameof(uri)); } return uri; } private class InMemoryFileStream : MemoryStream { private readonly Action<string> onDisposing; public InMemoryFileStream(Action<string> onDisposing) { this.onDisposing = onDisposing; } protected override void Dispose(bool disposing) { if (disposing) { this.onDisposing(Encoding.UTF8.GetString(this.ToArray())); } base.Dispose(disposing); } } private class DummyFileLock : IFileLock { public static readonly DummyFileLock Instance = new(); public void Dispose() { } } } }