dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.91k stars 4.63k forks source link

[API Proposal]: Non-allocating Span based APIs for Hex conversion #58937

Open javiercn opened 2 years ago

javiercn commented 2 years ago

Background and motivation

.NET 5.0 added ToHexString to allow computing Hex. However all the available APIs materialize into a string. In other words, there are no Try span based APIs as there are for Base64, which forces the intermediate allocation of the string when you want to further process the result.

It's not clear to me if this was explicitly excluded from the public API or an oversight. My expectation since we introduced span and friends on the BCL and runtime is for non-allocating span based APIs to be available for all these types of low level operations.

(As an example here where we wanted to use something like this to call ToLowerInvariant on it afterwards)

API Proposal

namespace System;

 public static class Convert
 {
      // Similar set of span based overloads as for Base64. Not including all for brevity.
      public bool TryToHexChars(ReadOnlySpan<byte> bytes, Span<char> chars, out int written);
 }

API Usage

Span<bytes> bytes = stackalloc byte[32];
Span<char> hexChars = stackalloc byte[64];

if(Convert.TryToHexChars(bytes, hexChars, out var written))
{
   ...
}

Risks

No response

ghost commented 2 years ago

Tagging subscribers to this area: @GrabYourPitchForks, @dotnet/area-system-memory See info in area-owners.md if you want to be subscribed.

Issue Details
### Background and motivation .NET 5.0 added `ToHexString` to allow computing Hex. However all the available APIs materialize into a string. In other words, there are no `Try` span based APIs as there are for Base64, which forces the intermediate allocation of the string when you want to further process the result. It's not clear to me if this was explicitly excluded from the public API or an oversight. My expectation since we introduced span and friends on the BCL and runtime is for non-allocating span based APIs to be available for all these types of low level operations. (As an example [here](https://github.com/dotnet/aspnetcore/pull/36368#discussion_r706039158) where we wanted to use something like this to call ToLowerInvariant on it afterwards) ### API Proposal ```C# namespace System; public static class Convert { // Similar set of span based overloads as for Base64. Not including all for brevity. public bool TryToHexChars(Span bytes, Span chars, out int written); } ``` ### API Usage ```C# Span bytes = stackalloc byte[32]; Span hexChars = stackalloc byte[64]; if(Convert.TryToHexChars(bytes, hexChars, out var written)) { ... } ``` ### Risks _No response_
Author: javiercn
Assignees: -
Labels: `api-suggestion`, `area-System.Memory`, `untriaged`
Milestone: -
EgorBo commented 2 years ago

If you need it for byte[] array you can do something like:

MemoryMarshal.Read<ulong>(byteArray).TryFormat(dst, out int written, "X");

in a loop.

nil4 commented 2 years ago

Shouldn't bytes be a ReadOnlySpan<byte> if it is the input value? That is:

-public bool TryToHexChars(Span<byte> bytes, Span<char> chars, out int written);
+public bool TryToHexChars(ReadOnlySpan<byte> bytes, Span<char> chars, out int written);
ghost commented 2 years ago

Tagging subscribers to this area: @dotnet/area-system-runtime See info in area-owners.md if you want to be subscribed.

Issue Details
### Background and motivation .NET 5.0 added `ToHexString` to allow computing Hex. However all the available APIs materialize into a string. In other words, there are no `Try` span based APIs as there are for Base64, which forces the intermediate allocation of the string when you want to further process the result. It's not clear to me if this was explicitly excluded from the public API or an oversight. My expectation since we introduced span and friends on the BCL and runtime is for non-allocating span based APIs to be available for all these types of low level operations. (As an example [here](https://github.com/dotnet/aspnetcore/pull/36368#discussion_r706039158) where we wanted to use something like this to call ToLowerInvariant on it afterwards) ### API Proposal ```C# namespace System; public static class Convert { // Similar set of span based overloads as for Base64. Not including all for brevity. public bool TryToHexChars(Span bytes, Span chars, out int written); } ``` ### API Usage ```C# Span bytes = stackalloc byte[32]; Span hexChars = stackalloc byte[64]; if(Convert.TryToHexChars(bytes, hexChars, out var written)) { ... } ``` ### Risks _No response_
Author: javiercn
Assignees: -
Labels: `api-suggestion`, `area-System.Runtime`, `untriaged`
Milestone: -
javiercn commented 2 years ago

@nil4 that's correct.