feat(opl): add ObjectPropertyList.Add(ReadOnlySpan<char>) overloads
This commit is contained in:
parent
a28a32f46d
commit
d35a527199
3 changed files with 99 additions and 0 deletions
|
|
@ -0,0 +1,61 @@
|
|||
using System;
|
||||
using System.Buffers.Binary;
|
||||
using System.Text;
|
||||
using Server;
|
||||
using Xunit;
|
||||
|
||||
namespace Server.Tests;
|
||||
|
||||
public class ObjectPropertyListSpanAddTests
|
||||
{
|
||||
// Decodes a terminated OPL buffer into (cliloc, argument) entries.
|
||||
// The OPL packet is big-endian (SpanWriter default), so use BinaryPrimitives.
|
||||
private static (int cliloc, string arg)[] Decode(ObjectPropertyList opl)
|
||||
{
|
||||
opl.Terminate();
|
||||
var buffer = opl.Buffer;
|
||||
var entries = new System.Collections.Generic.List<(int, string)>();
|
||||
var pos = 15; // header is 15 bytes
|
||||
while (true)
|
||||
{
|
||||
var cliloc = BinaryPrimitives.ReadInt32BigEndian(buffer.AsSpan(pos));
|
||||
pos += 4;
|
||||
if (cliloc == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
var byteLen = BinaryPrimitives.ReadUInt16BigEndian(buffer.AsSpan(pos));
|
||||
pos += 2;
|
||||
var arg = Encoding.Unicode.GetString(buffer, pos, byteLen);
|
||||
pos += byteLen;
|
||||
entries.Add((cliloc, arg));
|
||||
}
|
||||
|
||||
return entries.ToArray();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SpanAdd_ProducesSameBytesAsStringAdd()
|
||||
{
|
||||
var fromString = new ObjectPropertyList(null);
|
||||
fromString.Add("Hello World");
|
||||
|
||||
var fromSpan = new ObjectPropertyList(null);
|
||||
fromSpan.Add("Hello World".AsSpan());
|
||||
|
||||
Assert.Equal(Decode(fromString), Decode(fromSpan));
|
||||
Assert.Equal(fromString.Hash, fromSpan.Hash);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SpanAdd_WithNumber_EmitsClilocAndArgument()
|
||||
{
|
||||
var opl = new ObjectPropertyList(null);
|
||||
opl.Add(1070722, "Custom".AsSpan());
|
||||
|
||||
var entries = Decode(opl);
|
||||
Assert.Single(entries);
|
||||
Assert.Equal((1070722, "Custom"), entries[0]);
|
||||
}
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Server.Text;
|
||||
|
||||
|
|
@ -31,6 +32,9 @@ public interface IPropertyList : ISelfInterpolatedStringHandler
|
|||
/** Convenience method for $"{text}". */
|
||||
public void Add(string text);
|
||||
|
||||
public void Add(ReadOnlySpan<char> argument);
|
||||
public void Add(int number, ReadOnlySpan<char> argument);
|
||||
|
||||
/** Convenience method for $"{value}". */
|
||||
public void Add(int number, int value);
|
||||
|
||||
|
|
|
|||
|
|
@ -153,6 +153,40 @@ public sealed class ObjectPropertyList : IPropertyList, IDisposable
|
|||
public void AddLocalized(int value) => InternalAdd(GetStringNumber(), $"{value:#}");
|
||||
public void AddLocalized(int number, int value) => InternalAdd(number, $"{value:#}");
|
||||
|
||||
public void Add(ReadOnlySpan<char> argument) => InternalAdd(GetStringNumber(), argument);
|
||||
public void Add(int number, ReadOnlySpan<char> argument) => InternalAdd(number, argument);
|
||||
|
||||
private void InternalAdd(int number, ReadOnlySpan<char> chars)
|
||||
{
|
||||
if (number == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Header == 0)
|
||||
{
|
||||
Header = number;
|
||||
HeaderArgs = chars.ToString();
|
||||
}
|
||||
|
||||
AddHash(number);
|
||||
AddHash(string.GetHashCode(chars, StringComparison.Ordinal));
|
||||
|
||||
var strLength = chars.Length * 2;
|
||||
var length = _bufferPos + 6 + strLength;
|
||||
while (length > _buffer.Length)
|
||||
{
|
||||
Flush();
|
||||
}
|
||||
|
||||
var writer = new SpanWriter(_buffer.AsSpan(_bufferPos));
|
||||
writer.Write(number);
|
||||
writer.Write((ushort)strLength);
|
||||
writer.Write(chars, TextEncoding.UnicodeLE);
|
||||
|
||||
_bufferPos += writer.BytesWritten;
|
||||
}
|
||||
|
||||
private int GetStringNumber() => _stringNumbers[_stringNumbersIndex++ % _stringNumbers.Length];
|
||||
|
||||
// String Interpolation
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue