Skip to content

Commit

Permalink
Improve representation of file contents
Browse files Browse the repository at this point in the history
To improve readability and runtime-efficiency, switch the type to represent file contents from IReadOnlyList<byte> to ReadOnlyMemory<byte>
  • Loading branch information
Viir committed Aug 11, 2023
1 parent 4548870 commit e4e4a75
Show file tree
Hide file tree
Showing 13 changed files with 96 additions and 87 deletions.
2 changes: 1 addition & 1 deletion implement/elm-time/Elm019/Elm019Binaries.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public static Result<string, ElmMakeOk> ElmMake(
if (cacheEntryFile is not null)
{
var resultFromCache =
System.Text.Json.JsonSerializer.Deserialize<Result<string, ElmMakeOkJsonStructure>>(cacheEntryFile!.ToArray())
System.Text.Json.JsonSerializer.Deserialize<Result<string, ElmMakeOkJsonStructure>>(cacheEntryFile.Value.Span)
?.Map(AsElmMakeOk);

if (resultFromCache is Result<string, ElmMakeOk>.Ok resultOk)
Expand Down
13 changes: 7 additions & 6 deletions implement/elm-time/ElmTime/ProcessStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public IEnumerable<byte[]> EnumerateSerializedCompositionsRecordsReverse() =>
var fileContent = compositionFileStoreReader.GetFileContent(compositionFilePath)!;
return
Encoding.UTF8.GetString(fileContent as byte[] ?? fileContent.ToArray())
Encoding.UTF8.GetString(fileContent.Value.Span)
.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).Reverse()
.Select(compositionRecord => Encoding.UTF8.GetBytes(compositionRecord));
});
Expand All @@ -124,7 +124,7 @@ public IEnumerable<byte[]> EnumerateSerializedCompositionsRecordsReverse() =>

var fileContent = reductionFileStoreReader.GetFileContent(filePath);

if (fileContent == null)
if (fileContent is null)
return null;

try
Expand All @@ -135,15 +135,14 @@ public IEnumerable<byte[]> EnumerateSerializedCompositionsRecordsReverse() =>
https://github.com/elm-time/elm-time/blob/1cd3f00bdf5a05e9bda479c534b0458b2496393c/implement/PersistentProcess/PersistentProcess.Common/ProcessStore.cs#L183
Looking at the files from stores in production, it seems like that caused addition of BOM.
*/
fileContent.Take(3).SequenceEqual(new byte[] { 0xEF, 0xBB, 0xBF })
fileContent.Value.Span.StartsWith(new byte[] { 0xEF, 0xBB, 0xBF })
?
3
:
0;

var reductionRecordFromFile =
JsonSerializer.Deserialize<ReductionRecordInFile>(
Encoding.UTF8.GetString((fileContent as byte[] ?? fileContent.ToArray()).AsSpan(payloadStartIndex)))!;
JsonSerializer.Deserialize<ReductionRecordInFile>(fileContent.Value[payloadStartIndex..].Span)!;

if (reducedCompositionHashBase16 != reductionRecordFromFile.ReducedCompositionHashBase16)
throw new Exception("Unexpected content in file " + string.Join("/", filePath) + ", composition hash does not match.");
Expand All @@ -156,7 +155,9 @@ public IEnumerable<byte[]> EnumerateSerializedCompositionsRecordsReverse() =>
}
catch (Exception e)
{
throw new Exception("Failed to read reduction from file '" + string.Join("/", filePath) + "'.", e);
throw new Exception(
"Failed to read reduction from file '" + string.Join("/", filePath) + "' (" + fileContent.Value.Length + " bytes)",
e);
}
}

Expand Down
3 changes: 1 addition & 2 deletions implement/elm-time/Pine/CacheByFileName.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Collections.Immutable;
using System.Linq;

namespace Pine;

Expand All @@ -16,7 +15,7 @@ public ReadOnlyMemory<byte> GetOrUpdate(string fileName, Func<ReadOnlyMemory<byt
var fromCache = FileStore.GetFileContent(entryPath);

if (fromCache is not null)
return new ReadOnlyMemory<byte>(fromCache.ToArray());
return fromCache;

var file = tryBuild();

Expand Down
4 changes: 2 additions & 2 deletions implement/elm-time/Pine/CommonConversion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,12 @@ public static ReadOnlyMemory<byte> Deflate(ReadOnlyMemory<byte> input)
return deflatedStream.ToArray();
}

public static ReadOnlyMemory<byte> Inflate(IReadOnlyList<byte> input)
public static ReadOnlyMemory<byte> Inflate(ReadOnlyMemory<byte> input)
{
using var inflatedStream = new System.IO.MemoryStream();

using var deflateStream = new System.IO.Compression.DeflateStream(
new System.IO.MemoryStream(input as byte[] ?? input.ToArray()), System.IO.Compression.CompressionMode.Decompress);
new System.IO.MemoryStream(input.ToArray()), System.IO.Compression.CompressionMode.Decompress);

deflateStream.CopyTo(inflatedStream);

Expand Down
54 changes: 31 additions & 23 deletions implement/elm-time/Pine/FileStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,45 +9,45 @@ namespace Pine;

public interface IFileStoreReader
{
IReadOnlyList<byte>? GetFileContent(IImmutableList<string> path);
ReadOnlyMemory<byte>? GetFileContent(IImmutableList<string> path);

IEnumerable<IImmutableList<string>> ListFilesInDirectory(IImmutableList<string> directoryPath);
}

public interface IFileStoreWriter
{
void SetFileContent(IImmutableList<string> path, IReadOnlyList<byte> fileContent);
void SetFileContent(IImmutableList<string> path, ReadOnlyMemory<byte> fileContent);

// TODO: Simplify IFileStoreWriter: Do we still need AppendFileContent there?
void AppendFileContent(IImmutableList<string> path, IReadOnlyList<byte> fileContent);
void AppendFileContent(IImmutableList<string> path, ReadOnlyMemory<byte> fileContent);

void DeleteFile(IImmutableList<string> path);
}

public record DelegatingFileStoreReader(
Func<IImmutableList<string>, IReadOnlyList<byte>?> GetFileContentDelegate,
Func<IImmutableList<string>, ReadOnlyMemory<byte>?> GetFileContentDelegate,
Func<IImmutableList<string>, IEnumerable<IImmutableList<string>>> ListFilesInDirectoryDelegate)
: IFileStoreReader
{
public IReadOnlyList<byte>? GetFileContent(IImmutableList<string> path) => GetFileContentDelegate(path);
public ReadOnlyMemory<byte>? GetFileContent(IImmutableList<string> path) => GetFileContentDelegate(path);

public IEnumerable<IImmutableList<string>> ListFilesInDirectory(IImmutableList<string> directoryPath) =>
ListFilesInDirectoryDelegate(directoryPath);
}

public record DelegatingFileStoreWriter(
Action<(IImmutableList<string> path, IReadOnlyList<byte> fileContent)> AppendFileContentDelegate,
Action<(IImmutableList<string> path, ReadOnlyMemory<byte> fileContent)> AppendFileContentDelegate,
Action<IImmutableList<string>> DeleteFileDelegate,
Action<(IImmutableList<string> path, IReadOnlyList<byte> fileContent)> SetFileContentDelegate)
Action<(IImmutableList<string> path, ReadOnlyMemory<byte> fileContent)> SetFileContentDelegate)
: IFileStoreWriter
{
public void AppendFileContent(IImmutableList<string> path, IReadOnlyList<byte> fileContent) =>
public void AppendFileContent(IImmutableList<string> path, ReadOnlyMemory<byte> fileContent) =>
AppendFileContentDelegate((path, fileContent));

public void DeleteFile(IImmutableList<string> path) =>
DeleteFileDelegate(path);

public void SetFileContent(IImmutableList<string> path, IReadOnlyList<byte> fileContent) =>
public void SetFileContent(IImmutableList<string> path, ReadOnlyMemory<byte> fileContent) =>
SetFileContentDelegate((path, fileContent));
}

Expand Down Expand Up @@ -89,7 +89,7 @@ private static void EnsureDirectoryExists(string directoryPath)
Directory.CreateDirectory(directoryPath);
}

public void SetFileContent(IImmutableList<string> path, IReadOnlyList<byte> fileContent)
public void SetFileContent(IImmutableList<string> path, ReadOnlyMemory<byte> fileContent)
{
var filePath = CombinePath(path);

Expand All @@ -98,10 +98,14 @@ public void SetFileContent(IImmutableList<string> path, IReadOnlyList<byte> file
if (directoryPath != null)
EnsureDirectoryExists(directoryPath);

File.WriteAllBytes(filePath, fileContent as byte[] ?? fileContent.ToArray());
using var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write);

fileStream.Write(fileContent.Span);

fileStream.Flush();
}

public void AppendFileContent(IImmutableList<string> path, IReadOnlyList<byte> fileContent)
public void AppendFileContent(IImmutableList<string> path, ReadOnlyMemory<byte> fileContent)
{
var filePath = CombinePath(path);

Expand All @@ -112,10 +116,12 @@ public void AppendFileContent(IImmutableList<string> path, IReadOnlyList<byte> f

using var fileStream = new FileStream(filePath, FileMode.Append, FileAccess.Write);

fileStream.Write(fileContent as byte[] ?? fileContent.ToArray());
fileStream.Write(fileContent.Span);

fileStream.Flush();
}

public IReadOnlyList<byte>? GetFileContent(IImmutableList<string> path)
public ReadOnlyMemory<byte>? GetFileContent(IImmutableList<string> path)
{
var filePath = CombinePath(path);

Expand Down Expand Up @@ -161,16 +167,16 @@ public FileStoreFromWriterAndReader(IFileStoreWriter writer, IFileStoreReader re
this.reader = reader;
}

public void AppendFileContent(IImmutableList<string> path, IReadOnlyList<byte> fileContent) =>
public void AppendFileContent(IImmutableList<string> path, ReadOnlyMemory<byte> fileContent) =>
writer.AppendFileContent(path, fileContent);

public void DeleteFile(IImmutableList<string> path) =>
writer.DeleteFile(path);

public void SetFileContent(IImmutableList<string> path, IReadOnlyList<byte> fileContent) =>
public void SetFileContent(IImmutableList<string> path, ReadOnlyMemory<byte> fileContent) =>
writer.SetFileContent(path, fileContent);

public IReadOnlyList<byte>? GetFileContent(IImmutableList<string> path) =>
public ReadOnlyMemory<byte>? GetFileContent(IImmutableList<string> path) =>
reader.GetFileContent(path);

public IEnumerable<IImmutableList<string>> ListFilesInDirectory(IImmutableList<string> directoryPath) =>
Expand All @@ -187,8 +193,8 @@ public IFileStoreReader Apply(IFileStoreReader fileStoreReader) =>
WriteOperation.Apply(history, fileStoreReader);

public record WriteOperation(
(IImmutableList<string> path, IReadOnlyList<byte> fileContent)? SetFileContent = null,
(IImmutableList<string> path, IReadOnlyList<byte> fileContent)? AppendFileContent = null,
(IImmutableList<string> path, ReadOnlyMemory<byte> fileContent)? SetFileContent = null,
(IImmutableList<string> path, ReadOnlyMemory<byte> fileContent)? AppendFileContent = null,
IImmutableList<string>? DeleteFile = null)
{
public static IFileStoreReader Apply(IEnumerable<WriteOperation> writeOperations, IFileStoreReader fileStoreReader) =>
Expand Down Expand Up @@ -235,7 +241,9 @@ public IFileStoreReader Apply(IFileStoreReader previousState)
if (filePath.SequenceEqual(AppendFileContent.Value.path))
{
return (previousFileContent ?? Array.Empty<byte>()).Concat(AppendFileContent.Value.fileContent).ToList();
return CommonConversion.Concat(
(previousFileContent ?? ReadOnlyMemory<byte>.Empty).Span,
AppendFileContent.Value.fileContent.Span);
}
return previousFileContent;
Expand Down Expand Up @@ -276,10 +284,10 @@ public IFileStoreReader Apply(IFileStoreReader previousState)
}
}

public void SetFileContent(IImmutableList<string> path, IReadOnlyList<byte> fileContent) =>
public void SetFileContent(IImmutableList<string> path, ReadOnlyMemory<byte> fileContent) =>
history.Enqueue(new WriteOperation { SetFileContent = (path, fileContent) });

public void AppendFileContent(IImmutableList<string> path, IReadOnlyList<byte> fileContent) =>
public void AppendFileContent(IImmutableList<string> path, ReadOnlyMemory<byte> fileContent) =>
history.Enqueue(new WriteOperation { AppendFileContent = (path, fileContent) });

public void DeleteFile(IImmutableList<string> path) =>
Expand All @@ -288,7 +296,7 @@ public void DeleteFile(IImmutableList<string> path) =>

public class EmptyFileStoreReader : IFileStoreReader
{
public IReadOnlyList<byte>? GetFileContent(IImmutableList<string> path) => null;
public ReadOnlyMemory<byte>? GetFileContent(IImmutableList<string> path) => null;

public IEnumerable<IImmutableList<string>> ListFilesInDirectory(IImmutableList<string> directoryPath) =>
ImmutableList<IImmutableList<string>>.Empty;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,9 @@ public static (IImmutableDictionary<IReadOnlyList<string>, ReadOnlyMemory<byte>>
{
var fileContent = fileStoreReader.GetFileContent(filePath);
if (fileContent != null)
if (fileContent is not null)
{
filesForProcessRestore[filePath] = fileContent.ToArray();
filesForProcessRestore[filePath] = fileContent.Value;
}
return fileContent;
Expand Down
Loading

0 comments on commit e4e4a75

Please sign in to comment.