Skip to content

Commit d1d2e30

Browse files
committed
Add sourcelink, removed unsafe enumerator from blitzmap
1 parent c3c6aa0 commit d1d2e30

File tree

2 files changed

+38
-49
lines changed

2 files changed

+38
-49
lines changed

src/Core/BlitzMap.cs

Lines changed: 29 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,22 @@ public class BlitzMap<TKey, TValue, THasher> where THasher : struct, IHasher<TKe
8282
#region Enumerable
8383

8484
/// <summary>
85-
/// Fallback for `foreach` compatibility.
85+
/// Fallback for `foreach` compatibility.
86+
/// Example:
87+
/// <code>
88+
/// foreach (ref readonly var entry in map)
89+
/// {
90+
///
91+
/// }
92+
/// </code>
8693
/// </summary>
8794
[MethodImpl(MethodImplOptions.AggressiveInlining)]
88-
public IEnumerator<Entry> GetEnumerator()
95+
public SpanEnumerator GetEnumerator()
8996
{
90-
return new FastEnumerator(_entries, (int)_count);
97+
return new SpanEnumerator(
98+
MemoryMarshal.CreateReadOnlySpan(
99+
ref MemoryMarshal.GetArrayDataReference(_entries),
100+
(int)_count));
91101
}
92102

93103
#endregion
@@ -107,7 +117,7 @@ public IEnumerator<Entry> GetEnumerator()
107117
private uint _maxCountBeforeResize;
108118
private THasher _hasher;
109119
private uint _lastBucket = INACTIVE;
110-
120+
111121
#endregion
112122
/// <summary>
113123
/// Initializes a new instance of the <see cref="BlitzMap{TKey, TValue, THasher}"/> class
@@ -951,62 +961,35 @@ public struct Bucket
951961
public uint Next;
952962
}
953963

954-
public unsafe struct FastEnumerator : IEnumerator<Entry>
964+
public ref struct SpanEnumerator
955965
{
956-
private readonly Entry* _start;
957-
private readonly Entry* _end;
958-
private Entry* _current;
966+
private ReadOnlySpan<Entry> _span;
967+
private int _index;
959968

960-
/// <summary>
961-
/// Initializes a new instance of the <see cref="FastEnumerator"/> struct.
962-
/// Uses unsafe pointer-based iteration for extreme performance.
963-
/// </summary>
964-
/// <param name="entries">The array of entries to enumerate.</param>
965-
/// <param name="length">The number of elements in the array.</param>
966969
[MethodImpl(MethodImplOptions.AggressiveInlining)]
967-
public FastEnumerator(Entry[] entries, int length)
970+
public SpanEnumerator(ReadOnlySpan<Entry> span)
968971
{
969-
// Convert array reference to a raw pointer (avoiding fixed blocks)
970-
_start = (Entry*)Unsafe.AsPointer(ref MemoryMarshal.GetArrayDataReference(entries));
971-
_end = _start + length; // Pointer to the end of the array
972-
_current = _start - 1; // Start before the first element (MoveNext() advances it)
972+
_span = span;
973+
_index = -1;
973974
}
974975

975-
/// <summary>
976-
/// Moves to the next element in the collection.
977-
/// </summary>
978-
/// <returns>True if the enumerator successfully moved to the next element, false if at the end.</returns>
979976
[MethodImpl(MethodImplOptions.AggressiveInlining)]
980977
public bool MoveNext()
981978
{
982-
_current++; // Move pointer to the next entry
983-
return _current < _end; // Check if within bounds
979+
int next = _index + 1;
980+
if (next < _span.Length)
981+
{
982+
_index = next;
983+
return true;
984+
}
985+
return false;
984986
}
985987

986-
/// <summary>
987-
/// Gets the current entry in the enumeration.
988-
/// </summary>
989-
public readonly Entry Current
988+
public ref readonly Entry Current
990989
{
991990
[MethodImpl(MethodImplOptions.AggressiveInlining)]
992-
get => *_current; // Dereference pointer to get the current element
991+
get => ref _span[_index];
993992
}
994-
995-
/// <summary>
996-
/// Gets the current element of the collection (explicit interface implementation).
997-
/// </summary>
998-
object IEnumerator.Current => Current;
999-
1000-
/// <summary>
1001-
/// Resets the enumerator to its initial position before the first element.
1002-
/// </summary>
1003-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
1004-
public void Reset() => _current = _start - 1;
1005-
1006-
/// <summary>
1007-
/// Releases resources used by the enumerator (not needed for structs).
1008-
/// </summary>
1009-
public void Dispose() { }
1010993
}
1011994

1012995
#endregion

src/Faster.Map.csproj

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,19 @@
55
<LangVersion>preview</LangVersion>
66
<TargetFrameworks>net10.0;net9.0;net8.0;net7.0</TargetFrameworks>
77
<LangVersion>Latest</LangVersion>
8+
<PublishRepositoryUrl>true</PublishRepositoryUrl>
9+
<EmbedUntrackedSources>true</EmbedUntrackedSources>
810
<Authors>Wiljan Ruizendaal</Authors>
911
<PackageReadmeFile>README.md</PackageReadmeFile>
1012
<Copyright>MIT</Copyright>
1113
<PackageReleaseNotes>
1214
Add Equals method to IHasher to eliminate virtual key comparisons
1315
</PackageReleaseNotes>
1416
<PackageProjectUrl>https://github.com/Wsm2110/Faster.Map</PackageProjectUrl>
15-
<AssemblyVersion>8.0.1</AssemblyVersion>
16-
<FileVersion>8.0.1</FileVersion>
17+
<AssemblyVersion>8.0.3</AssemblyVersion>
18+
<FileVersion>8.0.3</FileVersion>
1719
<Title>Fastest .net hashmap</Title>
18-
<Version>8.0.1</Version>
20+
<Version>8.0.3</Version>
1921
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
2022
<Description>
2123
Incredibly fast hashmap
@@ -59,6 +61,10 @@
5961
<PackageReference Include="System.IO.Hashing" Version="10.*" />
6062
</ItemGroup>
6163

64+
<ItemGroup>
65+
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
66+
</ItemGroup>
67+
6268
<Target Name="GenerateSnk" BeforeTargets="BeforeBuild" Condition="!Exists('$(ProjectDir)Faster.Map.snk')">
6369
<Exec Command="powershell -ExecutionPolicy Bypass -Command ^&#xD;&#xA; $csp = New-Object System.Security.Cryptography.RSACryptoServiceProvider(2048); ^&#xD;&#xA; $bytes = $csp.ExportCspBlob($true); ^&#xD;&#xA; [System.IO.File]::WriteAllBytes('$(ProjectDir)Faster.Map.snk', $bytes)" />
6470
</Target>

0 commit comments

Comments
 (0)