< Summary

Information
Line coverage
41%
Covered lines: 61
Uncovered lines: 85
Coverable lines: 146
Total lines: 232
Line coverage: 41.7%
Branch coverage
51%
Covered branches: 33
Total branches: 64
Branch coverage: 51.5%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor()100%11100%
Read(...)62.5%8877.77%
Write(...)0%660%
ReadCore(...)62.5%8880%
WriteCore(...)100%110%
ReadAsPropertyNameCore(...)100%110%
WriteAsPropertyNameCore(...)100%110%
ReadNumberWithCustomHandling(...)66.66%121263.63%
WriteNumberWithCustomHandling(...)0%440%
GetSchema(...)100%110%
TryGetFloatingPointConstant(...)50%8856.52%
WriteFloatingPointConstant(...)0%660%
TryParse(...)91.66%1212100%
Format(...)100%110%

File(s)

C:\h\w\B31A098C\w\BB5A0A33\e\runtime-utils\Runner\runtime\src\libraries\System.Text.Json\src\System\Text\Json\Serialization\Converters\Value\HalfConverter.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Buffers;
 5using System.Diagnostics;
 6using System.Globalization;
 7using System.Text.Json.Nodes;
 8using System.Text.Json.Schema;
 9
 10namespace System.Text.Json.Serialization.Converters
 11{
 12    internal sealed class HalfConverter : JsonPrimitiveConverter<Half>
 13    {
 14        private const int MaxFormatLength = 20;
 15        private const int MaxUnescapedFormatLength = JsonConstants.MaximumFloatingPointConstantLength * JsonConstants.Ma
 16
 117        public HalfConverter()
 118        {
 119            IsInternalConverterForNumberType = true;
 120        }
 21
 22        public override Half Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
 17423        {
 17424            if (options?.NumberHandling is not null and not JsonNumberHandling.Strict)
 025            {
 026                return ReadNumberWithCustomHandling(ref reader, options.NumberHandling, options);
 27            }
 28
 17429            if (reader.TokenType != JsonTokenType.Number)
 14830            {
 14831                ThrowHelper.ThrowInvalidOperationException_ExpectedNumber(reader.TokenType);
 32            }
 33
 2634            return ReadCore(ref reader);
 2035        }
 36
 37        public override void Write(Utf8JsonWriter writer, Half value, JsonSerializerOptions options)
 038        {
 039            if (options?.NumberHandling is not null and not JsonNumberHandling.Strict)
 040            {
 041                WriteNumberWithCustomHandling(writer, value, options.NumberHandling);
 042                return;
 43            }
 44
 045            WriteCore(writer, value);
 046        }
 47
 48        private static Half ReadCore(ref Utf8JsonReader reader)
 23049        {
 50            Half result;
 51
 23052            byte[]? rentedByteBuffer = null;
 23053            int bufferLength = reader.ValueLength;
 54
 23055            Span<byte> byteBuffer = bufferLength <= JsonConstants.StackallocByteThreshold
 23056                ? stackalloc byte[JsonConstants.StackallocByteThreshold]
 23057                : (rentedByteBuffer = ArrayPool<byte>.Shared.Rent(bufferLength));
 58
 23059            int written = reader.CopyValue(byteBuffer);
 22060            byteBuffer = byteBuffer.Slice(0, written);
 61
 22062            bool success = TryParse(byteBuffer, out result);
 22063            if (rentedByteBuffer != null)
 064            {
 065                ArrayPool<byte>.Shared.Return(rentedByteBuffer);
 066            }
 67
 22068            if (!success)
 14269            {
 14270                ThrowHelper.ThrowFormatException(NumericType.Half);
 071            }
 72
 7873            Debug.Assert(!Half.IsNaN(result) && !Half.IsInfinity(result));
 7874            return result;
 7875        }
 76
 77        private static void WriteCore(Utf8JsonWriter writer, Half value)
 078        {
 079            Span<byte> buffer = stackalloc byte[MaxFormatLength];
 080            Format(buffer, value, out int written);
 081            writer.WriteRawValue(buffer.Slice(0, written));
 082        }
 83
 84        internal override Half ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptio
 085        {
 086            Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);
 087            return ReadCore(ref reader);
 088        }
 89
 90        internal override void WriteAsPropertyNameCore(Utf8JsonWriter writer, Half value, JsonSerializerOptions options,
 091        {
 092            Span<byte> buffer = stackalloc byte[MaxFormatLength];
 093            Format(buffer, value, out int written);
 094            writer.WritePropertyName(buffer.Slice(0, written));
 095        }
 96
 97        internal override Half ReadNumberWithCustomHandling(ref Utf8JsonReader reader, JsonNumberHandling handling, Json
 46098        {
 46099            if (reader.TokenType == JsonTokenType.String)
 172100            {
 172101                if ((JsonNumberHandling.AllowReadingFromString & handling) != 0)
 140102                {
 140103                    if (TryGetFloatingPointConstant(ref reader, out Half value))
 0104                    {
 0105                        return value;
 106                    }
 107
 102108                    return ReadCore(ref reader);
 109                }
 32110                else if ((JsonNumberHandling.AllowNamedFloatingPointLiterals & handling) != 0)
 0111                {
 0112                    if (!TryGetFloatingPointConstant(ref reader, out Half value))
 0113                    {
 0114                        ThrowHelper.ThrowFormatException(NumericType.Half);
 0115                    }
 116
 0117                    return value;
 118                }
 32119            }
 120
 320121            if (reader.TokenType != JsonTokenType.Number)
 218122            {
 218123                ThrowHelper.ThrowInvalidOperationException_ExpectedNumber(reader.TokenType);
 124            }
 125
 102126            return ReadCore(ref reader);
 58127        }
 128
 129        internal override void WriteNumberWithCustomHandling(Utf8JsonWriter writer, Half value, JsonNumberHandling handl
 0130        {
 0131            if ((JsonNumberHandling.WriteAsString & handling) != 0)
 0132            {
 133                const byte Quote = JsonConstants.Quote;
 0134                Span<byte> buffer = stackalloc byte[MaxFormatLength + 2];
 0135                buffer[0] = Quote;
 0136                Format(buffer.Slice(1), value, out int written);
 137
 0138                int length = written + 2;
 0139                buffer[length - 1] = Quote;
 0140                writer.WriteRawValue(buffer.Slice(0, length));
 0141            }
 0142            else if ((JsonNumberHandling.AllowNamedFloatingPointLiterals & handling) != 0)
 0143            {
 0144                WriteFloatingPointConstant(writer, value);
 0145            }
 146            else
 0147            {
 0148                WriteCore(writer, value);
 0149            }
 0150        }
 151
 152        internal override JsonSchema? GetSchema(JsonNumberHandling numberHandling) =>
 0153            GetSchemaForNumericType(JsonSchemaType.Number, numberHandling, isIeeeFloatingPoint: true);
 154
 155        private static bool TryGetFloatingPointConstant(ref Utf8JsonReader reader, out Half value)
 140156        {
 157            scoped Span<byte> buffer;
 158
 159            // Only checking for length 10 or less for constants
 140160            if (reader.ValueIsEscaped)
 0161            {
 0162                if (reader.ValueLength > MaxUnescapedFormatLength)
 0163                {
 0164                    value = default;
 0165                    return false;
 166                }
 167
 0168                buffer = stackalloc byte[MaxUnescapedFormatLength];
 0169            }
 170            else
 140171            {
 140172                if (reader.ValueLength > JsonConstants.MaximumFloatingPointConstantLength)
 12173                {
 12174                    value = default;
 12175                    return false;
 176                }
 177
 128178                buffer = stackalloc byte[JsonConstants.MaximumFloatingPointConstantLength];
 128179            }
 180
 128181            int written = reader.CopyValue(buffer);
 182
 90183            if (written > JsonConstants.MaximumFloatingPointConstantLength)
 0184            {
 0185                value = default;
 0186                return false;
 187            }
 188
 90189            return JsonReaderHelper.TryGetFloatingPointConstant(buffer.Slice(0, written), out value);
 102190        }
 191
 192        private static void WriteFloatingPointConstant(Utf8JsonWriter writer, Half value)
 0193        {
 0194            if (Half.IsNaN(value))
 0195            {
 0196                writer.WriteNumberValueAsStringUnescaped(JsonConstants.NaNValue);
 0197            }
 0198            else if (Half.IsPositiveInfinity(value))
 0199            {
 0200                writer.WriteNumberValueAsStringUnescaped(JsonConstants.PositiveInfinityValue);
 0201            }
 0202            else if (Half.IsNegativeInfinity(value))
 0203            {
 0204                writer.WriteNumberValueAsStringUnescaped(JsonConstants.NegativeInfinityValue);
 0205            }
 206            else
 0207            {
 0208                WriteCore(writer, value);
 0209            }
 0210        }
 211
 212        private static bool TryParse(ReadOnlySpan<byte> buffer, out Half result)
 220213        {
 220214            bool success = Half.TryParse(buffer, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.Invariant
 215
 216            // Half.TryParse is more lax with floating-point literals than other S.T.Json floating-point types
 217            // e.g: it parses "naN" successfully. Only succeed with the exact match.
 220218            return success &&
 220219                (!Half.IsNaN(result) || buffer.SequenceEqual(JsonConstants.NaNValue)) &&
 220220                (!Half.IsPositiveInfinity(result) || buffer.SequenceEqual(JsonConstants.PositiveInfinityValue)) &&
 220221                (!Half.IsNegativeInfinity(result) || buffer.SequenceEqual(JsonConstants.NegativeInfinityValue));
 220222        }
 223
 224        private static void Format(
 225            Span<byte> destination,
 226            Half value, out int written)
 0227        {
 0228            bool formattedSuccessfully = value.TryFormat(destination, out written, provider: CultureInfo.InvariantCultur
 0229            Debug.Assert(formattedSuccessfully);
 0230        }
 231    }
 232}