aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2024-01-08 22:04:41 -0500
committerLibravatar vnugent <public@vaughnnugent.com>2024-01-08 22:04:41 -0500
commit50885f7cd7e0519c96b0c95fce9ba6bf69502cf7 (patch)
tree11db78a9c2b9da56de92ebe27183c0ce12098947
parent86c0532edc0042b26dda5f1ca41abdf80db46414 (diff)
Some net 8.0 goodies like sha3 support
-rw-r--r--lib/Hashing.Portable/src/HashAlg.cs22
-rw-r--r--lib/Hashing.Portable/src/ManagedHash.cs349
-rw-r--r--lib/Hashing.Portable/src/ManagedHashAlgImpl.cs113
-rw-r--r--lib/Hashing.Portable/tests/ManagedHashTests.cs29
-rw-r--r--lib/Net.Compression/vnlib_compress/CMakeLists.txt20
-rw-r--r--lib/Net.Http/src/Core/HttpServerBase.cs14
-rw-r--r--lib/Net.Http/src/Core/HttpServerProcessing.cs2
-rw-r--r--lib/Net.Http/src/Core/InitDataBuffer.cs4
-rw-r--r--lib/Net.Http/src/Helpers/HttpHelpers.cs35
-rw-r--r--lib/Net.Http/src/Helpers/MimeLookups.cs19
-rw-r--r--lib/Plugins.Essentials/src/SemiConsistentVeTable.cs19
-rw-r--r--lib/Utils.Memory/vnlib_mimalloc/CMakeLists.txt2
-rw-r--r--lib/Utils.Memory/vnlib_rpmalloc/CMakeLists.txt2
-rw-r--r--lib/Utils/src/Extensions/MemoryExtensions.cs185
-rw-r--r--lib/Utils/src/IO/VnMemoryStream.cs78
-rw-r--r--lib/Utils/src/Memory/ArrayPoolBuffer.cs26
-rw-r--r--lib/Utils/src/Memory/MemoryHandle.cs30
-rw-r--r--lib/Utils/src/Memory/MemoryUtil.cs77
-rw-r--r--lib/Utils/src/Memory/MemoryUtilAlloc.cs12
-rw-r--r--lib/Utils/src/Memory/UnmanagedHeapBase.cs30
-rw-r--r--lib/Utils/src/Native/NativeMemoryOutOfMemoryException.cs16
-rw-r--r--lib/Utils/src/Native/SafeLibraryHandle.cs11
-rw-r--r--lib/Utils/src/VnEncoding.cs4
23 files changed, 514 insertions, 585 deletions
diff --git a/lib/Hashing.Portable/src/HashAlg.cs b/lib/Hashing.Portable/src/HashAlg.cs
index 030e7e6..4535b08 100644
--- a/lib/Hashing.Portable/src/HashAlg.cs
+++ b/lib/Hashing.Portable/src/HashAlg.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Hashing.Portable
@@ -58,6 +58,26 @@ namespace VNLib.Hashing
/// </summary>
MD5 = 16,
+#pragma warning disable CA1707 // Identifiers should not contain underscores
+
+ /// <summary>
+ /// Defines the SHA3-512 hashing algorithm. NOTE: May not be supported on all platforms.
+ /// Inspect the value of <see cref="ManagedHash.SupportsSha3"/>
+ /// </summary>
+ SHA3_512 = 364,
+ /// <summary>
+ /// Defines the SHA3-384 hashing algorithm. NOTE: May not be supported on all platforms.
+ /// Inspect the value of <see cref="ManagedHash.SupportsSha3"/>
+ /// </summary>
+ SHA3_384 = 348,
+ /// <summary>
+ /// Defines the SHA3-256 hashing algorithm. NOTE: May not be supported on all platforms.
+ /// Inspect the value of <see cref="ManagedHash.SupportsSha3"/>
+ /// </summary>
+ SHA3_256 = 332,
+
+#pragma warning restore CA1707 // Identifiers should not contain underscores
+
/*
* The blake2 value is negative because the hash size is variable and the enum value
* and cannot be used to determine the hash buffer size.
diff --git a/lib/Hashing.Portable/src/ManagedHash.cs b/lib/Hashing.Portable/src/ManagedHash.cs
index 5933804..49a2f09 100644
--- a/lib/Hashing.Portable/src/ManagedHash.cs
+++ b/lib/Hashing.Portable/src/ManagedHash.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Hashing.Portable
@@ -24,12 +24,12 @@
using System;
using System.Text;
+using System.Diagnostics;
using System.Security.Cryptography;
using VNLib.Utils;
using VNLib.Utils.Memory;
using VNLib.Hashing.Native.MonoCypher;
-using VNLib.Utils.Extensions;
namespace VNLib.Hashing
{
@@ -76,34 +76,47 @@ namespace VNLib.Hashing
private static readonly Md5 _md5Alg;
private static readonly Blake2b _blake2bAlg;
+ private static readonly Sha3_256 _3_sha256;
+ private static readonly Sha3_384 _3_sha384;
+ private static readonly Sha3_512 _3_sha512;
+
/// <summary>
/// Gets a value that indicates whether the current runtime has the required libraries
/// available to support the Blake2b hashing algorithm
/// </summary>
- public static bool SupportsBlake2b => MonoCypherLibrary.CanLoadDefaultLibrary();
+ public static bool SupportsBlake2b => MonoCypherLibrary.CanLoadDefaultLibrary();
+
+ /// <summary>
+ /// Gets a value that indicates whether the current platform supports the SHA3
+ /// hashing algorithm.
+ /// </summary>
+ public static bool SupportsSha3
+ {
+ get
+ {
+ if (Sha3_512.IsSupported)
+ {
+ //Assume others are supported too
+ Debug.Assert(Sha3_384.IsSupported);
+ Debug.Assert(Sha3_256.IsSupported);
+ return true;
+ }
+
+ return false;
+ }
+ }
/// <summary>
/// Uses the UTF8 character encoding to encode the string, then
/// attempts to compute the hash and store the results into the output buffer
/// </summary>
/// <param name="data">String to hash</param>
- /// <param name="buffer">The hash output buffer</param>
+ /// <param name="output">The hash output buffer</param>
/// <param name="type">The hash algorithm to use</param>
/// <returns>The number of bytes written to the buffer, false if the hash could not be computed</returns>
/// <exception cref="ArgumentException"></exception>
- public static ERRNO ComputeHash(ReadOnlySpan<char> data, Span<byte> buffer, HashAlg type)
- {
- return type switch
- {
- HashAlg.BlAKE2B => ComputeHashInternal(in _blake2bAlg, data, buffer),
- HashAlg.SHA512 => ComputeHashInternal(in _sha512Alg, data, buffer),
- HashAlg.SHA384 => ComputeHashInternal(in _sha384Alg, data, buffer),
- HashAlg.SHA256 => ComputeHashInternal(in _sha256Alg, data, buffer),
- HashAlg.SHA1 => ComputeHashInternal(in _sha1Alg, data, buffer),
- HashAlg.MD5 => ComputeHashInternal(in _md5Alg, data, buffer),
- _ => throw new ArgumentException("Invalid hash algorithm", nameof(type))
- };
- }
+ public static ERRNO ComputeHash(ReadOnlySpan<char> data, Span<byte> output, HashAlg type)
+ => ComputeHashInternal(type, data, output);
/// <summary>
/// Uses the UTF8 character encoding to encode the string, then
@@ -113,19 +126,8 @@ namespace VNLib.Hashing
/// <param name="type">The hash algorithm to use</param>
/// <returns>The number of bytes written to the buffer, false if the hash could not be computed</returns>
/// <exception cref="ArgumentException"></exception>
- public static byte[] ComputeHash(ReadOnlySpan<char> data, HashAlg type)
- {
- return type switch
- {
- HashAlg.BlAKE2B => ComputeHashInternal(in _blake2bAlg, data),
- HashAlg.SHA512 => ComputeHashInternal(in _sha512Alg, data),
- HashAlg.SHA384 => ComputeHashInternal(in _sha384Alg, data),
- HashAlg.SHA256 => ComputeHashInternal(in _sha256Alg, data),
- HashAlg.SHA1 => ComputeHashInternal(in _sha1Alg, data),
- HashAlg.MD5 => ComputeHashInternal(in _md5Alg, data),
- _ => throw new ArgumentException("Invalid hash algorithm", nameof(type))
- };
- }
+ public static byte[] ComputeHash(ReadOnlySpan<char> data, HashAlg type)
+ => ComputeHashInternal(type, data);
/// <summary>
/// Hashes the data parameter to the output buffer using the specified algorithm type
@@ -135,20 +137,8 @@ namespace VNLib.Hashing
/// <param name="type">The hash algorithm to use</param>
/// <returns>The number of bytes written to the buffer, <see cref="ERRNO.E_FAIL"/> if the hash could not be computed</returns>
/// <exception cref="ArgumentException"></exception>
- public static ERRNO ComputeHash(ReadOnlySpan<byte> data, Span<byte> output, HashAlg type)
- {
- //hash the buffer
- return type switch
- {
- HashAlg.BlAKE2B => ComputeHashInternal(in _blake2bAlg, data, output),
- HashAlg.SHA512 => ComputeHashInternal(in _sha512Alg, data, output),
- HashAlg.SHA384 => ComputeHashInternal(in _sha384Alg, data, output),
- HashAlg.SHA256 => ComputeHashInternal(in _sha256Alg, data, output),
- HashAlg.SHA1 => ComputeHashInternal(in _sha1Alg, data, output),
- HashAlg.MD5 => ComputeHashInternal(in _md5Alg, data, output),
- _ => throw new ArgumentException("Hash algorithm is not supported"),
- };
- }
+ public static ERRNO ComputeHash(ReadOnlySpan<byte> data, Span<byte> output, HashAlg type)
+ => ComputeHashInternal(type, data, output);
/// <summary>
/// Hashes the data parameter to the output buffer using the specified algorithm type
@@ -157,20 +147,8 @@ namespace VNLib.Hashing
/// <param name="type">The hash algorithm to use</param>
/// <returns>A byte array that contains the hash of the data buffer</returns>
/// <exception cref="ArgumentException"></exception>
- public static byte[] ComputeHash(ReadOnlySpan<byte> data, HashAlg type)
- {
- //hash the buffer
- return type switch
- {
- HashAlg.BlAKE2B => ComputeHashInternal(in _blake2bAlg, data),
- HashAlg.SHA512 => ComputeHashInternal(in _sha512Alg, data),
- HashAlg.SHA384 => ComputeHashInternal(in _sha384Alg, data),
- HashAlg.SHA256 => ComputeHashInternal(in _sha256Alg, data),
- HashAlg.SHA1 => ComputeHashInternal(in _sha1Alg, data),
- HashAlg.MD5 => ComputeHashInternal(in _md5Alg, data),
- _ => throw new ArgumentException("Invalid hash algorithm", nameof(type))
- };
- }
+ public static byte[] ComputeHash(ReadOnlySpan<byte> data, HashAlg type)
+ => ComputeHashInternal(type, data);
/// <summary>
/// Hashes the data parameter to the output buffer using the specified algorithm type
@@ -183,18 +161,7 @@ namespace VNLib.Hashing
/// <exception cref="OutOfMemoryException"></exception>
/// <exception cref="CryptographicException"></exception>
public static string ComputeHash(ReadOnlySpan<byte> data, HashAlg type, HashEncodingMode mode)
- {
- return type switch
- {
- HashAlg.BlAKE2B => ComputeHashInternal(in _blake2bAlg, data, mode),
- HashAlg.SHA512 => ComputeHashInternal(in _sha512Alg, data, mode),
- HashAlg.SHA384 => ComputeHashInternal(in _sha384Alg, data, mode),
- HashAlg.SHA256 => ComputeHashInternal(in _sha256Alg, data, mode),
- HashAlg.SHA1 => ComputeHashInternal(in _sha1Alg, data, mode),
- HashAlg.MD5 => ComputeHashInternal(in _md5Alg, data, mode),
- _ => throw new ArgumentException("Invalid hash algorithm", nameof(type))
- };
- }
+ => ComputeHashInternal(type, data, mode);
/// <summary>
/// Uses the UTF8 character encoding to encode the string, then computes the hash and encodes
@@ -208,18 +175,7 @@ namespace VNLib.Hashing
/// <exception cref="OutOfMemoryException"></exception>
/// <exception cref="CryptographicException"></exception>
public static string ComputeHash(ReadOnlySpan<char> data, HashAlg type, HashEncodingMode mode)
- {
- return type switch
- {
- HashAlg.BlAKE2B => ComputeHashInternal(in _blake2bAlg, data, mode),
- HashAlg.SHA512 => ComputeHashInternal(in _sha512Alg, data, mode),
- HashAlg.SHA384 => ComputeHashInternal(in _sha384Alg, data, mode),
- HashAlg.SHA256 => ComputeHashInternal(in _sha256Alg, data, mode),
- HashAlg.SHA1 => ComputeHashInternal(in _sha1Alg, data, mode),
- HashAlg.MD5 => ComputeHashInternal(in _md5Alg, data, mode),
- _ => throw new ArgumentException("Invalid hash algorithm", nameof(type))
- };
- }
+ => ComputeHashInternal(type, data, mode);
/// <summary>
/// Computes the HMAC of the specified character buffer using the specified key and
@@ -231,19 +187,8 @@ namespace VNLib.Hashing
/// <param name="type">The <see cref="HashAlg"/> type used to compute the HMAC</param>
/// <returns>The number of bytes written to the ouput buffer or <see cref="ERRNO.E_FAIL"/> if the operation failed</returns>
/// <exception cref="ArgumentException"></exception>
- public static ERRNO ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<char> data, Span<byte> output, HashAlg type)
- {
- return type switch
- {
- HashAlg.BlAKE2B => ComputeHashInternal(in _blake2bAlg, data, output, key),
- HashAlg.SHA512 => ComputeHashInternal(in _sha512Alg, data, output, key),
- HashAlg.SHA384 => ComputeHashInternal(in _sha384Alg, data, output, key),
- HashAlg.SHA256 => ComputeHashInternal(in _sha256Alg, data, output, key),
- HashAlg.SHA1 => ComputeHashInternal(in _sha1Alg, data, output, key),
- HashAlg.MD5 => ComputeHashInternal(in _md5Alg, data, output, key),
- _ => ERRNO.E_FAIL
- };
- }
+ public static ERRNO ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<char> data, Span<byte> output, HashAlg type)
+ => ComputeHashInternal(type, data, output, key);
/// <summary>
/// Computes the HMAC of the specified character buffer using the specified key and
@@ -254,19 +199,8 @@ namespace VNLib.Hashing
/// <param name="type">The <see cref="HashAlg"/> type used to compute the HMAC</param>
/// <returns>A buffer containg the computed HMAC</returns>
/// <exception cref="ArgumentException"></exception>
- public static byte[] ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<char> data, HashAlg type)
- {
- return type switch
- {
- HashAlg.BlAKE2B => ComputeHashInternal(in _blake2bAlg, data, key),
- HashAlg.SHA512 => ComputeHashInternal(in _sha512Alg, data, key),
- HashAlg.SHA384 => ComputeHashInternal(in _sha384Alg, data, key),
- HashAlg.SHA256 => ComputeHashInternal(in _sha256Alg, data, key),
- HashAlg.SHA1 => ComputeHashInternal(in _sha1Alg, data, key),
- HashAlg.MD5 => ComputeHashInternal(in _md5Alg, data, key),
- _ => throw new ArgumentException("Hash algorithm is not supported"),
- };
- }
+ public static byte[] ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<char> data, HashAlg type)
+ => ComputeHashInternal(type, data, key);
/// <summary>
/// Computes the HMAC of the specified data buffer using the specified key and
@@ -279,19 +213,7 @@ namespace VNLib.Hashing
/// <returns>The number of bytes written to the ouput buffer or <see cref="ERRNO.E_FAIL"/> if the operation failed</returns>
/// <exception cref="ArgumentException"></exception>
public static ERRNO ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, Span<byte> output, HashAlg type)
- {
- //hash the buffer
- return type switch
- {
- HashAlg.BlAKE2B => ComputeHashInternal(in _blake2bAlg, data, output, key),
- HashAlg.SHA512 => ComputeHashInternal(in _sha512Alg, data, output, key),
- HashAlg.SHA384 => ComputeHashInternal(in _sha384Alg, data, output, key),
- HashAlg.SHA256 => ComputeHashInternal(in _sha256Alg, data, output, key),
- HashAlg.SHA1 => ComputeHashInternal(in _sha1Alg, data, output, key),
- HashAlg.MD5 => ComputeHashInternal(in _md5Alg, data, output, key),
- _ => throw new ArgumentException("Hash algorithm is not supported"),
- };
- }
+ => ComputeHashInternal(type, data, output, key);
/// <summary>
/// Computes the HMAC of the specified data buffer using the specified key and
@@ -302,20 +224,8 @@ namespace VNLib.Hashing
/// <param name="type">The <see cref="HashAlg"/> type used to compute the HMAC</param>
/// <returns>A buffer containg the computed HMAC</returns>
/// <exception cref="ArgumentException"></exception>
- public static byte[] ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, HashAlg type)
- {
- //hash the buffer
- return type switch
- {
- HashAlg.BlAKE2B => ComputeHashInternal(in _blake2bAlg, data, key),
- HashAlg.SHA512 => ComputeHashInternal(in _sha512Alg, data, key),
- HashAlg.SHA384 => ComputeHashInternal(in _sha384Alg, data, key),
- HashAlg.SHA256 => ComputeHashInternal(in _sha256Alg, data, key),
- HashAlg.SHA1 => ComputeHashInternal(in _sha1Alg, data, key),
- HashAlg.MD5 => ComputeHashInternal(in _md5Alg, data, key),
- _ => throw new ArgumentException("Hash algorithm is not supported"),
- };
- }
+ public static byte[] ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, HashAlg type)
+ => ComputeHashInternal(type, data, key);
/// <summary>
/// Computes the HMAC of the specified data buffer and encodes the result in
@@ -328,18 +238,7 @@ namespace VNLib.Hashing
/// <returns>The encoded string of the result</returns>
/// <exception cref="ArgumentException"></exception>
public static string ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, HashAlg type, HashEncodingMode mode)
- {
- return type switch
- {
- HashAlg.BlAKE2B => ComputeHashInternal(in _blake2bAlg, data, mode, key),
- HashAlg.SHA512 => ComputeHashInternal(in _sha512Alg, data, mode, key),
- HashAlg.SHA384 => ComputeHashInternal(in _sha384Alg, data, mode, key),
- HashAlg.SHA256 => ComputeHashInternal(in _sha256Alg, data, mode, key),
- HashAlg.SHA1 => ComputeHashInternal(in _sha1Alg, data, mode, key),
- HashAlg.MD5 => ComputeHashInternal(in _md5Alg, data, mode, key),
- _ => throw new ArgumentException("Invalid hash algorithm", nameof(type))
- };
- }
+ => ComputeHashInternal(type, data, mode, key);
/// <summary>
/// Computes the HMAC of the specified data buffer and encodes the result in
@@ -351,115 +250,137 @@ namespace VNLib.Hashing
/// <param name="mode">The encoding type for the output data</param>
/// <returns>The encoded string of the result</returns>
/// <exception cref="ArgumentException"></exception>
- public static string ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<char> data, HashAlg type, HashEncodingMode mode)
- {
- return type switch
- {
- HashAlg.BlAKE2B => ComputeHashInternal(in _blake2bAlg, data, mode, key),
- HashAlg.SHA512 => ComputeHashInternal(in _sha512Alg, data, mode, key),
- HashAlg.SHA384 => ComputeHashInternal(in _sha384Alg, data, mode, key),
- HashAlg.SHA256 => ComputeHashInternal(in _sha256Alg, data, mode, key),
- HashAlg.SHA1 => ComputeHashInternal(in _sha1Alg, data, mode, key),
- HashAlg.MD5 => ComputeHashInternal(in _md5Alg, data, mode, key),
- _ => throw new ArgumentException("Invalid hash algorithm", nameof(type))
- };
- }
+ public static string ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<char> data, HashAlg type, HashEncodingMode mode)
+ => ComputeHashInternal(type, data, mode, key);
#region internal
- private static byte[] ComputeHashInternal<T>(in T algorithm, ReadOnlySpan<char> data, ReadOnlySpan<byte> key = default) where T : IHashAlgorithm
+
+ private static byte[] ComputeHashInternal(HashAlg alg, ReadOnlySpan<char> data, ReadOnlySpan<byte> key = default)
+ {
+ //Alloc output buffer
+ byte[] output = new byte[HashSize(alg)];
+
+ //Hash data
+ ERRNO result = ComputeHashInternal(alg, data, output, key);
+ Debug.Assert(result == HashSize(alg), $"Failed to compute hash using {alg} of size {output.Length}");
+
+ return output;
+ }
+
+ private static ERRNO ComputeHashInternal(HashAlg alg, ReadOnlySpan<char> data, Span<byte> output, ReadOnlySpan<byte> key = default)
{
int byteCount = CharEncoding.GetByteCount(data);
//Alloc buffer
using UnsafeMemoryHandle<byte> binbuf = MemoryUtil.UnsafeAlloc(byteCount, true);
//Encode data
byteCount = CharEncoding.GetBytes(data, binbuf.Span);
- //hash the buffer
- return ComputeHashInternal(in algorithm, binbuf.AsSpan(0, byteCount), key);
+ //hash the buffer or hmac if key is not empty
+ return ComputeHashInternal(alg, binbuf.Span[..byteCount], output, key);
}
- private static string ComputeHashInternal<T>(in T algorithm, ReadOnlySpan<char> data, HashEncodingMode mode, ReadOnlySpan<byte> key = default) where T : IHashAlgorithm
+ private static string ComputeHashInternal(HashAlg alg, ReadOnlySpan<char> data, HashEncodingMode mode, ReadOnlySpan<byte> key = default)
{
//Alloc stack buffer to store hash output
- Span<byte> hashBuffer = stackalloc byte[algorithm.HashSize];
+ Span<byte> hashBuffer = stackalloc byte[HashSize(alg)];
+
//hash the buffer
- ERRNO count = ComputeHashInternal(in algorithm, data, hashBuffer, key);
- if (!count)
- {
- throw new CryptographicException("Failed to compute the hash of the data");
- }
+ ERRNO count = ComputeHashInternal(alg, data, hashBuffer, key);
+
+ //Count should always be the same as the hash size, this should never fail
+ Debug.Assert(count == HashSize(alg), $"Failed to compute hash using {alg} of size {hashBuffer.Length}");
//Convert to encoded string
return mode switch
{
- HashEncodingMode.Hexadecimal => Convert.ToHexString(hashBuffer.Slice(0, count)),
- HashEncodingMode.Base64 => Convert.ToBase64String(hashBuffer.Slice(0, count)),
- HashEncodingMode.Base32 => VnEncoding.ToBase32String(hashBuffer.Slice(0, count)),
- HashEncodingMode.Base64Url => VnEncoding.ToBase64UrlSafeString(hashBuffer.Slice(0, count), true),
+ HashEncodingMode.Hexadecimal => Convert.ToHexString(hashBuffer),
+ HashEncodingMode.Base64 => Convert.ToBase64String(hashBuffer),
+ HashEncodingMode.Base32 => VnEncoding.ToBase32String(hashBuffer),
+ HashEncodingMode.Base64Url => VnEncoding.ToBase64UrlSafeString(hashBuffer, true),
_ => throw new ArgumentException("Encoding mode is not supported"),
};
}
- private static string ComputeHashInternal<T>(in T algorithm, ReadOnlySpan<byte> data, HashEncodingMode mode, ReadOnlySpan<byte> key = default) where T : IHashAlgorithm
+ private static string ComputeHashInternal(HashAlg alg, ReadOnlySpan<byte> data, HashEncodingMode mode, ReadOnlySpan<byte> key = default)
{
//Alloc stack buffer to store hash output
- Span<byte> hashBuffer = stackalloc byte[algorithm.HashSize];
+ Span<byte> hashBuffer = stackalloc byte[HashSize(alg)];
//hash the buffer
- ERRNO count = ComputeHashInternal(in algorithm, data, hashBuffer, key);
- if (!count)
- {
- throw new CryptographicException("Failed to compute the hash of the data");
- }
+ ERRNO count = ComputeHashInternal(alg, data, hashBuffer, key);
+
+ //Count should always be the same as the hash size, this should never fail
+ Debug.Assert(count == HashSize(alg), $"Failed to compute hash using {alg} of size {hashBuffer.Length}");
//Convert to encoded string
return mode switch
{
- HashEncodingMode.Hexadecimal => Convert.ToHexString(hashBuffer.Slice(0, count)),
- HashEncodingMode.Base64 => Convert.ToBase64String(hashBuffer.Slice(0, count)),
- HashEncodingMode.Base32 => VnEncoding.ToBase32String(hashBuffer.Slice(0, count)),
- HashEncodingMode.Base64Url => VnEncoding.ToBase64UrlSafeString(hashBuffer.Slice(0, count), true),
+ HashEncodingMode.Hexadecimal => Convert.ToHexString(hashBuffer),
+ HashEncodingMode.Base64 => Convert.ToBase64String(hashBuffer),
+ HashEncodingMode.Base32 => VnEncoding.ToBase32String(hashBuffer),
+ HashEncodingMode.Base64Url => VnEncoding.ToBase64UrlSafeString(hashBuffer, true),
_ => throw new ArgumentException("Encoding mode is not supported"),
};
}
- private static ERRNO ComputeHashInternal<T>(in T algorithm, ReadOnlySpan<char> data, Span<byte> output, ReadOnlySpan<byte> key = default) where T : IHashAlgorithm
+
+ private static byte[] ComputeHashInternal(HashAlg alg, ReadOnlySpan<byte> data, ReadOnlySpan<byte> key = default)
{
- int byteCount = CharEncoding.GetByteCount(data);
- //Alloc buffer
- using UnsafeMemoryHandle<byte> binbuf = MemoryUtil.UnsafeAlloc(byteCount, true);
- //Encode data
- byteCount = CharEncoding.GetBytes(data, binbuf.Span);
- //hash the buffer or hmac if key is not empty
- return ComputeHashInternal(in algorithm, binbuf.Span[..byteCount], output, key);
+ //Alloc output buffer
+ byte[] output = new byte[HashSize(alg)];
+
+ //Hash data
+ ERRNO result = ComputeHashInternal(alg, data, output, key);
+ Debug.Assert(result == HashSize(alg), $"Failed to compute hash using {alg} of size {output.Length}");
+
+ return output;
}
-
- private static ERRNO ComputeHashInternal<T>(in T algorithm, ReadOnlySpan<byte> data, Span<byte> buffer, ReadOnlySpan<byte> key = default) where T : IHashAlgorithm
+ private static int HashSize(HashAlg alg) => alg switch
{
- //hash the buffer or hmac if key is not empty
- if (key.IsEmpty)
- {
- return algorithm.TryComputeHash(data, buffer, out int written) ? written : ERRNO.E_FAIL;
- }
- else
- {
- return algorithm.TryComputeHmac(key, data, buffer, out int written) ? written : ERRNO.E_FAIL;
- }
- }
-
- private static byte[] ComputeHashInternal<T>(in T algorithm, ReadOnlySpan<byte> data, ReadOnlySpan<byte> key = default) where T : IHashAlgorithm
+ HashAlg.SHA3_512 => _3_sha512.HashSize,
+ HashAlg.SHA3_384 => _3_sha384.HashSize,
+ HashAlg.SHA3_256 => _3_sha256.HashSize,
+ HashAlg.BlAKE2B => _blake2bAlg.HashSize,
+ HashAlg.SHA512 => _sha512Alg.HashSize,
+ HashAlg.SHA384 => _sha384Alg.HashSize,
+ HashAlg.SHA256 => _sha256Alg.HashSize,
+ HashAlg.SHA1 => _sha1Alg.HashSize,
+ HashAlg.MD5 => _md5Alg.HashSize,
+ _ => throw new ArgumentException("Invalid hash algorithm", nameof(alg))
+ };
+
+
+ private static ERRNO ComputeHashInternal(HashAlg alg, ReadOnlySpan<byte> data, Span<byte> buffer, ReadOnlySpan<byte> key = default)
{
- //hash the buffer or hmac if key is not empty
- if (key.IsEmpty)
+ return alg switch
{
- return algorithm.ComputeHash(data);
- }
- else
+ HashAlg.SHA3_512 => computeHashInternal(in _3_sha512, data, buffer, key),
+ HashAlg.SHA3_384 => computeHashInternal(in _3_sha384, data, buffer, key),
+ HashAlg.SHA3_256 => computeHashInternal(in _3_sha256, data, buffer, key),
+ HashAlg.BlAKE2B => computeHashInternal(in _blake2bAlg, data, buffer, key),
+ HashAlg.SHA512 => computeHashInternal(in _sha512Alg, data, buffer, key),
+ HashAlg.SHA384 => computeHashInternal(in _sha384Alg, data, buffer, key),
+ HashAlg.SHA256 => computeHashInternal(in _sha256Alg, data, buffer, key),
+ HashAlg.SHA1 => computeHashInternal(in _sha1Alg, data, buffer, key),
+ HashAlg.MD5 => computeHashInternal(in _md5Alg, data, buffer, key),
+ _ => throw new ArgumentException("Invalid hash algorithm", nameof(alg))
+ };
+
+ static ERRNO computeHashInternal<T>(in T algorithm, ReadOnlySpan<byte> data, Span<byte> buffer, ReadOnlySpan<byte> key = default)
+ where T : IHashAlgorithm
{
- return algorithm.ComputeHmac(key, data);
+ //hash the buffer or hmac if key is not empty
+ if (key.IsEmpty)
+ {
+ return algorithm.TryComputeHash(data, buffer, out int written) ? written : ERRNO.E_FAIL;
+ }
+ else
+ {
+ return algorithm.TryComputeHmac(key, data, buffer, out int written) ? written : ERRNO.E_FAIL;
+ }
}
- }
+ }
#endregion
}
diff --git a/lib/Hashing.Portable/src/ManagedHashAlgImpl.cs b/lib/Hashing.Portable/src/ManagedHashAlgImpl.cs
index 7e2262e..d53152e 100644
--- a/lib/Hashing.Portable/src/ManagedHashAlgImpl.cs
+++ b/lib/Hashing.Portable/src/ManagedHashAlgImpl.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Hashing.Portable
@@ -23,7 +23,6 @@
*/
using System;
-using System.Diagnostics;
using System.Security.Cryptography;
using VNLib.Utils;
@@ -37,12 +36,8 @@ namespace VNLib.Hashing
{
int HashSize { get; }
- byte[] ComputeHash(ReadOnlySpan<byte> data);
-
bool TryComputeHash(ReadOnlySpan<byte> data, Span<byte> output, out int count);
- byte[] ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data);
-
bool TryComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, Span<byte> output, out int count);
}
@@ -50,13 +45,10 @@ namespace VNLib.Hashing
{
///<inheritdoc/>
public readonly int HashSize => (int)HashAlg.SHA1;
- ///<inheritdoc/>
- public readonly byte[] ComputeHash(ReadOnlySpan<byte> data) => SHA1.HashData(data);
+
///<inheritdoc/>
public readonly bool TryComputeHash(ReadOnlySpan<byte> data, Span<byte> output, out int count) => SHA1.TryHashData(data, output, out count);
-
- ///<inheritdoc/>
- public readonly byte[] ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data) => HMACSHA1.HashData(key, data);
+
///<inheritdoc/>
public readonly bool TryComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, Span<byte> output, out int count) => HMACSHA1.TryHashData(key, data, output, out count);
}
@@ -67,15 +59,9 @@ namespace VNLib.Hashing
public readonly int HashSize => (int)HashAlg.SHA256;
///<inheritdoc/>
- public readonly byte[] ComputeHash(ReadOnlySpan<byte> data) => SHA256.HashData(data);
-
- ///<inheritdoc/>
public readonly bool TryComputeHash(ReadOnlySpan<byte> data, Span<byte> output, out int count) => SHA256.TryHashData(data, output, out count);
///<inheritdoc/>
- public readonly byte[] ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data) => HMACSHA256.HashData(key, data);
-
- ///<inheritdoc/>
public readonly bool TryComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, Span<byte> output, out int count) => HMACSHA256.TryHashData(key, data, output, out count);
}
@@ -83,15 +69,11 @@ namespace VNLib.Hashing
{
///<inheritdoc/>
public readonly int HashSize => (int)HashAlg.SHA384;
- ///<inheritdoc/>
- public readonly byte[] ComputeHash(ReadOnlySpan<byte> data) => SHA384.HashData(data);
+
///<inheritdoc/>
public readonly bool TryComputeHash(ReadOnlySpan<byte> data, Span<byte> output, out int count) => SHA384.TryHashData(data, output, out count);
///<inheritdoc/>
- public readonly byte[] ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data) => HMACSHA384.HashData(key, data);
-
- ///<inheritdoc/>
public readonly bool TryComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, Span<byte> output, out int count) => HMACSHA384.TryHashData(key, data, output, out count);
}
@@ -99,13 +81,10 @@ namespace VNLib.Hashing
{
///<inheritdoc/>
public readonly int HashSize => (int)HashAlg.SHA512;
- ///<inheritdoc/>
- public readonly byte[] ComputeHash(ReadOnlySpan<byte> data) => SHA512.HashData(data);
+
///<inheritdoc/>
public readonly bool TryComputeHash(ReadOnlySpan<byte> data, Span<byte> output, out int count) => SHA512.TryHashData(data, output, out count);
-
- ///<inheritdoc/>
- public readonly byte[] ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data) => HMACSHA512.HashData(key, data);
+
///<inheritdoc/>
public readonly bool TryComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, Span<byte> output, out int count) => HMACSHA512.TryHashData(key, data, output, out count);
}
@@ -114,63 +93,65 @@ namespace VNLib.Hashing
{
///<inheritdoc/>
public readonly int HashSize => (int)HashAlg.MD5;
- ///<inheritdoc/>
- public readonly byte[] ComputeHash(ReadOnlySpan<byte> data) => MD5.HashData(data);
+
///<inheritdoc/>
public readonly bool TryComputeHash(ReadOnlySpan<byte> data, Span<byte> output, out int count) => MD5.TryHashData(data, output, out count);
-
- ///<inheritdoc/>
- public readonly byte[] ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data) => HMACMD5.HashData(key, data);
+
///<inheritdoc/>
public readonly bool TryComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, Span<byte> output, out int count) => HMACMD5.TryHashData(key, data, output, out count);
}
- private readonly struct Blake2b : IHashAlgorithm
+ private readonly struct Sha3_256 : IHashAlgorithm
{
- const byte DefaultBlake2HashSize = 64;
-
- internal static int MaxHashSize => MCBlake2Module.MaxHashSize;
- internal static int MaxKeySize => MCBlake2Module.MaxKeySize;
+ public static bool IsSupported => SHA3_256.IsSupported;
///<inheritdoc/>
- public readonly int HashSize => DefaultBlake2HashSize;
-
+ public readonly int HashSize => (int)HashAlg.SHA256;
+
///<inheritdoc/>
- public readonly byte[] ComputeHash(ReadOnlySpan<byte> data)
- {
- //Stack buffer for output hash
- byte[] output = new byte[DefaultBlake2HashSize];
+ public readonly bool TryComputeHash(ReadOnlySpan<byte> data, Span<byte> output, out int count) => SHA3_256.TryHashData(data, output, out count);
+
+ ///<inheritdoc/>
+ public readonly bool TryComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, Span<byte> output, out int count) => HMACSHA3_256.TryHashData(key, data, output, out count);
+ }
- if (!TryComputeHash(data, output, out int count))
- {
- throw new ArgumentException("Failed to compute Blake2 hash of desired data");
- }
+ private readonly struct Sha3_384 : IHashAlgorithm
+ {
+ public static bool IsSupported => SHA3_384.IsSupported;
- //Count must be exact same (sanity check)
- Debug.Assert(count == DefaultBlake2HashSize);
+ ///<inheritdoc/>
+ public readonly int HashSize => (int)HashAlg.SHA384;
+
+ ///<inheritdoc/>
+ public readonly bool TryComputeHash(ReadOnlySpan<byte> data, Span<byte> output, out int count) => SHA3_384.TryHashData(data, output, out count);
+
+ ///<inheritdoc/>
+ public readonly bool TryComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, Span<byte> output, out int count) => HMACSHA3_384.TryHashData(key, data, output, out count);
+ }
- //Return the hash as a new array
- return output;
- }
+ private readonly struct Sha3_512 : IHashAlgorithm
+ {
+ public static bool IsSupported => SHA3_512.IsSupported;
///<inheritdoc/>
- public readonly byte[] ComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data)
- {
- //Alloc output buffer
- byte[] output = new byte[DefaultBlake2HashSize];
-
- if (!TryComputeHmac(key, data, output, out int count))
- {
- throw new ArgumentException("Failed to compute Blake2 hash of desired data");
- }
+ public readonly int HashSize => (int)HashAlg.SHA512;
+
+ ///<inheritdoc/>
+ public readonly bool TryComputeHash(ReadOnlySpan<byte> data, Span<byte> output, out int count) => SHA3_512.TryHashData(data, output, out count);
+
+ ///<inheritdoc/>
+ public readonly bool TryComputeHmac(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, Span<byte> output, out int count) => HMACSHA3_512.TryHashData(key, data, output, out count);
+ }
- //Count must be exact same (sanity check)
- Debug.Assert(count == DefaultBlake2HashSize);
+ private readonly struct Blake2b : IHashAlgorithm
+ {
+ const byte DefaultBlake2HashSize = 64;
- //Return the hash as a new array
- return output;
+ internal static int MaxHashSize => MCBlake2Module.MaxHashSize;
+ internal static int MaxKeySize => MCBlake2Module.MaxKeySize;
- }
+ ///<inheritdoc/>
+ public readonly int HashSize => DefaultBlake2HashSize;
///<inheritdoc/>
public readonly bool TryComputeHash(ReadOnlySpan<byte> data, Span<byte> output, out int count)
diff --git a/lib/Hashing.Portable/tests/ManagedHashTests.cs b/lib/Hashing.Portable/tests/ManagedHashTests.cs
index 01b3336..8b2a3c3 100644
--- a/lib/Hashing.Portable/tests/ManagedHashTests.cs
+++ b/lib/Hashing.Portable/tests/ManagedHashTests.cs
@@ -4,6 +4,7 @@ using System.Text;
using VNLib.Utils.Memory;
using VNLib.Utils;
+using System.Diagnostics;
namespace VNLib.Hashing.Tests
@@ -17,6 +18,9 @@ namespace VNLib.Hashing.Tests
byte[] testData = Encoding.UTF8.GetBytes("Hello World!");
using UnsafeMemoryHandle<byte> heapBuffer = MemoryUtil.UnsafeAlloc(64, false);
+ Trace.WriteLineIf(ManagedHash.SupportsSha3, "SHA3 is supported");
+ Trace.WriteLineIf(ManagedHash.SupportsBlake2b, "Blake2b is supported");
+
//Test all supported algorithms
foreach (HashAlg alg in Enum.GetValues<HashAlg>())
{
@@ -25,6 +29,17 @@ namespace VNLib.Hashing.Tests
//Skip unsupported algorithms
if (alg == HashAlg.BlAKE2B && !ManagedHash.SupportsBlake2b) continue;
+ if (!ManagedHash.SupportsSha3)
+ {
+ switch (alg)
+ {
+ case HashAlg.SHA3_256:
+ case HashAlg.SHA3_384:
+ case HashAlg.SHA3_512:
+ continue;
+ }
+ }
+
//Compute hash
ERRNO hashSize = ManagedHash.ComputeHash(testData, heapBuffer.Span, alg);
Assert.IsTrue(hashSize == Math.Abs(hashSize));
@@ -58,6 +73,9 @@ namespace VNLib.Hashing.Tests
byte[] testKey = RandomHash.GetRandomBytes(32);
using UnsafeMemoryHandle<byte> heapBuffer = MemoryUtil.UnsafeAlloc(64, false);
+ Trace.WriteLineIf(ManagedHash.SupportsSha3, "SHA3 is supported");
+ Trace.WriteLineIf(ManagedHash.SupportsBlake2b, "Blake2b is supported");
+
//Test all supported algorithms
foreach (HashAlg alg in Enum.GetValues<HashAlg>())
{
@@ -66,6 +84,17 @@ namespace VNLib.Hashing.Tests
//Skip unsupported algorithms
if (alg == HashAlg.BlAKE2B && !ManagedHash.SupportsBlake2b) continue;
+ if (!ManagedHash.SupportsSha3)
+ {
+ switch (alg)
+ {
+ case HashAlg.SHA3_256:
+ case HashAlg.SHA3_384:
+ case HashAlg.SHA3_512:
+ continue;
+ }
+ }
+
//Compute hash
ERRNO hashSize = ManagedHash.ComputeHmac(testKey, testData, heapBuffer.Span, alg);
Assert.IsTrue(hashSize == Math.Abs(hashSize));
diff --git a/lib/Net.Compression/vnlib_compress/CMakeLists.txt b/lib/Net.Compression/vnlib_compress/CMakeLists.txt
index a5dfaa3..2eb234e 100644
--- a/lib/Net.Compression/vnlib_compress/CMakeLists.txt
+++ b/lib/Net.Compression/vnlib_compress/CMakeLists.txt
@@ -11,7 +11,7 @@ set(VNLIB_COMPRESS_SOURCES compression.c)
#set options for enable botli and zlib
option(ENABLE_BROTLI "Enable brotli compression" ON)
option(ENABLE_ZLIB "Enable zlib compression" ON)
-option(ENABLE_RPMALLOC "Link local vnlib_rpmalloc allocator" OFF)
+option(ENABLE_RPMALLOC "Enable local source code vnlib_rpmalloc memory allocator" OFF)
#add feature specific source files to the project
if(ENABLE_BROTLI)
@@ -33,7 +33,7 @@ add_library(${CMAKE_PROJECT_NAME}_static STATIC ${VNLIB_COMPRESS_SOURCES} ${COMP
#if on unix lib will be appended, so we can adjust
if(UNIX)
- set_target_properties(${CMAKE_PROJECT_NAME} ${CMAKE_PROJECT_NAME}_static PROPERTIES OUTPUT_NAME _vncompress)
+ set_target_properties(${CMAKE_PROJECT_NAME} ${CMAKE_PROJECT_NAME}_static PROPERTIES OUTPUT_NAME vn_compress)
endif()
@@ -281,6 +281,22 @@ if(ENABLE_ZLIB)
target_link_libraries(${CMAKE_PROJECT_NAME} lib_deflate)
endif()
+if(NATIVE_HEAP_LIB_PATH)
+
+ #Include the nativeheap api header
+ include_directories(${NATIVE_HEAP_INCLUDES})
+
+ #If manual heap linking is enabled, we need to link the native heap library
+ target_link_libraries(${CMAKE_PROJECT_NAME} ${NATIVE_HEAP_LIB_PATH})
+
+ #Disable rpmalloc if we are linking a custom native heap
+ set(ENABLE_RPMALLOC OFF)
+
+ #add defintion to enable custom malloc heap overrides
+ target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE VNLIB_CUSTOM_MALLOC_ENABLE)
+
+endif()
+
#Add support for rpmalloc memmory allocator
if(ENABLE_RPMALLOC)
diff --git a/lib/Net.Http/src/Core/HttpServerBase.cs b/lib/Net.Http/src/Core/HttpServerBase.cs
index ec42e5b..a73867f 100644
--- a/lib/Net.Http/src/Core/HttpServerBase.cs
+++ b/lib/Net.Http/src/Core/HttpServerBase.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Net.Http
@@ -36,10 +36,10 @@
*/
using System;
-using System.Linq;
using System.Threading;
using System.Net.Sockets;
using System.Threading.Tasks;
+using System.Collections.Frozen;
using System.Collections.Generic;
using System.Security.Authentication;
@@ -76,7 +76,7 @@ namespace VNLib.Net.Http
internal static readonly Memory<byte> WriteOnlyScratchBuffer = new byte[64 * 1024];
private readonly ITransportProvider Transport;
- private readonly IReadOnlyDictionary<string, IWebRoot> ServerRoots;
+ private readonly FrozenDictionary<string, IWebRoot> ServerRoots;
private readonly IWebRoot? _wildcardRoot;
private readonly HttpConfig _config;
@@ -139,7 +139,7 @@ namespace VNLib.Net.Http
_config = config;
//Configure roots and their directories
- ServerRoots = sites.ToDictionary(static r => r.Hostname, static tv => tv, StringComparer.OrdinalIgnoreCase);
+ ServerRoots = sites.ToFrozenDictionary(static r => r.Hostname, static tv => tv, StringComparer.OrdinalIgnoreCase);
//Compile and store the timeout keepalive header
KeepAliveTimeoutHeaderValue = $"timeout={(int)_config.ConnectionKeepAlive.TotalSeconds}";
//Create a new context store
@@ -164,9 +164,9 @@ namespace VNLib.Net.Http
private static void ValidateConfig(in HttpConfig conf)
{
- _ = conf.HttpEncoding ?? throw new ArgumentException("HttpEncoding cannot be null", nameof(conf));
- _ = conf.ServerLog ?? throw new ArgumentException("ServerLog cannot be null", nameof(conf));
- _ = conf.MemoryPool ?? throw new ArgumentNullException(nameof(conf));
+ ArgumentNullException.ThrowIfNull(conf.HttpEncoding, nameof(conf.HttpEncoding));
+ ArgumentNullException.ThrowIfNull(conf.ServerLog, nameof(conf.ServerLog));
+ ArgumentNullException.ThrowIfNull(conf.MemoryPool, nameof(conf.MemoryPool));
if (conf.ActiveConnectionRecvTimeout < -1)
{
diff --git a/lib/Net.Http/src/Core/HttpServerProcessing.cs b/lib/Net.Http/src/Core/HttpServerProcessing.cs
index 61adbbc..4595f3e 100644
--- a/lib/Net.Http/src/Core/HttpServerProcessing.cs
+++ b/lib/Net.Http/src/Core/HttpServerProcessing.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Net.Http
diff --git a/lib/Net.Http/src/Core/InitDataBuffer.cs b/lib/Net.Http/src/Core/InitDataBuffer.cs
index 323208a..4d215d9 100644
--- a/lib/Net.Http/src/Core/InitDataBuffer.cs
+++ b/lib/Net.Http/src/Core/InitDataBuffer.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Net.Http
@@ -87,7 +87,7 @@ namespace VNLib.Net.Http.Core
get => MemoryMarshal.Read<int>(_positionSegment);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set => MemoryMarshal.Write(_positionSegment, ref value);
+ set => MemoryMarshal.Write(_positionSegment, in value);
}
/// <summary>
diff --git a/lib/Net.Http/src/Helpers/HttpHelpers.cs b/lib/Net.Http/src/Helpers/HttpHelpers.cs
index a4486cd..86511a5 100644
--- a/lib/Net.Http/src/Helpers/HttpHelpers.cs
+++ b/lib/Net.Http/src/Helpers/HttpHelpers.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Net.Http
@@ -27,6 +27,7 @@ using System.IO;
using System.Net;
using System.Linq;
using System.Net.Sockets;
+using System.Collections.Frozen;
using System.Collections.Generic;
using System.Text.RegularExpressions;
@@ -66,14 +67,14 @@ namespace VNLib.Net.Http
* an HttpMethod enum value,
*/
- private static readonly IReadOnlyDictionary<int, HttpMethod> MethodHashLookup = HashHttpMethods();
+ private static readonly FrozenDictionary<int, HttpMethod> MethodHashLookup = HashHttpMethods();
/*
* Provides a constant lookup table from an MIME http request header string to a .NET
* enum value (with some extra support)
*/
- private static readonly IReadOnlyDictionary<string, HttpRequestHeader> RequestHeaderLookup = new Dictionary<string, HttpRequestHeader>(StringComparer.OrdinalIgnoreCase)
+ private static readonly FrozenDictionary<string, HttpRequestHeader> RequestHeaderLookup = new Dictionary<string, HttpRequestHeader>(StringComparer.OrdinalIgnoreCase)
{
{"CacheControl", HttpRequestHeader.CacheControl },
{"Connection", HttpRequestHeader.Connection },
@@ -119,7 +120,7 @@ namespace VNLib.Net.Http
//Custom request headers
{ "Content-Disposition", ContentDisposition },
{ "origin", Origin }
- };
+ }.ToFrozenDictionary();
/*
* Provides a lookup table for request header hashcodes (that are hashed in
@@ -128,28 +129,28 @@ namespace VNLib.Net.Http
* during request parsing)
*
*/
- private static readonly IReadOnlyDictionary<int, HttpRequestHeader> RequestHeaderHashLookup = ComputeCodeHashLookup(RequestHeaderLookup);
+ private static readonly FrozenDictionary<int, HttpRequestHeader> RequestHeaderHashLookup = ComputeCodeHashLookup(RequestHeaderLookup);
/*
* Provides a constant lookup table for http version hashcodes to an http
* version enum value
*/
- private static readonly IReadOnlyDictionary<int, HttpVersion> VersionHashLookup = new Dictionary<int, HttpVersion>()
+ private static readonly FrozenDictionary<int, HttpVersion> VersionHashLookup = new Dictionary<int, HttpVersion>()
{
{ string.GetHashCode("HTTP/0.9", StringComparison.OrdinalIgnoreCase), HttpVersion.Http09 },
{ string.GetHashCode("HTTP/1.0", StringComparison.OrdinalIgnoreCase), HttpVersion.Http1 },
{ string.GetHashCode("HTTP/1.1", StringComparison.OrdinalIgnoreCase), HttpVersion.Http11 },
{ string.GetHashCode("HTTP/2.0", StringComparison.OrdinalIgnoreCase), HttpVersion.Http2 }
- };
+ }.ToFrozenDictionary();
//Pre-compiled strings for all status codes for http 0.9 1, 1.1
- private static readonly IReadOnlyDictionary<HttpStatusCode, string> V0_9_STATUS_CODES = GetStatusCodes("0.9");
- private static readonly IReadOnlyDictionary<HttpStatusCode, string> V1_STAUTS_CODES = GetStatusCodes("1.0");
- private static readonly IReadOnlyDictionary<HttpStatusCode, string> V1_1_STATUS_CODES = GetStatusCodes("1.1");
- private static readonly IReadOnlyDictionary<HttpStatusCode, string> V2_STATUS_CODES = GetStatusCodes("2.0");
+ private static readonly FrozenDictionary<HttpStatusCode, string> V0_9_STATUS_CODES = GetStatusCodes("0.9");
+ private static readonly FrozenDictionary<HttpStatusCode, string> V1_STAUTS_CODES = GetStatusCodes("1.0");
+ private static readonly FrozenDictionary<HttpStatusCode, string> V1_1_STATUS_CODES = GetStatusCodes("1.1");
+ private static readonly FrozenDictionary<HttpStatusCode, string> V2_STATUS_CODES = GetStatusCodes("2.0");
- private static IReadOnlyDictionary<HttpStatusCode, string> GetStatusCodes(string version)
+ private static FrozenDictionary<HttpStatusCode, string> GetStatusCodes(string version)
{
//Setup status code dict
Dictionary<HttpStatusCode, string> statusCodes = new();
@@ -159,10 +160,10 @@ namespace VNLib.Net.Http
//Use a regex to write the status code value as a string
statusCodes[code] = $"HTTP/{version} {(int)code} {HttpRequestBuilderRegex.Replace(code.ToString(), " $1")}";
}
- return statusCodes;
+ return statusCodes.ToFrozenDictionary();
}
- private static IReadOnlyDictionary<int, HttpMethod> HashHttpMethods()
+ private static FrozenDictionary<int, HttpMethod> HashHttpMethods()
{
/*
* Http methods are hashed at runtime using the HttpMethod enum
@@ -173,11 +174,11 @@ namespace VNLib.Net.Http
//Exclude the not supported method
.Except(new HttpMethod[] { HttpMethod.None })
.Select(m => KeyValuePair.Create(m.ToString(), m))
- );
+ ).ToFrozenDictionary();
}
- private static IReadOnlyDictionary<int, T> ComputeCodeHashLookup<T>(IEnumerable<KeyValuePair<string, T>> enumerable)
- => enumerable.ToDictionary(
+ private static FrozenDictionary<int, T> ComputeCodeHashLookup<T>(IEnumerable<KeyValuePair<string, T>> enumerable)
+ => enumerable.ToFrozenDictionary(
static kv => string.GetHashCode(kv.Key, StringComparison.OrdinalIgnoreCase),
static kv => kv.Value
);
diff --git a/lib/Net.Http/src/Helpers/MimeLookups.cs b/lib/Net.Http/src/Helpers/MimeLookups.cs
index c0dd82c..ab1aef4 100644
--- a/lib/Net.Http/src/Helpers/MimeLookups.cs
+++ b/lib/Net.Http/src/Helpers/MimeLookups.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Net.Http
@@ -23,6 +23,7 @@
*/
+using System.Collections.Frozen;
using System.Collections.Generic;
namespace VNLib.Net.Http
@@ -30,7 +31,7 @@ namespace VNLib.Net.Http
public static partial class HttpHelpers
{
//Content type lookup dict
- private static readonly IReadOnlyDictionary<ContentType, string> CtToMime = new Dictionary<ContentType, string>()
+ private static readonly FrozenDictionary<ContentType, string> CtToMime = new Dictionary<ContentType, string>()
{
{ ContentType.NonSupported, "application/octet-stream" },
{ ContentType.UrlEncoded, "application/x-www-form-urlencoded" },
@@ -1179,8 +1180,9 @@ namespace VNLib.Net.Http
{ ContentType.Zir, "application/vnd.zul" },
{ ContentType.Zirz, "application/vnd.zul" },
{ ContentType.Zmm, "application/vnd.handheld-entertainment+xml" },
- };
- private static readonly IReadOnlyDictionary<string, ContentType> ExtensionToCt = new Dictionary<string, ContentType>()
+ }.ToFrozenDictionary();
+
+ private static readonly FrozenDictionary<string, ContentType> ExtensionToCt = new Dictionary<string, ContentType>()
{
{ "aab", ContentType.Aab },
{ "aac", ContentType.Aac },
@@ -2327,8 +2329,9 @@ namespace VNLib.Net.Http
{ "zir", ContentType.Zir },
{ "zirz", ContentType.Zirz },
{ "zmm", ContentType.Zmm },
- };
- private static readonly IReadOnlyDictionary<string, ContentType> MimeToCt = new Dictionary<string, ContentType>()
+ }.ToFrozenDictionary();
+
+ private static readonly FrozenDictionary<string, ContentType> MimeToCt = new Dictionary<string, ContentType>()
{
{ "application/x-www-form-urlencoded", ContentType.UrlEncoded },
{ "multipart/form-data", ContentType.MultiPart },
@@ -3230,12 +3233,12 @@ namespace VNLib.Net.Http
{ "application/zip", ContentType.Zip },
{ "application/vnd.zul", ContentType.Zir },
{ "application/vnd.handheld-entertainment+xml", ContentType.Zmm },
- };
+ }.ToFrozenDictionary();
/*
* A string hashcode lookup table for MIME content types
*/
- private static readonly IReadOnlyDictionary<int, ContentType> ContentTypeHashLookup = ComputeCodeHashLookup(MimeToCt);
+ private static readonly FrozenDictionary<int, ContentType> ContentTypeHashLookup = ComputeCodeHashLookup(MimeToCt);
}
}
diff --git a/lib/Plugins.Essentials/src/SemiConsistentVeTable.cs b/lib/Plugins.Essentials/src/SemiConsistentVeTable.cs
index 4849107..a235b13 100644
--- a/lib/Plugins.Essentials/src/SemiConsistentVeTable.cs
+++ b/lib/Plugins.Essentials/src/SemiConsistentVeTable.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Plugins.Essentials
@@ -26,6 +26,7 @@ using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using System.Collections.Frozen;
using System.Collections.Generic;
using VNLib.Net.Http;
@@ -60,7 +61,9 @@ namespace VNLib.Plugins.Essentials
/// A "lookup table" that represents virtual endpoints to be processed when an
/// incomming connection matches its path parameter
/// </summary>
- private IReadOnlyDictionary<string, IVirtualEndpoint<HttpEntity>> VirtualEndpoints = new Dictionary<string, IVirtualEndpoint<HttpEntity>>(StringComparer.OrdinalIgnoreCase);
+ private FrozenDictionary<string, IVirtualEndpoint<HttpEntity>> VirtualEndpoints =
+ new Dictionary<string, IVirtualEndpoint<HttpEntity>>(StringComparer.OrdinalIgnoreCase)
+ .ToFrozenDictionary();
/*
@@ -112,15 +115,17 @@ namespace VNLib.Plugins.Essentials
newTable.Add(ep.Path, ep);
}
+ FrozenDictionary<string, IVirtualEndpoint<HttpEntity>> newTableFrozen = newTable.ToFrozenDictionary();
+
//Store the new table
- _ = Interlocked.Exchange(ref VirtualEndpoints, newTable);
+ _ = Interlocked.Exchange(ref VirtualEndpoints, newTableFrozen);
}
}
///<inheritdoc/>
public void RemoveEndpoint(params IEndpoint[] eps)
{
- _ = eps ?? throw new ArgumentNullException(nameof(eps));
+ ArgumentNullException.ThrowIfNull(eps);
//Call remove on path
RemoveEndpoint(eps.Select(static s => s.Path).ToArray());
}
@@ -128,7 +133,7 @@ namespace VNLib.Plugins.Essentials
///<inheritdoc/>
public void RemoveEndpoint(params string[] paths)
{
- _ = paths ?? throw new ArgumentNullException(nameof(paths));
+ ArgumentNullException.ThrowIfNull(paths);
//Make sure all endpoints specify a path
if (paths.Any(static e => string.IsNullOrWhiteSpace(e)))
@@ -152,8 +157,10 @@ namespace VNLib.Plugins.Essentials
_ = newTable.Remove(eps);
}
+ FrozenDictionary<string, IVirtualEndpoint<HttpEntity>> newTableFrozen = newTable.ToFrozenDictionary();
+
//Store the new table
- _ = Interlocked.Exchange(ref VirtualEndpoints, newTable);
+ _ = Interlocked.Exchange(ref VirtualEndpoints, newTableFrozen);
}
}
diff --git a/lib/Utils.Memory/vnlib_mimalloc/CMakeLists.txt b/lib/Utils.Memory/vnlib_mimalloc/CMakeLists.txt
index 72b1e48..20383fb 100644
--- a/lib/Utils.Memory/vnlib_mimalloc/CMakeLists.txt
+++ b/lib/Utils.Memory/vnlib_mimalloc/CMakeLists.txt
@@ -21,7 +21,7 @@ add_library(${CMAKE_PROJECT_NAME}_static STATIC ${VNLIB_MIMALLOC_SOURCES} ${HEAD
#if on unix lib will be appended, so we can adjust
if(UNIX)
- set_target_properties(${CMAKE_PROJECT_NAME} ${CMAKE_PROJECT_NAME}_static PROPERTIES OUTPUT_NAME _vnmimalloc)
+ set_target_properties(${CMAKE_PROJECT_NAME} ${CMAKE_PROJECT_NAME}_static PROPERTIES OUTPUT_NAME vn_mimalloc)
endif()
#Setup the compiler options
diff --git a/lib/Utils.Memory/vnlib_rpmalloc/CMakeLists.txt b/lib/Utils.Memory/vnlib_rpmalloc/CMakeLists.txt
index 75efde6..82d1c38 100644
--- a/lib/Utils.Memory/vnlib_rpmalloc/CMakeLists.txt
+++ b/lib/Utils.Memory/vnlib_rpmalloc/CMakeLists.txt
@@ -25,7 +25,7 @@ add_library(${CMAKE_PROJECT_NAME}_static STATIC ${VNLIB_RPMALLOC_SOURCES} ${HEAD
#if on unix lib will be appended, so we can adjust
if(UNIX)
- set_target_properties(${CMAKE_PROJECT_NAME} ${CMAKE_PROJECT_NAME}_static PROPERTIES OUTPUT_NAME _vnrpmalloc)
+ set_target_properties(${CMAKE_PROJECT_NAME} ${CMAKE_PROJECT_NAME}_static PROPERTIES OUTPUT_NAME vn_rpmalloc)
endif()
#Setup the compiler options
diff --git a/lib/Utils/src/Extensions/MemoryExtensions.cs b/lib/Utils/src/Extensions/MemoryExtensions.cs
index 28969ea..8f90525 100644
--- a/lib/Utils/src/Extensions/MemoryExtensions.cs
+++ b/lib/Utils/src/Extensions/MemoryExtensions.cs
@@ -71,6 +71,8 @@ namespace VNLib.Utils.Extensions
/// <returns>A new <see cref="OpenResourceHandle{T}"/> encapsulating the rented array</returns>
public static IMemoryHandle<T> SafeAlloc<T>(this ArrayPool<T> pool, int size, bool zero = false) where T : struct
{
+ ArgumentNullException.ThrowIfNull(pool);
+
T[] array = pool.Rent(size);
if (zero)
@@ -94,6 +96,8 @@ namespace VNLib.Utils.Extensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T[] Rent<T>(this ArrayPool<T> pool, int size, bool zero)
{
+ ArgumentNullException.ThrowIfNull(pool);
+
//Rent the array
T[] arr = pool.Rent(size);
//If zero flag is set, zero only the used section
@@ -186,7 +190,8 @@ namespace VNLib.Utils.Extensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static MemoryManager<T> DirectAlloc<T>(this IUnmangedHeap heap, nint size, bool zero = false) where T : unmanaged
{
- return size >= 0 ? DirectAlloc<T>(heap, (nuint)size, zero) : throw new ArgumentOutOfRangeException(nameof(size), "The size paramter must be a positive integer");
+ ArgumentOutOfRangeException.ThrowIfNegative(size);
+ return DirectAlloc<T>(heap, (nuint)size, zero);
}
/// <summary>
@@ -200,7 +205,9 @@ namespace VNLib.Utils.Extensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe T* GetOffset<T>(this MemoryHandle<T> memory, nint elements) where T : unmanaged
{
- return elements >= 0 ? memory.GetOffset((nuint)elements) : throw new ArgumentOutOfRangeException(nameof(elements), "The elements paramter must be a positive integer");
+ ArgumentNullException.ThrowIfNull(memory);
+ ArgumentOutOfRangeException.ThrowIfNegative(elements);
+ return memory.GetOffset((nuint)elements);
}
/// <summary>
@@ -215,10 +222,8 @@ namespace VNLib.Utils.Extensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Resize<T>(this IResizeableMemoryHandle<T> memory, nint elements)
{
- if (elements < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(elements));
- }
+ ArgumentNullException.ThrowIfNull(memory);
+ ArgumentOutOfRangeException.ThrowIfNegative(elements);
memory.Resize((nuint)elements);
}
@@ -235,10 +240,7 @@ namespace VNLib.Utils.Extensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ResizeIfSmaller<T>(this IResizeableMemoryHandle<T> handle, nint count)
{
- if(count < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(count));
- }
+ ArgumentOutOfRangeException.ThrowIfNegative(count);
ResizeIfSmaller(handle, (nuint)count);
}
@@ -255,6 +257,7 @@ namespace VNLib.Utils.Extensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ResizeIfSmaller<T>(this IResizeableMemoryHandle<T> handle, nuint count)
{
+ ArgumentNullException.ThrowIfNull(handle);
//Check handle size
if(handle.Length < count)
{
@@ -274,12 +277,8 @@ namespace VNLib.Utils.Extensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref T GetOffsetRef<T>(this IMemoryHandle<T> block, nuint offset)
{
- _ = block ?? throw new ArgumentNullException(nameof(block));
-
- if (offset >= block.Length)
- {
- throw new ArgumentOutOfRangeException(nameof(offset));
- }
+ ArgumentNullException.ThrowIfNull(block);
+ ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(offset, block.Length);
return ref Unsafe.Add(ref block.GetReference(), offset);
}
@@ -297,12 +296,8 @@ namespace VNLib.Utils.Extensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref byte GetOffsetByteRef<T>(this IMemoryHandle<T> block, nuint offset)
{
- _ = block ?? throw new ArgumentNullException(nameof(block));
-
- if (offset >= block.Length)
- {
- throw new ArgumentOutOfRangeException(nameof(offset));
- }
+ ArgumentNullException.ThrowIfNull(block);
+ ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(offset, block.Length);
//Get the base reference, then offset by the desired number of elements and cast to a byte reference
ref T baseRef = ref block.GetReference();
@@ -322,13 +317,10 @@ namespace VNLib.Utils.Extensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<T> GetOffsetSpan<T>(this IMemoryHandle<T> block, nuint offset, int size)
{
- _ = block ?? throw new ArgumentNullException(nameof(block));
-
- if(size < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(size));
- }
- if(size == 0)
+ ArgumentNullException.ThrowIfNull(block);
+ ArgumentOutOfRangeException.ThrowIfNegative(size);
+
+ if (size == 0)
{
return Span<T>.Empty;
}
@@ -353,7 +345,9 @@ namespace VNLib.Utils.Extensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe Span<T> GetOffsetSpan<T>(this IMemoryHandle<T> block, nint offset, int size)
{
- return offset >= 0 ? block.GetOffsetSpan((nuint)offset, size) : throw new ArgumentOutOfRangeException(nameof(offset));
+ ArgumentNullException.ThrowIfNull(block);
+ ArgumentOutOfRangeException.ThrowIfNegative(size);
+ return block.GetOffsetSpan((nuint)offset, size);
}
/// <summary>
@@ -380,7 +374,9 @@ namespace VNLib.Utils.Extensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static SubSequence<T> GetSubSequence<T>(this IMemoryHandle<T> block, nint offset, int size)
{
- return offset >= 0 ? new (block, (nuint)offset, size) : throw new ArgumentOutOfRangeException(nameof(offset));
+ ArgumentNullException.ThrowIfNull(block);
+ ArgumentOutOfRangeException.ThrowIfNegative(size);
+ return new (block, (nuint)offset, size);
}
/// <summary>
@@ -390,7 +386,8 @@ namespace VNLib.Utils.Extensions
/// <typeparam name="T">The unmanged data type to provide allocations from</typeparam>
/// <returns>The new <see cref="MemoryPool{T}"/> heap wrapper.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static MemoryPool<T> ToPool<T>(this IUnmangedHeap heap, int maxBufferSize = int.MaxValue) where T : unmanaged => new PrivateBuffersMemoryPool<T>(heap, maxBufferSize);
+ public static MemoryPool<T> ToPool<T>(this IUnmangedHeap heap, int maxBufferSize = int.MaxValue) where T : unmanaged
+ => new PrivateBuffersMemoryPool<T>(heap, maxBufferSize);
/// <summary>
/// Allocates a structure of the specified type on the current unmanged heap and optionally zero's its memory
@@ -403,7 +400,8 @@ namespace VNLib.Utils.Extensions
/// <exception cref="OutOfMemoryException"></exception>
/// <exception cref="ObjectDisposedException"></exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static unsafe T* StructAlloc<T>(this IUnmangedHeap heap, bool zero = true) where T : unmanaged => MemoryUtil.StructAlloc<T>(heap, zero);
+ public static unsafe T* StructAlloc<T>(this IUnmangedHeap heap, bool zero = true) where T : unmanaged
+ => MemoryUtil.StructAlloc<T>(heap, zero);
/// <summary>
/// Allocates a structure of the specified type on the current unmanged heap and optionally zero's its memory
@@ -416,7 +414,8 @@ namespace VNLib.Utils.Extensions
/// <exception cref="OutOfMemoryException"></exception>
/// <exception cref="ObjectDisposedException"></exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ref T StructAllocRef<T>(this IUnmangedHeap heap, bool zero = true) where T : unmanaged => ref MemoryUtil.StructAllocRef<T>(heap, zero);
+ public static ref T StructAllocRef<T>(this IUnmangedHeap heap, bool zero = true) where T : unmanaged
+ => ref MemoryUtil.StructAllocRef<T>(heap, zero);
/// <summary>
@@ -427,7 +426,8 @@ namespace VNLib.Utils.Extensions
/// <param name="heap"></param>
/// <param name="structPtr">A reference/pointer to the structure</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static unsafe void StructFree<T>(this IUnmangedHeap heap, T* structPtr) where T : unmanaged => MemoryUtil.StructFree(heap, structPtr);
+ public static unsafe void StructFree<T>(this IUnmangedHeap heap, T* structPtr) where T : unmanaged
+ => MemoryUtil.StructFree(heap, structPtr);
/// <summary>
/// Frees a structure at the specified address from the this heap.
@@ -437,7 +437,8 @@ namespace VNLib.Utils.Extensions
/// <param name="heap"></param>
/// <param name="structRef">A reference to the structure</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void StructFreeRef<T>(this IUnmangedHeap heap, ref T structRef) where T : unmanaged => MemoryUtil.StructFreeRef(heap, ref structRef);
+ public static void StructFreeRef<T>(this IUnmangedHeap heap, ref T structRef) where T : unmanaged
+ => MemoryUtil.StructFreeRef(heap, ref structRef);
/// <summary>
/// Allocates a block of unmanaged memory of the number of elements to store of an unmanged type
@@ -452,7 +453,7 @@ namespace VNLib.Utils.Extensions
/// <exception cref="ObjectDisposedException"></exception>
public static unsafe MemoryHandle<T> Alloc<T>(this IUnmangedHeap heap, nuint elements, bool zero = false) where T : unmanaged
{
- _ = heap ?? throw new ArgumentNullException(nameof(heap));
+ ArgumentNullException.ThrowIfNull(heap);
//Minimum of one element
elements = Math.Max(elements, 1);
//If zero flag is set then specify zeroing memory
@@ -475,7 +476,8 @@ namespace VNLib.Utils.Extensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static MemoryHandle<T> Alloc<T>(this IUnmangedHeap heap, nint elements, bool zero = false) where T : unmanaged
{
- return elements >= 0 ? Alloc<T>(heap, (nuint)elements, zero) : throw new ArgumentOutOfRangeException(nameof(elements));
+ ArgumentOutOfRangeException.ThrowIfNegative(elements);
+ return Alloc<T>(heap, (nuint)elements, zero);
}
/// <summary>
@@ -532,6 +534,7 @@ namespace VNLib.Utils.Extensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void WriteAndResize<T>(this IResizeableMemoryHandle<T> handle, ReadOnlySpan<T> input) where T: unmanaged
{
+ ArgumentNullException.ThrowIfNull(handle);
handle.Resize(input.Length);
MemoryUtil.Copy(input, 0, handle, 0, input.Length);
}
@@ -552,6 +555,8 @@ namespace VNLib.Utils.Extensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static UnsafeMemoryHandle<T> UnsafeAlloc<T>(this IUnmangedHeap heap, int elements, bool zero = false) where T : unmanaged
{
+ ArgumentNullException.ThrowIfNull(heap);
+
if (elements < 1)
{
//Return an empty handle
@@ -583,7 +588,7 @@ namespace VNLib.Utils.Extensions
Span<byte> output = buffer.Remaining[..size];
//Format value and write to buffer
- MemoryMarshal.Write(output, ref value);
+ MemoryMarshal.Write(output, in value);
//If byte order is reversed, reverse elements
if (!BitConverter.IsLittleEndian)
@@ -608,7 +613,7 @@ namespace VNLib.Utils.Extensions
Span<byte> output = buffer.Remaining.Span[..size];
//Format value and write to buffer
- MemoryMarshal.Write(output, ref value);
+ MemoryMarshal.Write(output, in value);
//If byte order is reversed, reverse elements
if (BitConverter.IsLittleEndian)
@@ -676,10 +681,8 @@ namespace VNLib.Utils.Extensions
/// <returns>The actual number of bytes written at the location indicated by the bytes parameter.</returns>
/// <exception cref="ArgumentOutOfRangeException"></exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int GetBytes(this Encoder enc, char[] chars, int offset, int charCount, ref ForwardOnlyWriter<byte> writer, bool flush)
- {
- return GetBytes(enc, chars.AsSpan(offset, charCount), ref writer, flush);
- }
+ public static int GetBytes(this Encoder enc, char[] chars, int offset, int charCount, ref ForwardOnlyWriter<byte> writer, bool flush)
+ => GetBytes(enc, chars.AsSpan(offset, charCount), ref writer, flush);
/// <summary>
/// Encodes a set of characters in the input characters span and any characters
@@ -696,6 +699,7 @@ namespace VNLib.Utils.Extensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetBytes(this Encoder enc, ReadOnlySpan<char> chars, ref ForwardOnlyWriter<byte> writer, bool flush)
{
+ ArgumentNullException.ThrowIfNull(enc);
//Encode the characters
int written = enc.GetBytes(chars, writer.Remaining, flush);
//Update the writer position
@@ -715,6 +719,7 @@ namespace VNLib.Utils.Extensions
/// <exception cref="ArgumentOutOfRangeException"></exception>
public static int GetBytes(this Encoding encoding, ReadOnlySpan<char> chars, ref ForwardOnlyWriter<byte> writer)
{
+ ArgumentNullException.ThrowIfNull(encoding);
//Encode the characters
int written = encoding.GetBytes(chars, writer.Remaining);
//Update the writer position
@@ -734,6 +739,7 @@ namespace VNLib.Utils.Extensions
/// <exception cref="ArgumentOutOfRangeException"></exception>
public static int GetChars(this Encoding encoding, ReadOnlySpan<byte> bytes, ref ForwardOnlyWriter<char> writer)
{
+ ArgumentNullException.ThrowIfNull(encoding);
int charCount = encoding.GetCharCount(bytes);
//Encode the characters
_ = encoding.GetChars(bytes, writer.Remaining);
@@ -770,10 +776,10 @@ namespace VNLib.Utils.Extensions
/// <exception cref="ArgumentOutOfRangeException"></exception>
public static T[] Slice<T>(this T[] arr, int start)
{
- if(start < 0 || start > arr.Length)
- {
- throw new ArgumentOutOfRangeException(nameof(start));
- }
+ ArgumentNullException.ThrowIfNull(arr);
+ ArgumentOutOfRangeException.ThrowIfNegative(start);
+ ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(start, arr.Length);
+
Range sliceRange = new(start, arr.Length - start);
return RuntimeHelpers.GetSubArray(arr, sliceRange);
}
@@ -790,22 +796,16 @@ namespace VNLib.Utils.Extensions
/// <exception cref="ArgumentOutOfRangeException"></exception>
public static T[] Slice<T>(this T[] arr, int start, int count)
{
- if(start < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(start));
- }
- if(count < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(count));
- }
- if(start + count >= arr.Length)
- {
- throw new ArgumentOutOfRangeException(nameof(count));
- }
+ ArgumentNullException.ThrowIfNull(arr);
+ ArgumentOutOfRangeException.ThrowIfNegative(start);
+ ArgumentOutOfRangeException.ThrowIfNegative(count);
+ ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(start + count, arr.Length);
+
if(count == 0)
{
- return Array.Empty<T>();
+ return [];
}
+
//Calc the slice range
Range sliceRange = new(start, start + count);
return RuntimeHelpers.GetSubArray(arr, sliceRange);
@@ -822,11 +822,17 @@ namespace VNLib.Utils.Extensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<T> AsSpan<T>(this IMemoryHandle<T> handle, nint start)
{
- _ = handle ?? throw new ArgumentNullException(nameof(handle));
- if(start < 0 || (uint)start > handle.Length)
+ ArgumentNullException.ThrowIfNull(handle);
+ ArgumentOutOfRangeException.ThrowIfNegative(start);
+
+ //Allow empty spans for empty handles or last elements
+ if((nuint)start == handle.Length)
{
- throw new ArgumentOutOfRangeException(nameof(start));
+ return Span<T>.Empty;
}
+
+ ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual((nuint)start, handle.Length);
+
//calculate a remaining count
int count = checked((int)(handle.Length - (uint)start));
//call the other overload
@@ -839,40 +845,24 @@ namespace VNLib.Utils.Extensions
/// <typeparam name="T"></typeparam>
/// <param name="handle"></param>
/// <param name="start">Intial offset into the handle</param>
- /// <returns>The sub-sequence of the current handle</returns>
- /// <exception cref="ArgumentOutOfRangeException"></exception>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Span<T> AsSpan<T>(this IMemoryHandle<T> handle, int start) => AsSpan(handle, (nint)start);
-
- /// <summary>
- /// Creates a new sub-sequence over the target handle. (allows for convient sub span)
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="handle"></param>
- /// <param name="start">Intial offset into the handle</param>
/// <param name="count">The number of elements within the new sequence</param>
/// <returns>The sub-sequence of the current handle</returns>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public static Span<T> AsSpan<T>(this IMemoryHandle<T> handle, nint start, int count)
{
- _ = handle ?? throw new ArgumentNullException(nameof(handle));
- if(start < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(start));
- }
- if(count < 0)
+ ArgumentNullException.ThrowIfNull(handle);
+ ArgumentOutOfRangeException.ThrowIfNegative(start);
+ ArgumentOutOfRangeException.ThrowIfNegative(count);
+
+ //Allow empty spans for empty handles
+ if (count == 0)
{
- throw new ArgumentOutOfRangeException(nameof(count));
+ return Span<T>.Empty;
}
//guard against buffer overrun
MemoryUtil.CheckBounds(handle, (nuint)start, (nuint)count);
- if(count == 0)
- {
- return Span<T>.Empty;
- }
-
//Get the offset ref and create a new span from the pointer
ref T asRef = ref handle.GetOffsetRef((nuint)start);
return MemoryMarshal.CreateSpan(ref asRef, count);
@@ -884,18 +874,6 @@ namespace VNLib.Utils.Extensions
/// <typeparam name="T"></typeparam>
/// <param name="handle"></param>
/// <param name="start">Intial offset into the handle</param>
- /// <param name="count">The number of elements within the new sequence</param>
- /// <returns>The sub-sequence of the current handle</returns>
- /// <exception cref="ArgumentOutOfRangeException"></exception>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Span<T> AsSpan<T>(this IMemoryHandle<T> handle, int start, int count) => AsSpan(handle, (nint)start, count);
-
- /// <summary>
- /// Creates a new sub-sequence over the target handle. (allows for convient sub span)
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="handle"></param>
- /// <param name="start">Intial offset into the handle</param>
/// <returns>The sub-sequence of the current handle</returns>
/// <exception cref="ArgumentOutOfRangeException"></exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -920,12 +898,7 @@ namespace VNLib.Utils.Extensions
/// <param name="handle"></param>
/// <exception cref="ObjectDisposedException"></exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void ThrowIfClosed(this SafeHandle handle)
- {
- if (handle.IsClosed || handle.IsInvalid)
- {
- throw new ObjectDisposedException(handle.GetType().Name);
- }
- }
+ public static void ThrowIfClosed(this SafeHandle handle)
+ => ObjectDisposedException.ThrowIf(handle.IsClosed || handle.IsInvalid, handle);
}
}
diff --git a/lib/Utils/src/IO/VnMemoryStream.cs b/lib/Utils/src/IO/VnMemoryStream.cs
index 45c4a55..885d9c2 100644
--- a/lib/Utils/src/IO/VnMemoryStream.cs
+++ b/lib/Utils/src/IO/VnMemoryStream.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Utils
@@ -75,7 +75,7 @@ namespace VNLib.Utils.IO
public static VnMemoryStream FromHandle(IResizeableMemoryHandle<byte> handle, bool ownsHandle, nint length, bool readOnly)
{
//Check the handle
- _ = handle ?? throw new ArgumentNullException(nameof(handle));
+ ArgumentNullException.ThrowIfNull(handle);
return handle.CanRealloc || readOnly
? new VnMemoryStream(handle, length, readOnly, ownsHandle)
@@ -121,7 +121,7 @@ namespace VNLib.Utils.IO
/// <exception cref="ArgumentOutOfRangeException"></exception>
public VnMemoryStream(IUnmangedHeap heap, nuint bufferSize, bool zero)
{
- _ = heap ?? throw new ArgumentNullException(nameof(heap));
+ ArgumentNullException.ThrowIfNull(heap);
_buffer = heap.Alloc<byte>(bufferSize, zero);
}
@@ -132,7 +132,7 @@ namespace VNLib.Utils.IO
/// <param name="data">Initial data</param>
public VnMemoryStream(IUnmangedHeap heap, ReadOnlySpan<byte> data)
{
- _ = heap ?? throw new ArgumentNullException(nameof(heap));
+ ArgumentNullException.ThrowIfNull(heap);
//Alloc the internal buffer to match the data stream
_buffer = heap.AllocAndCopy(data);
//Set length
@@ -147,7 +147,7 @@ namespace VNLib.Utils.IO
/// <param name="data">Initial data</param>
public VnMemoryStream(IUnmangedHeap heap, ReadOnlyMemory<byte> data)
{
- _ = heap ?? throw new ArgumentNullException(nameof(heap));
+ ArgumentNullException.ThrowIfNull(heap);
//Alloc the internal buffer to match the data stream
_buffer = heap.AllocAndCopy(data);
//Set length
@@ -200,12 +200,9 @@ namespace VNLib.Utils.IO
/// <exception cref="IOException"></exception>
public override void CopyTo(Stream destination, int bufferSize)
{
- _ = destination ?? throw new ArgumentNullException(nameof(destination));
- if(bufferSize < 1)
- {
- throw new ArgumentOutOfRangeException(nameof(bufferSize), "Buffer size must be greater than 0");
- }
-
+ ArgumentNullException.ThrowIfNull(destination);
+ ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(bufferSize, 0);
+
if (!destination.CanWrite)
{
throw new IOException("The destinaion stream is not writeable");
@@ -239,12 +236,8 @@ namespace VNLib.Utils.IO
/// <exception cref="ArgumentOutOfRangeException"></exception>
public override async Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
{
- _ = destination ?? throw new ArgumentNullException(nameof(destination));
-
- if (bufferSize < 1)
- {
- throw new ArgumentOutOfRangeException(nameof(bufferSize), "Buffer size must be greater than 0");
- }
+ ArgumentNullException.ThrowIfNull(destination);
+ ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(bufferSize, 0);
if (!destination.CanWrite)
{
@@ -400,14 +393,9 @@ namespace VNLib.Utils.IO
///<inheritdoc/>
public override long Seek(long offset, SeekOrigin origin)
{
- if (offset < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(offset), "Offset cannot be less than 0");
- }
- if(offset > nint.MaxValue)
- {
- throw new ArgumentOutOfRangeException(nameof(offset), "Offset cannot be less than nint.MaxValue");
- }
+ //gaurd for overflow, offset cannot be greater than platform pointer size
+ ArgumentOutOfRangeException.ThrowIfGreaterThan(offset, nint.MaxValue);
+ ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(offset, nint.MinValue);
//safe cast to nint
nint _offset = (nint)offset;
@@ -415,16 +403,38 @@ namespace VNLib.Utils.IO
switch (origin)
{
case SeekOrigin.Begin:
+
+ ArgumentOutOfRangeException.ThrowIfNegative(offset);
+ ArgumentOutOfRangeException.ThrowIfGreaterThan(offset, _length);
+
//Length will never be greater than nint.Max so output will never exceed nint.max
return _position = Math.Min(_length, _offset);
+
case SeekOrigin.Current:
+
+ if(_offset < 0)
+ {
+ ArgumentOutOfRangeException.ThrowIfLessThan(offset, -_position);
+ }
+ else
+ {
+ ArgumentOutOfRangeException.ThrowIfGreaterThan(offset, LenToPosDiff);
+ }
+
//Calc new seek position from current position
nint newPos = _position + _offset;
return _position = Math.Min(_length, newPos);
+
case SeekOrigin.End:
+
+ //Must be negative value
+ ArgumentOutOfRangeException.ThrowIfGreaterThan(_offset, 0, nameof(offset));
+ ArgumentOutOfRangeException.ThrowIfLessThan(_offset, -_length, nameof(offset));
+
//Calc new seek position from end of stream, should be len -1 so 0 can be specified from the end
- nint realIndex = _length - (_offset - 1);
+ nint realIndex = _length + _offset;
return _position = Math.Min(realIndex, 0);
+
default:
throw new ArgumentException("Stream operation is not supported on current stream");
}
@@ -446,14 +456,9 @@ namespace VNLib.Utils.IO
{
throw new NotSupportedException("This stream is readonly");
}
- if (value < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(value), "Value cannot be less than 0");
- }
- if(value > nint.MaxValue)
- {
- throw new ArgumentOutOfRangeException(nameof(value), "Value cannot be greater than nint.MaxValue");
- }
+
+ ArgumentOutOfRangeException.ThrowIfNegative(value);
+ ArgumentOutOfRangeException.ThrowIfGreaterThan(value, nint.MaxValue);
nint _value = (nint)value;
@@ -468,9 +473,11 @@ namespace VNLib.Utils.IO
}
///<inheritdoc/>
+ ///<exception cref="OutOfMemoryException"></exception>
public override void Write(byte[] buffer, int offset, int count) => Write(buffer.AsSpan(offset, count));
///<inheritdoc/>
+ ///<exception cref="OutOfMemoryException"></exception>
public override void Write(ReadOnlySpan<byte> buffer)
{
if (_isReadonly)
@@ -494,6 +501,7 @@ namespace VNLib.Utils.IO
}
///<inheritdoc/>
+ ///<exception cref="OutOfMemoryException"></exception>
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
//Write synchronously and return a completed task
@@ -502,6 +510,7 @@ namespace VNLib.Utils.IO
}
///<inheritdoc/>
+ ///<exception cref="OutOfMemoryException"></exception>
public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
{
//Write synchronously and return a completed task
@@ -510,6 +519,7 @@ namespace VNLib.Utils.IO
}
///<inheritdoc/>
+ ///<exception cref="OutOfMemoryException"></exception>
public override void WriteByte(byte value)
{
Span<byte> buf = MemoryMarshal.CreateSpan(ref value, 1);
diff --git a/lib/Utils/src/Memory/ArrayPoolBuffer.cs b/lib/Utils/src/Memory/ArrayPoolBuffer.cs
index 2f00e66..e728cd7 100644
--- a/lib/Utils/src/Memory/ArrayPoolBuffer.cs
+++ b/lib/Utils/src/Memory/ArrayPoolBuffer.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Utils
@@ -91,11 +91,8 @@ namespace VNLib.Utils.Memory
/// <param name="minSize">Minimum size of the buffer</param>
/// <param name="zero">Set the zero memory flag on close</param>
public ArrayPoolBuffer(ArrayPool<T> pool, int minSize, bool zero = false)
- {
- Pool = pool ?? throw new ArgumentNullException(nameof(pool));
- Buffer = pool.Rent(minSize, zero);
- InitSize = minSize;
- }
+ :this(pool, pool.Rent(minSize, zero), minSize)
+ { }
/// <summary>
/// Initialzies a new <see cref="ArrayPoolBuffer{T}"/> from the specified rented array
@@ -108,12 +105,13 @@ namespace VNLib.Utils.Memory
/// <exception cref="ArgumentOutOfRangeException"></exception>
public ArrayPoolBuffer(ArrayPool<T> pool, T[] array, int size)
{
- Pool = pool ?? throw new ArgumentNullException(nameof(pool));
- Buffer = array ?? throw new ArgumentNullException(nameof(array));
-
- if (size < 0 || size > array.Length)
- throw new ArgumentOutOfRangeException(nameof(size));
+ ArgumentNullException.ThrowIfNull(pool);
+ ArgumentNullException.ThrowIfNull(array);
+ ArgumentOutOfRangeException.ThrowIfNegative(size);
+ ArgumentOutOfRangeException.ThrowIfGreaterThan(size, array.Length);
+ Pool = pool;
+ Buffer = array;
InitSize = size;
}
@@ -209,7 +207,11 @@ namespace VNLib.Utils.Memory
//Pin, will also check bounds
///<inheritdoc/>
- public MemoryHandle Pin(int elementIndex) => MemoryUtil.PinArrayAndGetHandle(Buffer, elementIndex);
+ public MemoryHandle Pin(int elementIndex)
+ {
+ Check();
+ return MemoryUtil.PinArrayAndGetHandle(Buffer, elementIndex);
+ }
void IPinnable.Unpin()
{
diff --git a/lib/Utils/src/Memory/MemoryHandle.cs b/lib/Utils/src/Memory/MemoryHandle.cs
index f474abd..09d4c32 100644
--- a/lib/Utils/src/Memory/MemoryHandle.cs
+++ b/lib/Utils/src/Memory/MemoryHandle.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Utils
@@ -106,7 +106,7 @@ namespace VNLib.Utils.Memory
public bool CanRealloc
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => Heap != null && Heap.CreationFlags.HasFlag(HeapCreation.SupportsRealloc);
+ get => !IsClosed && Heap != null && Heap.CreationFlags.HasFlag(HeapCreation.SupportsRealloc);
}
/// <summary>
@@ -184,11 +184,7 @@ namespace VNLib.Utils.Memory
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe T* GetOffset(nuint elements)
{
- if (elements >= _length)
- {
- throw new ArgumentOutOfRangeException(nameof(elements), "Element offset cannot be larger than allocated size");
- }
-
+ ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(elements, _length);
this.ThrowIfClosed();
//Get ptr and offset it
@@ -212,30 +208,26 @@ namespace VNLib.Utils.Memory
///</remarks>
public unsafe MemoryHandle Pin(int elementIndex)
{
- if (elementIndex < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(elementIndex));
- }
+ ArgumentOutOfRangeException.ThrowIfNegative(elementIndex);
//Get ptr and guard checks before adding the referrence
T* ptr = GetOffset((nuint)elementIndex);
bool addRef = false;
+
//use the pinned field as success val
DangerousAddRef(ref addRef);
+
+ //If adding ref failed, the handle is closed
+ ObjectDisposedException.ThrowIf(!addRef, this);
+
//Create a new system.buffers memory handle from the offset ptr address
- return !addRef
- ? throw new ObjectDisposedException("Failed to increase referrence count on the memory handle because it was released")
- : new MemoryHandle(ptr, pinnable: this);
+ return new MemoryHandle(ptr, pinnable: this);
}
///<inheritdoc/>
///<exception cref="ObjectDisposedException"></exception>
- public void Unpin()
- {
- //Dec count on release
- DangerousRelease();
- }
+ public void Unpin() => DangerousRelease();
///<inheritdoc/>
protected override bool ReleaseHandle() => Heap.Free(ref handle);
diff --git a/lib/Utils/src/Memory/MemoryUtil.cs b/lib/Utils/src/Memory/MemoryUtil.cs
index 1e0d11a..dacb6b4 100644
--- a/lib/Utils/src/Memory/MemoryUtil.cs
+++ b/lib/Utils/src/Memory/MemoryUtil.cs
@@ -520,10 +520,7 @@ namespace VNLib.Utils.Memory
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyStruct<T>(ref byte source, T* target) where T : unmanaged
{
- if (target == null)
- {
- throw new ArgumentNullException(nameof(target));
- }
+ ArgumentNullException.ThrowIfNull(target);
CopyStruct(ref source, ref *target);
}
@@ -593,11 +590,7 @@ namespace VNLib.Utils.Memory
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyStruct<T>(T* source, ref byte target) where T : unmanaged
{
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
-
+ ArgumentNullException.ThrowIfNull(source);
CopyStruct(ref *source, ref target);
}
@@ -633,10 +626,7 @@ namespace VNLib.Utils.Memory
public static void CopyStruct<T>(ref T source, Span<byte> target) where T : unmanaged
{
//check that the span is large enough to hold the structure
- if (target.Length < sizeof(T))
- {
- throw new ArgumentException("Target span is smaller than the size of the structure");
- }
+ ArgumentOutOfRangeException.ThrowIfLessThan(target.Length, sizeof(T), nameof(target));
CopyStruct(ref source, ref MemoryMarshal.GetReference(target));
}
@@ -657,10 +647,9 @@ namespace VNLib.Utils.Memory
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyStruct<T>(T* source, Span<byte> target) where T : unmanaged
{
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
+ ArgumentNullException.ThrowIfNull(source);
+ ArgumentOutOfRangeException.ThrowIfLessThan(target.Length, sizeof(T), nameof(target));
+
CopyStruct(ref *source, target);
}
@@ -732,14 +721,8 @@ namespace VNLib.Utils.Memory
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CloneStruct<T>(T* source, T* target) where T : unmanaged
{
- if(source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if(target == null)
- {
- throw new ArgumentNullException(nameof(target));
- }
+ ArgumentNullException.ThrowIfNull(source);
+ ArgumentNullException.ThrowIfNull(target);
Unsafe.CopyBlockUnaligned(target, source, (uint)sizeof(T));
}
@@ -1102,7 +1085,7 @@ namespace VNLib.Utils.Memory
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static nuint ByteSize<T>(IMemoryHandle<T> handle)
{
- _ = handle ?? throw new ArgumentNullException(nameof(handle));
+ ArgumentNullException.ThrowIfNull(handle);
return checked(handle.Length * (nuint)Unsafe.SizeOf<T>());
}
@@ -1167,12 +1150,7 @@ namespace VNLib.Utils.Memory
/// <exception cref="ArgumentOutOfRangeException"></exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CheckBounds<T>(IMemoryHandle<T> handle, nuint offset, nuint count)
- {
- if (offset + count > handle.Length)
- {
- throw new ArgumentOutOfRangeException(nameof(offset), "Offset or count are beyond the range of the supplied memory handle");
- }
- }
+ => ArgumentOutOfRangeException.ThrowIfGreaterThan(offset + count, handle.Length, nameof(count));
/// <summary>
/// Checks if the offset/count paramters for the given block
@@ -1185,11 +1163,9 @@ namespace VNLib.Utils.Memory
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CheckBounds<T>(ReadOnlySpan<T> block, int offset, int count)
{
- //Check span bounds
- if (offset < 0 || count < 0 || offset + count > block.Length)
- {
- throw new ArgumentOutOfRangeException(nameof(offset), "Offset or count are beyond the range of the supplied memory handle");
- }
+ ArgumentOutOfRangeException.ThrowIfNegative(offset);
+ ArgumentOutOfRangeException.ThrowIfNegative(count);
+ ArgumentOutOfRangeException.ThrowIfGreaterThan(offset + count, block.Length, nameof(count));
}
/// <summary>
@@ -1204,11 +1180,9 @@ namespace VNLib.Utils.Memory
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CheckBounds<T>(Span<T> block, int offset, int count)
{
- //Check span bounds
- if (offset < 0 || count < 0 || offset + count > block.Length)
- {
- throw new ArgumentOutOfRangeException(nameof(offset), "Offset or count are beyond the range of the supplied memory handle");
- }
+ ArgumentOutOfRangeException.ThrowIfNegative(offset);
+ ArgumentOutOfRangeException.ThrowIfNegative(count);
+ ArgumentOutOfRangeException.ThrowIfGreaterThan(offset + count, block.Length, nameof(count));
}
/// <summary>
@@ -1222,12 +1196,7 @@ namespace VNLib.Utils.Memory
/// <exception cref="ArgumentOutOfRangeException"></exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CheckBounds<T>(T[] block, nuint offset, nuint count)
- {
- if (offset + count > (ulong)block.LongLength)
- {
- throw new ArgumentOutOfRangeException(nameof(offset), "The offset or count is outside of the range of the block of memory");
- }
- }
+ => ArgumentOutOfRangeException.ThrowIfGreaterThan(offset + count, (ulong)block.LongLength, nameof(count));
#endregion
@@ -1242,11 +1211,7 @@ namespace VNLib.Utils.Memory
/// <exception cref="IndexOutOfRangeException"></exception>
public static MemoryHandle PinArrayAndGetHandle<T>(T[] array, nint elementOffset)
{
- if(elementOffset < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(elementOffset));
- }
-
+ ArgumentOutOfRangeException.ThrowIfNegative(elementOffset);
return PinArrayAndGetHandle(array, (nuint)elementOffset);
}
@@ -1475,6 +1440,8 @@ namespace VNLib.Utils.Memory
}
}
+ const nuint _avx32ByteAlignment = 0x20u;
+
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private static void _avx32ByteCopy(
ref byte src,
@@ -1486,7 +1453,7 @@ namespace VNLib.Utils.Memory
Debug.Assert(Avx2.IsSupported, "AVX2 is not supported on this platform");
//determine the number of loops
- nuint loopCount = count / (nuint)Vector256<byte>.Count;
+ nuint loopCount = count / _avx32ByteAlignment;
fixed (byte* srcPtr = &src, dstPtr = &dst)
{
@@ -1514,7 +1481,7 @@ namespace VNLib.Utils.Memory
/// <param name="size">The block size to test</param>
/// <returns>A value that indicates if the block size is 32byte aligned</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool Is32ByteAligned(nuint size) => unchecked(size % 0x20u) == 0;
+ public static bool Is32ByteAligned(nuint size) => unchecked(size % _avx32ByteAlignment) == 0;
}
private static class Refs
diff --git a/lib/Utils/src/Memory/MemoryUtilAlloc.cs b/lib/Utils/src/Memory/MemoryUtilAlloc.cs
index 0f25682..e2e7434 100644
--- a/lib/Utils/src/Memory/MemoryUtilAlloc.cs
+++ b/lib/Utils/src/Memory/MemoryUtilAlloc.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Utils
@@ -174,7 +174,7 @@ namespace VNLib.Utils.Memory
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T* StructAlloc<T>(IUnmangedHeap heap, bool zero) where T : unmanaged
{
- _ = heap ?? throw new ArgumentNullException(nameof(heap));
+ ArgumentNullException.ThrowIfNull(heap);
return (T*)heap.Alloc(1, (nuint)sizeof(T), zero);
}
@@ -228,11 +228,9 @@ namespace VNLib.Utils.Memory
/// <exception cref="ArgumentNullException"></exception>
public static void StructFree(IUnmangedHeap heap, void* structPtr)
{
- _ = heap ?? throw new ArgumentNullException(nameof(heap));
- if(structPtr == null)
- {
- throw new ArgumentNullException(nameof(structPtr));
- }
+ ArgumentNullException.ThrowIfNull(heap);
+ ArgumentNullException.ThrowIfNull(structPtr);
+
//Get intpointer
IntPtr ptr = (IntPtr)structPtr;
//Free
diff --git a/lib/Utils/src/Memory/UnmanagedHeapBase.cs b/lib/Utils/src/Memory/UnmanagedHeapBase.cs
index daf360c..a038358 100644
--- a/lib/Utils/src/Memory/UnmanagedHeapBase.cs
+++ b/lib/Utils/src/Memory/UnmanagedHeapBase.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Utils
@@ -78,10 +78,7 @@ namespace VNLib.Utils.Memory
DangerousAddRef(ref handleCountIncremented);
//Failed to increment ref count, class has been disposed
- if (!handleCountIncremented)
- {
- throw new ObjectDisposedException("The handle has been released");
- }
+ ObjectDisposedException.ThrowIf(handleCountIncremented == false, "The handle has been released");
try
{
@@ -102,8 +99,12 @@ namespace VNLib.Utils.Memory
//Alloc block without lock
block = AllocBlock(elements, size, zero);
}
+
+ //Check block
+ NativeMemoryOutOfMemoryException.ThrowIfNullPointer(block);
+
//Check if block was allocated
- return block != IntPtr.Zero ? block : throw new NativeMemoryOutOfMemoryException("Failed to allocate the requested block");
+ return block;
}
catch
{
@@ -146,7 +147,7 @@ namespace VNLib.Utils.Memory
//Decrement handle count
DangerousRelease();
//set block to invalid
- block = IntPtr.Zero;
+ block = 0;
return result;
}
@@ -186,12 +187,9 @@ namespace VNLib.Utils.Memory
{
newBlock = ReAllocBlock(block, elements, size, zero);
}
-
+
//Check block
- if (newBlock == IntPtr.Zero)
- {
- throw new NativeMemoryOutOfMemoryException("The memory block could not be resized");
- }
+ NativeMemoryOutOfMemoryException.ThrowIfNullPointer(newBlock, "The memory block could not be resized");
//Set the new block
block = newBlock;
@@ -228,11 +226,9 @@ namespace VNLib.Utils.Memory
///<inheritdoc/>
public override int GetHashCode() => handle.GetHashCode();
-
+
///<inheritdoc/>
- public override bool Equals(object? obj)
- {
- return obj is UnmanagedHeapBase heap && !heap.IsInvalid && !heap.IsClosed && handle == heap.handle;
- }
+ public override bool Equals(object? obj)
+ => obj is UnmanagedHeapBase heap && !heap.IsInvalid && !heap.IsClosed && handle == heap.handle;
}
}
diff --git a/lib/Utils/src/Native/NativeMemoryOutOfMemoryException.cs b/lib/Utils/src/Native/NativeMemoryOutOfMemoryException.cs
index 5a836da..d257233 100644
--- a/lib/Utils/src/Native/NativeMemoryOutOfMemoryException.cs
+++ b/lib/Utils/src/Native/NativeMemoryOutOfMemoryException.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Utils
@@ -40,5 +40,19 @@ namespace VNLib.Utils.Native
public NativeMemoryOutOfMemoryException()
{ }
+
+ /// <summary>
+ /// Throws an <see cref="NativeMemoryOutOfMemoryException"/> if the pointer is null
+ /// </summary>
+ /// <param name="value">The pointer value to test</param>
+ /// <param name="message">The message to use if the pointer is null</param>
+ /// <exception cref="NativeMemoryOutOfMemoryException"></exception>
+ public static void ThrowIfNullPointer(nint value, string? message = null)
+ {
+ if (value == 0)
+ {
+ throw new NativeMemoryOutOfMemoryException(message ?? "Failed to allocate or reallocte memory region");
+ }
+ }
}
}
diff --git a/lib/Utils/src/Native/SafeLibraryHandle.cs b/lib/Utils/src/Native/SafeLibraryHandle.cs
index 4772bd4..b3594e1 100644
--- a/lib/Utils/src/Native/SafeLibraryHandle.cs
+++ b/lib/Utils/src/Native/SafeLibraryHandle.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2022 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Utils
@@ -169,11 +169,10 @@ namespace VNLib.Utils.Native
{
//Increment handle count before obtaining a method
bool success = false;
- DangerousAddRef(ref success);
- if (!success)
- {
- throw new ObjectDisposedException("The libary has been released!");
- }
+ DangerousAddRef(ref success);
+
+ ObjectDisposedException.ThrowIf(success == false, "The libary has been released!");
+
try
{
//Get the method pointer
diff --git a/lib/Utils/src/VnEncoding.cs b/lib/Utils/src/VnEncoding.cs
index 3e895bc..ffdebae 100644
--- a/lib/Utils/src/VnEncoding.cs
+++ b/lib/Utils/src/VnEncoding.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Utils
@@ -539,7 +539,7 @@ namespace VNLib.Utils
//Rent a bin buffer
Span<byte> binBuffer = stackalloc byte[binSize];
//Write memory to buffer
- MemoryMarshal.Write(binBuffer, ref value);
+ MemoryMarshal.Write(binBuffer, in value);
//Convert to base32
return ToBase32String(binBuffer, withPadding);
}