From 97b93ef47e4e77b362ca1758a3a228ef2a03ca4b Mon Sep 17 00:00:00 2001 From: winstxnhdw Date: Sat, 3 Feb 2024 00:04:52 +0800 Subject: [PATCH] build: load all resources if they end with `.dll` --- lc-hax/Scripts/Helpers/FuzzyMatch.cs | 4 +- .../Libraries/Quickenshtein/DataHelper.cs | 82 ----- .../Quickenshtein/Levenshtein.Common.cs | 346 ------------------ .../Libraries/Quickenshtein/Levenshtein.cs | 81 ---- lc-hax/Scripts/Loader.cs | 29 +- lc-hax/lc-hax.csproj | 10 + lc-hax/packages.lock.json | 34 ++ 7 files changed, 59 insertions(+), 527 deletions(-) delete mode 100644 lc-hax/Scripts/Libraries/Quickenshtein/DataHelper.cs delete mode 100644 lc-hax/Scripts/Libraries/Quickenshtein/Levenshtein.Common.cs delete mode 100644 lc-hax/Scripts/Libraries/Quickenshtein/Levenshtein.cs diff --git a/lc-hax/Scripts/Helpers/FuzzyMatch.cs b/lc-hax/Scripts/Helpers/FuzzyMatch.cs index 4b763dbd..3adf8a61 100644 --- a/lc-hax/Scripts/Helpers/FuzzyMatch.cs +++ b/lc-hax/Scripts/Helpers/FuzzyMatch.cs @@ -30,14 +30,14 @@ static int LongestCommonSubstring(ReadOnlySpan query, ReadOnlySpan o return result; } - static int GetSimilarityWeight(ReadOnlySpan query, ReadOnlySpan original) { + static int GetSimilarityWeight(string query, string original) { int distancePenalty = Levenshtein.GetDistance(query, original); int commonalityReward = Helper.LongestCommonSubstring(query, original) * -2; return distancePenalty + commonalityReward; } - public static string FuzzyMatch(ReadOnlySpan query, StringArray strings) { + public static string FuzzyMatch(string query, StringArray strings) { string closestMatch = strings[0]; int lowestWeight = Helper.GetSimilarityWeight(query, strings[0]); diff --git a/lc-hax/Scripts/Libraries/Quickenshtein/DataHelper.cs b/lc-hax/Scripts/Libraries/Quickenshtein/DataHelper.cs deleted file mode 100644 index 22900d5a..00000000 --- a/lc-hax/Scripts/Libraries/Quickenshtein/DataHelper.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace Quickenshtein.Internal { - internal static class DataHelper { - /// - /// Fills with a number sequence from 1 to the length specified. - /// - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static unsafe void SequentialFill(int* targetPtr, int length) { - int value = 0; - - while (length >= 8) { - length -= 8; - *targetPtr = ++value; - targetPtr++; - *targetPtr = ++value; - targetPtr++; - *targetPtr = ++value; - targetPtr++; - *targetPtr = ++value; - targetPtr++; - *targetPtr = ++value; - targetPtr++; - *targetPtr = ++value; - targetPtr++; - *targetPtr = ++value; - targetPtr++; - *targetPtr = ++value; - targetPtr++; - } - - if (length > 4) { - length -= 4; - *targetPtr = ++value; - targetPtr++; - *targetPtr = ++value; - targetPtr++; - *targetPtr = ++value; - targetPtr++; - *targetPtr = ++value; - targetPtr++; - } - - while (length > 0) { - length--; - *targetPtr = ++value; - targetPtr++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static unsafe int GetIndexOfFirstNonMatchingCharacter(char* sourcePtr, char* targetPtr, int sourceLength, int targetLength) { - int searchLength = Math.Min(sourceLength, targetLength); - int index = 0; - - while (index < searchLength && sourcePtr[index] == targetPtr[index]) { - index++; - } - - return index; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static unsafe void TrimLengthOfMatchingCharacters(char* sourcePtr, char* targetPtr, ref int sourceLength, ref int targetLength) { - int searchLength = Math.Min(sourceLength, targetLength); - - sourcePtr += sourceLength - 1; - targetPtr += targetLength - 1; - - while (searchLength > 0 && sourcePtr[0] == targetPtr[0]) { - sourcePtr--; - targetPtr--; - sourceLength--; - targetLength--; - searchLength--; - } - } - } -} diff --git a/lc-hax/Scripts/Libraries/Quickenshtein/Levenshtein.Common.cs b/lc-hax/Scripts/Libraries/Quickenshtein/Levenshtein.Common.cs deleted file mode 100644 index c29990d4..00000000 --- a/lc-hax/Scripts/Libraries/Quickenshtein/Levenshtein.Common.cs +++ /dev/null @@ -1,346 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace Quickenshtein { - public static partial class Levenshtein { - /// - /// Calculates the costs for an entire row of the virtual matrix. - /// - /// - /// - /// - /// - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static unsafe void CalculateRow(int* previousRowPtr, char* targetPtr, int targetLength, char sourcePrevChar, int lastInsertionCost, int lastSubstitutionCost) { - int lastDeletionCost; - int localCost; - int rowColumnsRemaining = targetLength; - - while (rowColumnsRemaining >= 8) { - rowColumnsRemaining -= 8; - localCost = lastSubstitutionCost; - lastDeletionCost = previousRowPtr[0]; - - if (sourcePrevChar != targetPtr[0]) { - localCost = Math.Min(lastInsertionCost, localCost); - localCost = Math.Min(lastDeletionCost, localCost); - localCost++; - } - - lastInsertionCost = localCost; - previousRowPtr[0] = localCost; - lastSubstitutionCost = lastDeletionCost; - previousRowPtr++; - targetPtr++; - - localCost = lastSubstitutionCost; - lastDeletionCost = previousRowPtr[0]; - - if (sourcePrevChar != targetPtr[0]) { - localCost = Math.Min(lastInsertionCost, localCost); - localCost = Math.Min(lastDeletionCost, localCost); - localCost++; - } - - lastInsertionCost = localCost; - previousRowPtr[0] = localCost; - lastSubstitutionCost = lastDeletionCost; - previousRowPtr++; - targetPtr++; - - localCost = lastSubstitutionCost; - lastDeletionCost = previousRowPtr[0]; - - if (sourcePrevChar != targetPtr[0]) { - localCost = Math.Min(lastInsertionCost, localCost); - localCost = Math.Min(lastDeletionCost, localCost); - localCost++; - } - - lastInsertionCost = localCost; - previousRowPtr[0] = localCost; - lastSubstitutionCost = lastDeletionCost; - previousRowPtr++; - targetPtr++; - - localCost = lastSubstitutionCost; - lastDeletionCost = previousRowPtr[0]; - - if (sourcePrevChar != targetPtr[0]) { - localCost = Math.Min(lastInsertionCost, localCost); - localCost = Math.Min(lastDeletionCost, localCost); - localCost++; - } - - lastInsertionCost = localCost; - previousRowPtr[0] = localCost; - lastSubstitutionCost = lastDeletionCost; - previousRowPtr++; - targetPtr++; - - localCost = lastSubstitutionCost; - lastDeletionCost = previousRowPtr[0]; - - if (sourcePrevChar != targetPtr[0]) { - localCost = Math.Min(lastInsertionCost, localCost); - localCost = Math.Min(lastDeletionCost, localCost); - localCost++; - } - - lastInsertionCost = localCost; - previousRowPtr[0] = localCost; - lastSubstitutionCost = lastDeletionCost; - previousRowPtr++; - targetPtr++; - - localCost = lastSubstitutionCost; - lastDeletionCost = previousRowPtr[0]; - - if (sourcePrevChar != targetPtr[0]) { - localCost = Math.Min(lastInsertionCost, localCost); - localCost = Math.Min(lastDeletionCost, localCost); - localCost++; - } - - lastInsertionCost = localCost; - previousRowPtr[0] = localCost; - lastSubstitutionCost = lastDeletionCost; - previousRowPtr++; - targetPtr++; - - localCost = lastSubstitutionCost; - lastDeletionCost = previousRowPtr[0]; - - if (sourcePrevChar != targetPtr[0]) { - localCost = Math.Min(lastInsertionCost, localCost); - localCost = Math.Min(lastDeletionCost, localCost); - localCost++; - } - - lastInsertionCost = localCost; - previousRowPtr[0] = localCost; - lastSubstitutionCost = lastDeletionCost; - previousRowPtr++; - targetPtr++; - - localCost = lastSubstitutionCost; - lastDeletionCost = previousRowPtr[0]; - - if (sourcePrevChar != targetPtr[0]) { - localCost = Math.Min(lastInsertionCost, localCost); - localCost = Math.Min(lastDeletionCost, localCost); - localCost++; - } - - lastInsertionCost = localCost; - previousRowPtr[0] = localCost; - lastSubstitutionCost = lastDeletionCost; - previousRowPtr++; - targetPtr++; - } - - if (rowColumnsRemaining > 4) { - rowColumnsRemaining -= 4; - - localCost = lastSubstitutionCost; - lastDeletionCost = previousRowPtr[0]; - - if (sourcePrevChar != targetPtr[0]) { - localCost = Math.Min(lastInsertionCost, localCost); - localCost = Math.Min(lastDeletionCost, localCost); - localCost++; - } - - lastInsertionCost = localCost; - previousRowPtr[0] = localCost; - lastSubstitutionCost = lastDeletionCost; - previousRowPtr++; - targetPtr++; - - localCost = lastSubstitutionCost; - lastDeletionCost = previousRowPtr[0]; - - if (sourcePrevChar != targetPtr[0]) { - localCost = Math.Min(lastInsertionCost, localCost); - localCost = Math.Min(lastDeletionCost, localCost); - localCost++; - } - - lastInsertionCost = localCost; - previousRowPtr[0] = localCost; - lastSubstitutionCost = lastDeletionCost; - previousRowPtr++; - targetPtr++; - - localCost = lastSubstitutionCost; - lastDeletionCost = previousRowPtr[0]; - - if (sourcePrevChar != targetPtr[0]) { - localCost = Math.Min(lastInsertionCost, localCost); - localCost = Math.Min(lastDeletionCost, localCost); - localCost++; - } - - lastInsertionCost = localCost; - previousRowPtr[0] = localCost; - lastSubstitutionCost = lastDeletionCost; - previousRowPtr++; - targetPtr++; - - localCost = lastSubstitutionCost; - lastDeletionCost = previousRowPtr[0]; - - if (sourcePrevChar != targetPtr[0]) { - localCost = Math.Min(lastInsertionCost, localCost); - localCost = Math.Min(lastDeletionCost, localCost); - localCost++; - } - - lastInsertionCost = localCost; - previousRowPtr[0] = localCost; - lastSubstitutionCost = lastDeletionCost; - previousRowPtr++; - targetPtr++; - } - - while (rowColumnsRemaining > 0) { - rowColumnsRemaining--; - - localCost = lastSubstitutionCost; - lastDeletionCost = previousRowPtr[0]; - - if (sourcePrevChar != targetPtr[0]) { - localCost = Math.Min(lastInsertionCost, localCost); - localCost = Math.Min(lastDeletionCost, localCost); - localCost++; - } - - lastInsertionCost = localCost; - previousRowPtr[0] = localCost; - lastSubstitutionCost = lastDeletionCost; - previousRowPtr++; - targetPtr++; - } - } - - /// - /// Calculates the costs for the virtual matrix. - /// This performs a 4x outer loop unrolling allowing fewer lookups of target character and deletion cost data across the rows. - /// - /// - /// - /// - /// - /// - static unsafe void CalculateRows_4Rows(int* previousRowPtr, char* sourcePtr, int sourceLength, ref int rowIndex, char* targetPtr, int targetLength) { - int acceptableRowCount = sourceLength - 3; - - int row1Costs, row2Costs, row3Costs, row4Costs, row5Costs; - char sourceChar1, sourceChar2, sourceChar3, sourceChar4; - - for (; rowIndex < acceptableRowCount;) { - char* localTargetPtr = targetPtr; - int* localPreviousRowPtr = previousRowPtr; - - sourceChar1 = sourcePtr[row1Costs = rowIndex]; //Sub - sourceChar2 = sourcePtr[row2Costs = rowIndex + 1]; //Insert, Sub - sourceChar3 = sourcePtr[row3Costs = rowIndex + 2]; //Insert, Sub - sourceChar4 = sourcePtr[row4Costs = rowIndex + 3]; //Insert, Sub - row5Costs = rowIndex += 4; //Insert - - int rowColumnsRemaining = targetLength; - - while (rowColumnsRemaining >= 8) { - rowColumnsRemaining -= 8; - CalculateColumn_4Rows(ref localTargetPtr, ref localPreviousRowPtr, ref row1Costs, ref row2Costs, ref row3Costs, ref row4Costs, ref row5Costs, sourceChar1, sourceChar2, sourceChar3, sourceChar4); - CalculateColumn_4Rows(ref localTargetPtr, ref localPreviousRowPtr, ref row1Costs, ref row2Costs, ref row3Costs, ref row4Costs, ref row5Costs, sourceChar1, sourceChar2, sourceChar3, sourceChar4); - CalculateColumn_4Rows(ref localTargetPtr, ref localPreviousRowPtr, ref row1Costs, ref row2Costs, ref row3Costs, ref row4Costs, ref row5Costs, sourceChar1, sourceChar2, sourceChar3, sourceChar4); - CalculateColumn_4Rows(ref localTargetPtr, ref localPreviousRowPtr, ref row1Costs, ref row2Costs, ref row3Costs, ref row4Costs, ref row5Costs, sourceChar1, sourceChar2, sourceChar3, sourceChar4); - CalculateColumn_4Rows(ref localTargetPtr, ref localPreviousRowPtr, ref row1Costs, ref row2Costs, ref row3Costs, ref row4Costs, ref row5Costs, sourceChar1, sourceChar2, sourceChar3, sourceChar4); - CalculateColumn_4Rows(ref localTargetPtr, ref localPreviousRowPtr, ref row1Costs, ref row2Costs, ref row3Costs, ref row4Costs, ref row5Costs, sourceChar1, sourceChar2, sourceChar3, sourceChar4); - CalculateColumn_4Rows(ref localTargetPtr, ref localPreviousRowPtr, ref row1Costs, ref row2Costs, ref row3Costs, ref row4Costs, ref row5Costs, sourceChar1, sourceChar2, sourceChar3, sourceChar4); - CalculateColumn_4Rows(ref localTargetPtr, ref localPreviousRowPtr, ref row1Costs, ref row2Costs, ref row3Costs, ref row4Costs, ref row5Costs, sourceChar1, sourceChar2, sourceChar3, sourceChar4); - } - - if (rowColumnsRemaining >= 4) { - rowColumnsRemaining -= 4; - CalculateColumn_4Rows(ref localTargetPtr, ref localPreviousRowPtr, ref row1Costs, ref row2Costs, ref row3Costs, ref row4Costs, ref row5Costs, sourceChar1, sourceChar2, sourceChar3, sourceChar4); - CalculateColumn_4Rows(ref localTargetPtr, ref localPreviousRowPtr, ref row1Costs, ref row2Costs, ref row3Costs, ref row4Costs, ref row5Costs, sourceChar1, sourceChar2, sourceChar3, sourceChar4); - CalculateColumn_4Rows(ref localTargetPtr, ref localPreviousRowPtr, ref row1Costs, ref row2Costs, ref row3Costs, ref row4Costs, ref row5Costs, sourceChar1, sourceChar2, sourceChar3, sourceChar4); - CalculateColumn_4Rows(ref localTargetPtr, ref localPreviousRowPtr, ref row1Costs, ref row2Costs, ref row3Costs, ref row4Costs, ref row5Costs, sourceChar1, sourceChar2, sourceChar3, sourceChar4); - } - - while (rowColumnsRemaining > 0) { - rowColumnsRemaining--; - CalculateColumn_4Rows(ref localTargetPtr, ref localPreviousRowPtr, ref row1Costs, ref row2Costs, ref row3Costs, ref row4Costs, ref row5Costs, sourceChar1, sourceChar2, sourceChar3, sourceChar4); - } - } - } - - /// - /// Calculates the cost for 4 vertically adjacent cells in the virtual matrix. - /// Comparing 4 vertically adjacent cells prevents 3 target character lookups, 3 deletion cost lookups and 3 saves of the deletion cost. - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static unsafe void CalculateColumn_4Rows(ref char* targetPtr, ref int* previousRowPtr, ref int row1Costs, ref int row2Costs, ref int row3Costs, ref int row4Costs, ref int row5Costs, char sourceChar1, char sourceChar2, char sourceChar3, char sourceChar4) { - char targetChar = targetPtr[0]; - int lastDeletionCost = previousRowPtr[0]; - int localCost = row1Costs; - - if (sourceChar1 != targetChar) { - localCost = Math.Min(row2Costs, localCost); - localCost = Math.Min(lastDeletionCost, localCost); - localCost++; - } - - row1Costs = lastDeletionCost; - lastDeletionCost = localCost; - localCost = row2Costs; - - if (sourceChar2 != targetChar) { - localCost = Math.Min(row3Costs, localCost); - localCost = Math.Min(lastDeletionCost, localCost); - localCost++; - } - - row2Costs = lastDeletionCost; - lastDeletionCost = localCost; - localCost = row3Costs; - - if (sourceChar3 != targetChar) { - localCost = Math.Min(row4Costs, localCost); - localCost = Math.Min(lastDeletionCost, localCost); - localCost++; - } - - row3Costs = lastDeletionCost; - lastDeletionCost = localCost; - localCost = row4Costs; - - if (sourceChar4 != targetChar) { - localCost = Math.Min(row5Costs, localCost); - localCost = Math.Min(lastDeletionCost, localCost); - localCost++; - } - - row4Costs = lastDeletionCost; - previousRowPtr[0] = row5Costs = localCost; - - previousRowPtr++; - targetPtr++; - } - } -} diff --git a/lc-hax/Scripts/Libraries/Quickenshtein/Levenshtein.cs b/lc-hax/Scripts/Libraries/Quickenshtein/Levenshtein.cs deleted file mode 100644 index 2c0a0ed6..00000000 --- a/lc-hax/Scripts/Libraries/Quickenshtein/Levenshtein.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using System.Buffers; -using System.Runtime.CompilerServices; -using Quickenshtein.Internal; - -namespace Quickenshtein { - /// - /// A modified Levenshtein Distance Calculator based on https://github.com/Turnerj/Quickenshtein - /// - public static partial class Levenshtein { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static unsafe int GetDistance(ReadOnlySpan source, ReadOnlySpan target) { - int sourceLength = source.Length; - int targetLength = target.Length; - - if (sourceLength == 0) { - return targetLength; - } - if (targetLength == 0) { - return sourceLength; - } - - fixed (char* sourcePtr = source) - fixed (char* targetPtr = target) { - return CalculateDistance(sourcePtr, targetPtr, sourceLength, targetLength); - } - } - - static unsafe int CalculateDistance(char* sourcePtr, char* targetPtr, int sourceLength, int targetLength) { - //Identify and trim any common prefix or suffix between the strings - int offset = DataHelper.GetIndexOfFirstNonMatchingCharacter(sourcePtr, targetPtr, sourceLength, targetLength); - sourcePtr += offset; - targetPtr += offset; - sourceLength -= offset; - targetLength -= offset; - DataHelper.TrimLengthOfMatchingCharacters(sourcePtr, targetPtr, ref sourceLength, ref targetLength); - - //Check the trimmed values are not empty - if (sourceLength == 0) { - return targetLength; - } - if (targetLength == 0) { - return sourceLength; - } - - //Switch around variables so outer loop has fewer iterations - if (targetLength < sourceLength) { - char* tempSourcePtr = sourcePtr; - sourcePtr = targetPtr; - targetPtr = tempSourcePtr; - - (sourceLength, targetLength) = (targetLength, sourceLength); - } - - int[] pooledArray = ArrayPool.Shared.Rent(targetLength); - - fixed (int* previousRowPtr = pooledArray) { - DataHelper.SequentialFill(previousRowPtr, targetLength); - - int rowIndex = 0; - - CalculateRows_4Rows(previousRowPtr, sourcePtr, sourceLength, ref rowIndex, targetPtr, targetLength); - - //Calculate Single Rows - for (; rowIndex < sourceLength; rowIndex++) { - int lastSubstitutionCost = rowIndex; - int lastInsertionCost = rowIndex + 1; - - char sourcePrevChar = sourcePtr[rowIndex]; - - CalculateRow(previousRowPtr, targetPtr, targetLength, sourcePrevChar, lastInsertionCost, lastSubstitutionCost); - } - - int result = previousRowPtr[targetLength - 1]; - ArrayPool.Shared.Return(pooledArray); - - return result; - } - } - } -} diff --git a/lc-hax/Scripts/Loader.cs b/lc-hax/Scripts/Loader.cs index 9f09b317..109fc8ab 100644 --- a/lc-hax/Scripts/Loader.cs +++ b/lc-hax/Scripts/Loader.cs @@ -3,6 +3,7 @@ using System.Reflection; using UnityEngine; using HarmonyLib; +using System.Linq; namespace Hax; @@ -13,31 +14,27 @@ public class Loader : MonoBehaviour { static void AddHaxModules() where T : Component => Loader.HaxModules.AddComponent(); static void AddHaxGameObject() where T : Component => Loader.HaxGameObjects.AddComponent(); - static Assembly OnResolveAssembly(object _, ResolveEventArgs args) { + static void LoadLibraries() { Assembly assembly = Assembly.GetExecutingAssembly(); - string? resourceName = - assembly.GetManifestResourceNames() - .First(name => name.EndsWith($"{new AssemblyName(args.Name).Name}.dll")); - if (string.IsNullOrWhiteSpace(resourceName)) { - Logger.Write($"Failed to resolve assembly: {args.Name}"); - throw new FileNotFoundException(); + StringArray resourceNames = + assembly.GetManifestResourceNames() + .Where(name => name.EndsWith(".dll")) + .ToArray(); + + foreach (string resourceName in resourceNames) { + using Stream stream = assembly.GetManifestResourceStream(resourceName); + using MemoryStream memoryStream = new(); + stream.CopyTo(memoryStream); + _ = AppDomain.CurrentDomain.Load(memoryStream.ToArray()); } - - using Stream stream = assembly.GetManifestResourceStream(resourceName); - using MemoryStream memoryStream = new(); - stream.CopyTo(memoryStream); - return Assembly.Load(memoryStream.ToArray()); } public static void Load() { - AppDomain.CurrentDomain.AssemblyResolve += Loader.OnResolveAssembly; - + Loader.LoadLibraries(); Loader.LoadHarmonyPatches(); Loader.LoadHaxGameObjects(); Loader.LoadHaxModules(); - - AppDomain.CurrentDomain.AssemblyResolve -= Loader.OnResolveAssembly; } static void LoadHarmonyPatches() { diff --git a/lc-hax/lc-hax.csproj b/lc-hax/lc-hax.csproj index 45b3456f..055feaee 100644 --- a/lc-hax/lc-hax.csproj +++ b/lc-hax/lc-hax.csproj @@ -123,6 +123,16 @@ + + + + + + + + + + diff --git a/lc-hax/packages.lock.json b/lc-hax/packages.lock.json index f6223449..c65cdc12 100644 --- a/lc-hax/packages.lock.json +++ b/lc-hax/packages.lock.json @@ -8,6 +8,15 @@ "resolved": "2.2.2", "contentHash": "70KvWz+DiUELxafsYL/LHxA/jH3PDWeApLo/VwtnrpTvRWQ/eUdPfS/l5funmhZWOy41QXw6UjVv+6C57Nx77A==" }, + "Quickenshtein": { + "type": "Direct", + "requested": "[1.5.1, )", + "resolved": "1.5.1", + "contentHash": "orca+eUrt8FSF/mrgxFA2XNyXdp+2N/7+lwxD/cJEub6D/4VfpBMUkZrvP3WubKz3ToyDO0HV3sYbQql3xL7Nw==", + "dependencies": { + "System.Memory": "4.5.4" + } + }, "RequireNamedArgs": { "type": "Direct", "requested": "[0.0.7, )", @@ -21,6 +30,31 @@ "type": "Transitive", "resolved": "4.5.2", "contentHash": "apbdQOjzsjQ637kTWQuW29jqwY18jsHMyNC5A+TPJZKFEIE2cIfQWf3V7+mXrxlbX69BueYkv293/g70wuXuRw==" + }, + "System.Buffers": { + "type": "Transitive", + "resolved": "4.5.1", + "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==", + "dependencies": { + "System.Buffers": "4.5.1", + "System.Numerics.Vectors": "4.4.0", + "System.Runtime.CompilerServices.Unsafe": "4.5.3" + } + }, + "System.Numerics.Vectors": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "UiLzLW+Lw6HLed1Hcg+8jSRttrbuXv7DANVj0DkL9g6EnnzbL75EB7EWsw5uRbhxd/4YdG8li5XizGWepmG3PQ==" + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "4.5.3", + "contentHash": "3TIsJhD1EiiT0w2CcDMN/iSSwnNnsrnbzeVHSKkaEgV85txMprmuO+Yq2AdSbeVGcg28pdNDTPK87tJhX7VFHw==" } }, ".NETStandard,Version=v2.1/win-x64": {}