generated from Nexus-Mods/NexusMods.App.Template
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #55 from Nexus-Mods/nx-extensions
Added: Extensions for Nx Library And Support for Writing to Memory Mapped Files
- Loading branch information
Showing
22 changed files
with
679 additions
and
93 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
is_global = true | ||
|
||
# CS4014: Task not awaited | ||
dotnet_diagnostic.cs4014.severity = error | ||
|
||
# CS8509: Missing switch case for named enum value | ||
dotnet_diagnostic.CS8509.severity = error | ||
|
||
# CS824: Missing switch case for unnamed enum value | ||
dotnet_diagnostic.CS8524.severity = none | ||
|
||
# Enums should not have duplicate values | ||
dotnet_diagnostic.CA1069.severity = error | ||
|
||
# Non-constant fields should not be visible | ||
dotnet_diagnostic.CA2211.severity = error | ||
|
||
# Don't call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types | ||
dotnet_diagnostic.CA2021.severity = error | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Submodule meta
updated
8 files
60 changes: 60 additions & 0 deletions
60
...ensions/NexusMods.Paths.Extensions.Nx/FileProviders/FileData/PathsMemoryMappedFileData.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
using System; | ||
using NexusMods.Archives.Nx.Interfaces; | ||
|
||
namespace NexusMods.Paths.Extensions.Nx.FileProviders.FileData; | ||
|
||
/// <summary> | ||
/// Provides access to data of a Paths memory-mapped file. | ||
/// </summary> | ||
public unsafe class PathsMemoryMappedFileData : IFileData | ||
{ | ||
private readonly MemoryMappedFileHandle _memoryMappedFileHandle; | ||
private readonly bool _disposeHandle; | ||
private bool _disposed; | ||
|
||
/// <inheritdoc /> | ||
public byte* Data { get; } | ||
|
||
/// <inheritdoc /> | ||
public ulong DataLength { get; } | ||
|
||
/// <summary> | ||
/// Paths memory mapped file data. | ||
/// </summary> | ||
/// <param name="handle">The handle to use</param> | ||
/// <param name="start">The start offset in the file</param> | ||
/// <param name="length">The length of the data to map</param> | ||
/// <param name="disposeHandle">Disposes the handle on close.</param> | ||
public PathsMemoryMappedFileData(MemoryMappedFileHandle handle, ulong start, ulong length, bool disposeHandle = true) | ||
{ | ||
_memoryMappedFileHandle = handle; | ||
_disposeHandle = disposeHandle; | ||
if (start >= handle.Length) | ||
{ | ||
Data = handle.Pointer; | ||
DataLength = 0; | ||
} | ||
else | ||
{ | ||
Data = handle.Pointer + start; | ||
DataLength = Math.Min(length, handle.Length - start); | ||
} | ||
} | ||
|
||
/// <inheritdoc /> | ||
~PathsMemoryMappedFileData() => Dispose(); | ||
|
||
/// <inheritdoc /> | ||
public void Dispose() | ||
{ | ||
if (_disposed) | ||
return; | ||
|
||
_disposed = true; | ||
|
||
if (_disposeHandle) | ||
_memoryMappedFileHandle.Dispose(); | ||
|
||
GC.SuppressFinalize(this); | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
src/Extensions/NexusMods.Paths.Extensions.Nx/FileProviders/FromAbsolutePathProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
using NexusMods.Archives.Nx.Interfaces; | ||
using NexusMods.Paths.Extensions.Nx.FileProviders.FileData; | ||
using System.IO; | ||
using System.IO.MemoryMappedFiles; | ||
|
||
namespace NexusMods.Paths.Extensions.Nx.FileProviders; | ||
|
||
/// <summary> | ||
/// A provider for creating <see cref="IFileData" /> instances from an absolute path | ||
/// </summary> | ||
public class FromAbsolutePathProvider : IFileDataProvider | ||
{ | ||
/// <summary> | ||
/// The full path to the file from which the data will be fetched. | ||
/// </summary> | ||
public required AbsolutePath FilePath { get; init; } | ||
|
||
/// <inheritdoc /> | ||
public IFileData GetFileData(ulong start, ulong length) | ||
{ | ||
// TODO: This could probably be better, as it's unoptimal for chunked files. | ||
// Ideally the file should be opened once in the provider and then calls in GetFileData | ||
// could work on slices of the larger MMF. | ||
// This however requires a change in Nx itself, which should be done at some point. | ||
var fileSystem = FilePath.FileSystem; | ||
var handle = fileSystem.CreateMemoryMappedFile(FilePath, FileMode.Open, MemoryMappedFileAccess.Read, 0); | ||
return new PathsMemoryMappedFileData(handle, start, length); | ||
} | ||
} |
94 changes: 94 additions & 0 deletions
94
src/Extensions/NexusMods.Paths.Extensions.Nx/FileProviders/OutputAbsolutePathProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
using System; | ||
using System.IO; | ||
using System.IO.MemoryMappedFiles; | ||
using NexusMods.Archives.Nx.FileProviders.FileData; | ||
using NexusMods.Archives.Nx.Headers.Managed; | ||
using NexusMods.Archives.Nx.Interfaces; | ||
using NexusMods.Paths.Extensions.Nx.FileProviders.FileData; | ||
|
||
namespace NexusMods.Paths.Extensions.Nx.FileProviders; | ||
|
||
/// <summary> | ||
/// A provider for creating <see cref="IFileData" /> instances which allow | ||
/// the user to output information to an absolute path. | ||
/// </summary> | ||
public class OutputAbsolutePathProvider : IOutputDataProvider | ||
{ | ||
/// <inheritdoc /> | ||
public string RelativePath { get; } | ||
|
||
/// <inheritdoc /> | ||
public FileEntry Entry { get; } | ||
|
||
/// <summary> | ||
/// Full path to the file. | ||
/// </summary> | ||
public AbsolutePath FullPath { get; } | ||
|
||
private readonly MemoryMappedFileHandle? _mappedFileHandle; | ||
private bool _isDisposed; | ||
private readonly bool _isEmpty; | ||
|
||
/// <summary> | ||
/// Initializes outputting a file to an absolute path. | ||
/// </summary> | ||
/// <param name="fullPath">The absolute path to output the file.</param> | ||
/// <param name="relativePath">The relative path of the file (context from the Nx archive).</param> | ||
/// <param name="entry">The individual file entry (context from the Nx archive).</param> | ||
public OutputAbsolutePathProvider(AbsolutePath fullPath, string relativePath, FileEntry entry) | ||
{ | ||
RelativePath = relativePath; | ||
Entry = entry; | ||
FullPath = fullPath; | ||
|
||
TryCreate: | ||
try | ||
{ | ||
if (entry.DecompressedSize <= 0) | ||
{ | ||
using var _ = FullPath.FileSystem.CreateFile(FullPath); | ||
_isEmpty = true; | ||
return; | ||
} | ||
|
||
// Ensure the directory exists | ||
FullPath.FileSystem.CreateDirectory(FullPath.Parent); | ||
|
||
// Delete the file if it exists to ensure we start with an empty file | ||
if (FullPath.FileSystem.FileExists(FullPath)) | ||
FullPath.FileSystem.DeleteFile(FullPath); | ||
|
||
// Create the memory mapped file | ||
_mappedFileHandle = FullPath.FileSystem.CreateMemoryMappedFile(FullPath, FileMode.CreateNew, MemoryMappedFileAccess.ReadWrite, entry.DecompressedSize); | ||
} | ||
catch (DirectoryNotFoundException) | ||
{ | ||
// This is written this way because explicit check is slow. | ||
FullPath.FileSystem.CreateDirectory(FullPath.Parent); | ||
goto TryCreate; | ||
} | ||
} | ||
|
||
/// <inheritdoc /> | ||
public IFileData GetFileData(ulong start, ulong length) | ||
{ | ||
if (_isEmpty) | ||
return new ArrayFileData(Array.Empty<byte>(), 0, 0); | ||
|
||
return new PathsMemoryMappedFileData(_mappedFileHandle!.Value, start, length, false); | ||
} | ||
|
||
/// <inheritdoc /> | ||
~OutputAbsolutePathProvider() => Dispose(); | ||
|
||
/// <inheritdoc /> | ||
public void Dispose() | ||
{ | ||
if (_isDisposed) | ||
return; | ||
|
||
_isDisposed = true; | ||
_mappedFileHandle?.Dispose(); | ||
GC.SuppressFinalize(this); | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
src/Extensions/NexusMods.Paths.Extensions.Nx/NexusMods.Paths.Extensions.Nx.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<Import Project="$([MSBuild]::GetPathOfFileAbove('NuGet.Build.props', '$(MSBuildThisFileDirectory)../../'))" /> | ||
|
||
<PropertyGroup> | ||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="NexusMods.Archives.Nx" Version="0.5.0" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\..\NexusMods.Paths\NexusMods.Paths.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.