diff --git a/CHANGELOG.md b/CHANGELOG.md index 175c5aa..21383d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ - Added `Random.NextUnitVector2()` - Added `Random.NextUnitVector3()` - Added `Random.NextRotation()` +- Added `Rune.Repeat(int)` - Added `bool.GetBytes()` - Added `byte.GetBytes()` - Added `byte.IsEven()` diff --git a/X10D.Tests/src/Text/RuneTests.cs b/X10D.Tests/src/Text/RuneTests.cs new file mode 100644 index 0000000..e85a8a5 --- /dev/null +++ b/X10D.Tests/src/Text/RuneTests.cs @@ -0,0 +1,39 @@ +using System.Text; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using X10D.Text; + +namespace X10D.Tests.Text; + +[TestClass] +public class RuneTests +{ + [TestMethod] + public void RepeatShouldBeCorrect() + { + const string expected = "aaaaaaaaaa"; + var rune = new Rune('a'); + string actual = rune.Repeat(10); + + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void RepeatOneCountShouldBeLength1String() + { + string repeated = new Rune('a').Repeat(1); + Assert.AreEqual(1, repeated.Length); + Assert.AreEqual("a", repeated); + } + + [TestMethod] + public void RepeatZeroCountShouldBeEmpty() + { + Assert.AreEqual(string.Empty, new Rune('a').Repeat(0)); + } + + [TestMethod] + public void RepeatNegativeCountShouldThrow() + { + Assert.ThrowsException(() => new Rune('a').Repeat(-1)); + } +} diff --git a/X10D/src/Text/RuneExtensions.cs b/X10D/src/Text/RuneExtensions.cs new file mode 100644 index 0000000..9441773 --- /dev/null +++ b/X10D/src/Text/RuneExtensions.cs @@ -0,0 +1,47 @@ +using System.Text; + +namespace X10D.Text; + +/// +/// Extension methods for . +/// +public static class RuneExtensions +{ + /// + /// Returns a string composed of the current rune repeated a specified number of times. + /// + /// The rune to repeat. + /// The number of times to repeat. + /// + /// A composed of repeated times. + /// + public static string Repeat(this Rune value, int count) + { + if (count < 0) + { + throw new ArgumentOutOfRangeException(nameof(count), ExceptionMessages.CountMustBeGreaterThanOrEqualTo0); + } + + if (count == 0) + { + return string.Empty; + } + + if (count == 1) + { + return value.ToString(); + } + + int utf8SequenceLength = value.Utf8SequenceLength; + Span utf8 = stackalloc byte[utf8SequenceLength]; + value.EncodeToUtf8(utf8); + + Span buffer = stackalloc byte[utf8.Length * count]; + for (var index = 0; index < count; index++) + { + utf8.CopyTo(buffer.Slice(index * utf8.Length, utf8.Length)); + } + + return Encoding.UTF8.GetString(buffer); + } +}