From 91b89458c175866212694e7b09aae0211cf9e3ce Mon Sep 17 00:00:00 2001 From: dajiaohuang Date: Fri, 16 Oct 2026 05:24:15 +0800 Subject: [PATCH] Copy only written formatting data into buffer writers --- .../Assets/Scripts/ZString/FormatHelper.cs | 6 +-- .../Scripts/ZString/Utf8ValueStringBuilder.cs | 2 +- src/ZString/FormatHelper.cs | 6 +-- src/ZString/FormatHelper.tt | 2 +- src/ZString/Utf8ValueStringBuilder.cs | 2 +- tests/ZString.Tests/RightAlignedBufferTest.cs | 53 +++++++++++++++++++ 6 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 tests/ZString.Tests/RightAlignedBufferTest.cs diff --git a/src/ZString.Unity/Assets/Scripts/ZString/FormatHelper.cs b/src/ZString.Unity/Assets/Scripts/ZString/FormatHelper.cs index de9846c..559ba5d 100644 --- a/src/ZString.Unity/Assets/Scripts/ZString/FormatHelper.cs +++ b/src/ZString.Unity/Assets/Scripts/ZString/FormatHelper.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Text; using System.Buffers; using System.Runtime.CompilerServices; @@ -82,7 +82,7 @@ private static void FormatToRightJustify(ref TBufferWriter sb, } var span = sb.GetSpan(charsWritten); - s.CopyTo(span); + s.Slice(0, charsWritten).CopyTo(span); sb.Advance(charsWritten); } } @@ -163,7 +163,7 @@ private static void FormatToRightJustify(ref TBufferWriter sb, } var span = sb.GetSpan(charsWritten); - s.CopyTo(span); + s.Slice(0, charsWritten).CopyTo(span); sb.Advance(charsWritten); } } diff --git a/src/ZString.Unity/Assets/Scripts/ZString/Utf8ValueStringBuilder.cs b/src/ZString.Unity/Assets/Scripts/ZString/Utf8ValueStringBuilder.cs index 19df488..c4a5e3e 100644 --- a/src/ZString.Unity/Assets/Scripts/ZString/Utf8ValueStringBuilder.cs +++ b/src/ZString.Unity/Assets/Scripts/ZString/Utf8ValueStringBuilder.cs @@ -460,7 +460,7 @@ private void AppendFormatInternal(T arg, int width, StandardFormat format, st Append(' ', padding); // TODO Fill Method is too slow. } - s.CopyTo(GetSpan(charsWritten)); + s.Slice(0, charsWritten).CopyTo(GetSpan(charsWritten)); Advance(charsWritten); } } diff --git a/src/ZString/FormatHelper.cs b/src/ZString/FormatHelper.cs index de9846c..559ba5d 100644 --- a/src/ZString/FormatHelper.cs +++ b/src/ZString/FormatHelper.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Text; using System.Buffers; using System.Runtime.CompilerServices; @@ -82,7 +82,7 @@ private static void FormatToRightJustify(ref TBufferWriter sb, } var span = sb.GetSpan(charsWritten); - s.CopyTo(span); + s.Slice(0, charsWritten).CopyTo(span); sb.Advance(charsWritten); } } @@ -163,7 +163,7 @@ private static void FormatToRightJustify(ref TBufferWriter sb, } var span = sb.GetSpan(charsWritten); - s.CopyTo(span); + s.Slice(0, charsWritten).CopyTo(span); sb.Advance(charsWritten); } } diff --git a/src/ZString/FormatHelper.tt b/src/ZString/FormatHelper.tt index d6ed5aa..3399c7b 100644 --- a/src/ZString/FormatHelper.tt +++ b/src/ZString/FormatHelper.tt @@ -94,7 +94,7 @@ namespace Cysharp.Text } var span = sb.GetSpan(charsWritten); - s.CopyTo(span); + s.Slice(0, charsWritten).CopyTo(span); sb.Advance(charsWritten); } } diff --git a/src/ZString/Utf8ValueStringBuilder.cs b/src/ZString/Utf8ValueStringBuilder.cs index 19df488..c4a5e3e 100644 --- a/src/ZString/Utf8ValueStringBuilder.cs +++ b/src/ZString/Utf8ValueStringBuilder.cs @@ -460,7 +460,7 @@ private void AppendFormatInternal(T arg, int width, StandardFormat format, st Append(' ', padding); // TODO Fill Method is too slow. } - s.CopyTo(GetSpan(charsWritten)); + s.Slice(0, charsWritten).CopyTo(GetSpan(charsWritten)); Advance(charsWritten); } } diff --git a/tests/ZString.Tests/RightAlignedBufferTest.cs b/tests/ZString.Tests/RightAlignedBufferTest.cs new file mode 100644 index 0000000..4488c57 --- /dev/null +++ b/tests/ZString.Tests/RightAlignedBufferTest.cs @@ -0,0 +1,53 @@ +using Cysharp.Text; +using FluentAssertions; +using System; +using System.Buffers; +using System.Text; +using Xunit; + +namespace ZStringTests +{ + public class RightAlignedBufferTest + { + [Theory] + [InlineData(1)] + [InlineData(100)] + public void PreparedUtf16UsesOnlyFormattedCharacters(int value) + { + var writer = new ArrayBufferWriter(1); + ZString.PrepareUtf16("{0,2}").FormatTo(ref writer, value); + new string(writer.WrittenSpan).Should().Be(string.Format("{0,2}", value)); + } + + [Theory] + [InlineData(false, 1)] + [InlineData(false, 100)] + [InlineData(true, 1)] + [InlineData(true, 100)] + public void Utf8UsesOnlyFormattedBytes(bool prepared, int value) + { + var writer = new ArrayBufferWriter(1); + if (prepared) + { + ZString.PrepareUtf8("{0,2}").FormatTo(ref writer, value); + } + else + { + ZString.Utf8Format(writer, "{0,2}", value); + } + Encoding.UTF8.GetString(writer.WrittenSpan).Should().Be(string.Format("{0,2}", value)); + } + + [Fact] + public void Utf8BuilderUsesOnlyFormattedBytesNearCapacity() + { + using (var builder = ZString.CreateUtf8StringBuilder()) + { + var prefix = new string('x', builder.GetSpan(0).Length - 2); + builder.Append(prefix); + builder.AppendFormat("{0,1}", 1); + builder.ToString().Should().Be(prefix + "1"); + } + } + } +}