Skip to content

Commit

Permalink
Move rentedCharBuffer logic to TryParse helper
Browse files Browse the repository at this point in the history
  • Loading branch information
Jozkee committed Jul 18, 2023
1 parent 22bc1f7 commit 43fe8a8
Showing 1 changed file with 20 additions and 31 deletions.
Expand Up @@ -36,7 +36,6 @@ private static Half ReadCore(ref Utf8JsonReader reader)
Half result;

byte[]? rentedByteBuffer = null;
char[]? rentedCharBuffer = null;
int bufferLength = reader.ValueLength;

Span<byte> byteBuffer = bufferLength <= JsonConstants.StackallocByteThreshold
Expand All @@ -46,24 +45,12 @@ private static Half ReadCore(ref Utf8JsonReader reader)
int written = reader.CopyValue(byteBuffer);
byteBuffer = byteBuffer.Slice(0, written);

#if NET8_0_OR_GREATER
bool success = TryParse(byteBuffer, out result);
#else
// We need to transcode here instead of letting CopyValue do it for us because TryGetFloatingPointConstant only accepts ROS<byte>.
Span<char> charBuffer = stackalloc char[MaxFormatLength];
written = JsonReaderHelper.TranscodeHelper(byteBuffer, charBuffer);
bool success = TryParse(charBuffer, out result);
#endif
if (rentedByteBuffer != null)
{
ArrayPool<byte>.Shared.Return(rentedByteBuffer);
}

if (rentedCharBuffer != null)
{
ArrayPool<char>.Shared.Return(rentedCharBuffer);
}

if (!success)
{
ThrowHelper.ThrowFormatException(NumericType.Half);
Expand Down Expand Up @@ -186,31 +173,33 @@ private static void WriteFloatingPointConstant(Utf8JsonWriter writer, Half value

// Half.TryFormat/TryParse(ROS<byte>) are not available on .NET 7
// we need to use Half.TryFormat/TryParse(ROS<char>) in that case.
private static bool TryParse(
private static bool TryParse(ReadOnlySpan<byte> buffer, out Half result)
{
#if NET8_0_OR_GREATER
ReadOnlySpan<byte> buffer,
bool success = Half.TryParse(buffer, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out result);
#else
ReadOnlySpan<char> buffer,
char[]? rentedCharBuffer = null;

Span<char> charBuffer = buffer.Length <= JsonConstants.StackallocCharThreshold
? stackalloc char[JsonConstants.StackallocCharThreshold]
: (rentedCharBuffer = ArrayPool<char>.Shared.Rent(buffer.Length));

int written = JsonReaderHelper.TranscodeHelper(buffer, charBuffer);

bool success = Half.TryParse(charBuffer, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out result);

if (rentedCharBuffer != null)
{
ArrayPool<char>.Shared.Return(rentedCharBuffer);
}
#endif
out Half result)
{
bool success = Half.TryParse(buffer, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out result);

// Half.TryParse is more lax with floating-point literals than other S.T.Json floating-point types
// e.g: it parses "naN" successfully. Only succeed with the exact match.
#if NET8_0_OR_GREATER
ReadOnlySpan<byte> NaN = JsonConstants.NaNValue;
ReadOnlySpan<byte> PositiveInfinity = JsonConstants.PositiveInfinityValue;
ReadOnlySpan<byte> NegativeInfinity = JsonConstants.NegativeInfinityValue;
#else
const string NaN = "NaN";
const string PositiveInfinity = "Infinity";
const string NegativeInfinity = "-Infinity";
#endif
return success &&
(!Half.IsNaN(result) || buffer.SequenceEqual(NaN)) &&
(!Half.IsPositiveInfinity(result) || buffer.SequenceEqual(PositiveInfinity)) &&
(!Half.IsNegativeInfinity(result) || buffer.SequenceEqual(NegativeInfinity));
(!Half.IsNaN(result) || buffer.SequenceEqual(JsonConstants.NaNValue)) &&
(!Half.IsPositiveInfinity(result) || buffer.SequenceEqual(JsonConstants.PositiveInfinityValue)) &&
(!Half.IsNegativeInfinity(result) || buffer.SequenceEqual(JsonConstants.NegativeInfinityValue));
}

private static void Format(
Expand Down

0 comments on commit 43fe8a8

Please sign in to comment.