Skip to content

Commit

Permalink
Add GetByteCount(Span) (#261)
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonCropp authored Dec 19, 2024
1 parent 0876e27 commit 7396cca
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 14 deletions.
2 changes: 1 addition & 1 deletion apiCount.include.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
**API count: 415**
**API count: 416**
3 changes: 2 additions & 1 deletion api_list.include.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@

#### Encoding

* `int GetBytes(Encoding, ReadOnlySpan<char>, Span<byte>)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.text.encoding.getbytes?#system-text-encoding-getbytes(system-readonlyspan((system-char))-system-span((system-byte))))
* `int GetByteCount(Encoding, ReadOnlySpan<char>)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.text.encoding.getbytecount#system-text-encoding-getbytecount(system-readonlyspan((system-char))))
* `int GetBytes(Encoding, ReadOnlySpan<char>, Span<byte>)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.text.encoding.getbytes#system-text-encoding-getbytes(system-readonlyspan((system-char))-system-span((system-byte))))
* `string GetString(Encoding, ReadOnlySpan<byte>)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.text.encoding.getstring#system-text-encoding-getstring(system-readonlyspan((system-byte))))


Expand Down
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -1212,7 +1212,7 @@ Enable by adding and MSBuild property `PolyGuard`

* `ArgumentException.ThrowIfNullOrEmpty` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.argumentexception.throwifnullorempty)
* `ArgumentException.ThrowIfNullOrWhiteSpace` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.argumentexception.throwifnullorwhitespace)
* `ArgumentNullException.ThrowIfNull` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.argumentnullexception.throwifnull?view=net-8.0)
* `ArgumentNullException.ThrowIfNull` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.argumentnullexception.throwifnull)

With the equivalent Guard APIs:

Expand Down
34 changes: 24 additions & 10 deletions src/Polyfill/Polyfill_Encoding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,49 +5,63 @@

#pragma warning disable

#if FeatureMemory && AllowUnsafeBlocks && !NETCOREAPP2_1_OR_GREATER
#if FeatureMemory

namespace Polyfills;

using System;

static partial class Polyfill
{
#if NETCOREAPP2_0 || NETFRAMEWORK || NETSTANDARD2_0
/// <summary>
/// When overridden in a derived class, calculates the number of bytes produced by encoding the characters in the specified character span.
/// </summary>
/// <param name="encoding"></param>
/// <param name="chars">The span of characters to encode.</param>
/// <returns>The number of bytes produced by encoding the specified character span.</returns>
//Link: https://learn.microsoft.com/en-us/dotnet/api/system.text.encoding.getbytecount#system-text-encoding-getbytecount(system-readonlyspan((system-char)))
public static int GetByteCount(this Encoding target, ReadOnlySpan<char> chars) =>
target.GetByteCount(chars.ToArray());
#endif

#if AllowUnsafeBlocks && !NETCOREAPP2_1_OR_GREATER
/// <summary>When overridden in a derived class, encodes into a span of bytes a set of characters from the specified read-only span.</summary>
/// <param name="chars">The span containing the set of characters to encode.</param>
/// <param name="bytes">The byte span to hold the encoded bytes.</param>
/// <returns>The number of encoded bytes.</returns>
//Link: https://learn.microsoft.com/en-us/dotnet/api/system.text.encoding.getbytes?#system-text-encoding-getbytes(system-readonlyspan((system-char))-system-span((system-byte)))
public static unsafe int GetBytes(this Encoding encoding, ReadOnlySpan<char> chars, Span<byte> bytes)
//Link: https://learn.microsoft.com/en-us/dotnet/api/system.text.encoding.getbytes#system-text-encoding-getbytes(system-readonlyspan((system-char))-system-span((system-byte)))
public static unsafe int GetBytes(this Encoding target, ReadOnlySpan<char> chars, Span<byte> bytes)
{
if (encoding is null)
if (target is null)
{
throw new ArgumentNullException(nameof(encoding));
throw new ArgumentNullException(nameof(target));
}

fixed (char* charsPtr = chars)
fixed (byte* bytesPtr = bytes)
{
return encoding.GetBytes(charsPtr, chars.Length, bytesPtr, bytes.Length);
return target.GetBytes(charsPtr, chars.Length, bytesPtr, bytes.Length);
}
}

/// <summary>When overridden in a derived class, decodes all the bytes in the specified byte span into a string.</summary>
/// <param name="bytes">A read-only byte span to decode to a Unicode string.</param>
/// <returns>A string that contains the decoded bytes from the provided read-only span.</returns>
//Link: https://learn.microsoft.com/en-us/dotnet/api/system.text.encoding.getstring#system-text-encoding-getstring(system-readonlyspan((system-byte)))
public static unsafe string GetString(this Encoding encoding, ReadOnlySpan<byte> bytes)
public static unsafe string GetString(this Encoding target, ReadOnlySpan<byte> bytes)
{
if (encoding is null)
if (target is null)
{
throw new ArgumentNullException(nameof(encoding));
throw new ArgumentNullException(nameof(target));
}

fixed (byte* bytesPtr = bytes)
{
return encoding.GetString(bytesPtr, bytes.Length);
return target.GetString(bytesPtr, bytes.Length);
}
}
#endif
}

#endif
40 changes: 40 additions & 0 deletions src/Tests/PolyfillTests_Encoding.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
partial class PolyfillTests
{
#if FeatureMemory
[Test]
public void Encoding_GetByteCount()
{
var encoding = Encoding.UTF8;
var chars = "Hello, World!".AsSpan();
var byteCount = encoding.GetByteCount(chars);
Assert.AreEqual(13, byteCount);
}
#endif

#if FeatureMemory && AllowUnsafeBlocks

[Test]
public void Encoding_GetString()
{
var array = (ReadOnlySpan<byte>)"value"u8.ToArray().AsSpan();
var result = Encoding.UTF8.GetString(array);
Assert.AreEqual("value", result);
}

[Test]
public void Encoding_GetBytes()
{
var encoding = Encoding.UTF8;
var chars = "Hello, World!".AsSpan();
var bytes = new byte[encoding.GetByteCount(chars)].AsSpan();

// Act
var byteCount = encoding.GetBytes(chars, bytes);

// Assert
Assert.AreEqual(encoding.GetByteCount(chars), byteCount);
Assert.AreEqual(encoding.GetBytes("Hello, World!"), bytes.ToArray());
}

#endif
}
1 change: 0 additions & 1 deletion src/Tests/PolyfillTests_Enum.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ public void Parse()
[Test]
public void TryParse()
{

var result = EnumPolyfill.TryParse<DayOfWeek>("Sunday".AsSpan(), out var dayOfWeek);
Assert.AreEqual(DayOfWeek.Sunday, dayOfWeek);
Assert.True(result);
Expand Down

0 comments on commit 7396cca

Please sign in to comment.