Skip to content

Commit fdde198

Browse files
committed
feat: Builder can be used in foreach loops
1 parent 31e9533 commit fdde198

File tree

4 files changed

+68
-0
lines changed

4 files changed

+68
-0
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ All notable changes to **ValueStringBuilder** will be documented in this file. T
66

77
## [Unreleased]
88

9+
### Added
10+
11+
- Added custom enumerator to `ValueStringBuilder` so it can be used in `foreach` loops
12+
913
## [1.17.0] - 2023-04-13
1014

1115
### Added
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using System.Runtime.CompilerServices;
2+
using System.Runtime.InteropServices;
3+
4+
namespace LinkDotNet.StringBuilder;
5+
6+
public ref partial struct ValueStringBuilder
7+
{
8+
public readonly Enumerator GetEnumerator() => new(buffer[..bufferPosition]);
9+
10+
/// <summary>Enumerates the elements of a <see cref="Span{T}"/>.</summary>
11+
[StructLayout(LayoutKind.Auto)]
12+
public ref struct Enumerator
13+
{
14+
private readonly Span<char> span;
15+
private int index;
16+
17+
/// <summary>Initializes a new instance of the <see cref="Enumerator"/> struct.</summary>
18+
/// <param name="span">The span to enumerate.</param>
19+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
20+
internal Enumerator(Span<char> span)
21+
{
22+
this.span = span;
23+
index = -1;
24+
}
25+
26+
/// <summary>Gets the element at the current position of the enumerator.</summary>
27+
public ref char Current
28+
{
29+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
30+
get => ref span[index];
31+
}
32+
33+
/// <summary>Advances the enumerator to the next element of the span.</summary>
34+
/// <returns>True if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the span.</returns>
35+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
36+
public bool MoveNext()
37+
{
38+
var nextIndex = index + 1;
39+
if (nextIndex < span.Length)
40+
{
41+
index = nextIndex;
42+
return true;
43+
}
44+
45+
return false;
46+
}
47+
}
48+
}

stylecop.analyzers.ruleset

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
<Rule Id="CA1009" Action="Warning"/>
1010
<Rule Id="CA1016" Action="Warning"/>
1111
<Rule Id="CA1033" Action="Warning"/>
12+
<Rule Id="CA1034" Action="None"/>
13+
<Rule Id="CA1033" Action="Warning"/>
1214
<Rule Id="CA1049" Action="Warning"/>
1315
<Rule Id="CA1060" Action="Warning"/>
1416
<Rule Id="CA1061" Action="Warning"/>

tests/LinkDotNet.StringBuilder.UnitTests/ValueStringBuilderTests.cs

+14
Original file line numberDiff line numberDiff line change
@@ -489,4 +489,18 @@ public void GivenAString_WhenCallingToStringWithRange_ThenShouldReturnSubstring(
489489

490490
builder.ToString(1..4).Should().Be("ell");
491491
}
492+
493+
[Fact]
494+
public void GivenAString_WhenEnumerating_ThenShouldReturnCharacters()
495+
{
496+
using var builder = new ValueStringBuilder("Hello World");
497+
var output = string.Empty;
498+
499+
foreach (var c in builder)
500+
{
501+
output += c;
502+
}
503+
504+
output.Should().Be("Hello World");
505+
}
492506
}

0 commit comments

Comments
 (0)