Skip to content

Commit

Permalink
feat: Builder can be used in foreach loops
Browse files Browse the repository at this point in the history
  • Loading branch information
linkdotnet committed Jun 8, 2023
1 parent 31e9533 commit fdde198
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ All notable changes to **ValueStringBuilder** will be documented in this file. T

## [Unreleased]

### Added

- Added custom enumerator to `ValueStringBuilder` so it can be used in `foreach` loops

## [1.17.0] - 2023-04-13

### Added
Expand Down
48 changes: 48 additions & 0 deletions src/LinkDotNet.StringBuilder/ValueStringBuilder.Enumerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace LinkDotNet.StringBuilder;

public ref partial struct ValueStringBuilder
{
public readonly Enumerator GetEnumerator() => new(buffer[..bufferPosition]);

/// <summary>Enumerates the elements of a <see cref="Span{T}"/>.</summary>
[StructLayout(LayoutKind.Auto)]
public ref struct Enumerator
{
private readonly Span<char> span;
private int index;

/// <summary>Initializes a new instance of the <see cref="Enumerator"/> struct.</summary>
/// <param name="span">The span to enumerate.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal Enumerator(Span<char> span)
{
this.span = span;
index = -1;
}

/// <summary>Gets the element at the current position of the enumerator.</summary>
public ref char Current
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => ref span[index];
}

/// <summary>Advances the enumerator to the next element of the span.</summary>
/// <returns>True if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the span.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool MoveNext()
{
var nextIndex = index + 1;
if (nextIndex < span.Length)
{
index = nextIndex;
return true;
}

return false;
}
}
}
2 changes: 2 additions & 0 deletions stylecop.analyzers.ruleset
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
<Rule Id="CA1009" Action="Warning"/>
<Rule Id="CA1016" Action="Warning"/>
<Rule Id="CA1033" Action="Warning"/>
<Rule Id="CA1034" Action="None"/>
<Rule Id="CA1033" Action="Warning"/>
<Rule Id="CA1049" Action="Warning"/>
<Rule Id="CA1060" Action="Warning"/>
<Rule Id="CA1061" Action="Warning"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -489,4 +489,18 @@ public void GivenAString_WhenCallingToStringWithRange_ThenShouldReturnSubstring(

builder.ToString(1..4).Should().Be("ell");
}

[Fact]
public void GivenAString_WhenEnumerating_ThenShouldReturnCharacters()
{
using var builder = new ValueStringBuilder("Hello World");
var output = string.Empty;

foreach (var c in builder)
{
output += c;
}

output.Should().Be("Hello World");
}
}

0 comments on commit fdde198

Please sign in to comment.