< Summary

Line coverage
0%
Covered lines: 0
Uncovered lines: 70
Coverable lines: 70
Total lines: 152
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 67
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)0%220%
GetValue()0%440%
TryGetValue(...)0%440%
.cctor()100%110%
DetermineValueKind(...)0%660%
DetermineValueKindForType(...)0%51510%

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonValueOfT.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.Diagnostics;
 5using System.Diagnostics.CodeAnalysis;
 6
 7namespace System.Text.Json.Nodes
 8{
 9    [DebuggerDisplay("{ToJsonString(),nq}")]
 10    [DebuggerTypeProxy(typeof(JsonValue<>.DebugView))]
 11    internal abstract class JsonValue<TValue> : JsonValue
 12    {
 13        internal readonly TValue Value; // keep as a field for direct access to avoid copies
 14
 015        protected JsonValue(TValue value, JsonNodeOptions? options) : base(options)
 016        {
 017            Debug.Assert(value is not null);
 018            Debug.Assert(value is not JsonElement or JsonElement { ValueKind: not JsonValueKind.Null });
 019            Debug.Assert(value is not JsonNode);
 020            Value = value;
 021        }
 22
 23        public override T GetValue<T>()
 024        {
 25            // If no conversion is needed, just return the raw value.
 026            if (Value is T returnValue)
 027            {
 028                return returnValue;
 29            }
 30
 31            // Currently we do not support other conversions.
 32            // Generics (and also boxing) do not support standard cast operators say from 'long' to 'int',
 33            //  so attempting to cast here would throw InvalidCastException.
 034            ThrowHelper.ThrowInvalidOperationException_NodeUnableToConvert(typeof(TValue), typeof(T));
 35            return default!;
 036        }
 37
 38        public override bool TryGetValue<T>([NotNullWhen(true)] out T value)
 039        {
 40            // If no conversion is needed, just return the raw value.
 041            if (Value is T returnValue)
 042            {
 043                value = returnValue;
 044                return true;
 45            }
 46
 47            // Currently we do not support other conversions.
 48            // Generics (and also boxing) do not support standard cast operators say from 'long' to 'int',
 49            //  so attempting to cast here would throw InvalidCastException.
 050            value = default!;
 051            return false;
 052        }
 53
 54        /// <summary>
 55        /// Whether <typeparamref name="TValue"/> is a built-in type that admits primitive JsonValue representation.
 56        /// </summary>
 057        internal static bool TypeIsSupportedPrimitive => s_valueKind.HasValue;
 058        private static readonly JsonValueKind? s_valueKind = DetermineValueKindForType(typeof(TValue));
 59
 60        /// <summary>
 61        /// Determines the JsonValueKind for the value of a built-in type.
 62        /// </summary>
 63        private protected static JsonValueKind DetermineValueKind(TValue value)
 064        {
 065            Debug.Assert(s_valueKind is not null, "Should only be invoked for types that are supported primitives.");
 66
 067            if (value is bool boolean)
 068            {
 69                // Boolean requires special handling since kind varies by value.
 070                return boolean ? JsonValueKind.True : JsonValueKind.False;
 71            }
 72
 073            return s_valueKind.Value;
 074        }
 75
 76        /// <summary>
 77        /// Precomputes the JsonValueKind for a given built-in type where possible.
 78        /// </summary>
 79        private static JsonValueKind? DetermineValueKindForType(Type type)
 080        {
 081            if (type.IsEnum)
 082            {
 083                return null; // Can vary depending on converter configuration and value.
 84            }
 85
 086            if (Nullable.GetUnderlyingType(type) is Type underlyingType)
 087            {
 88                // Because JsonNode excludes null values, we can identify with the value kind of the underlying type.
 089                return DetermineValueKindForType(underlyingType);
 90            }
 91
 092            if (type == typeof(DateTime) || type == typeof(DateTimeOffset) || type == typeof(TimeSpan) ||
 093#if NET
 094                type == typeof(DateOnly) || type == typeof(TimeOnly) ||
 095#endif
 096                type == typeof(Guid) || type == typeof(Uri) || type == typeof(Version))
 097            {
 098                return JsonValueKind.String;
 99            }
 100
 101#if NET
 0102            if (type == typeof(Half) || type == typeof(UInt128) || type == typeof(Int128))
 0103            {
 0104                return JsonValueKind.Number;
 105            }
 106#endif
 107#if NET11_0_OR_GREATER
 0108            if (type == typeof(System.Numerics.BFloat16) || type == typeof(System.Numerics.Decimal32) ||
 0109                type == typeof(System.Numerics.Decimal64) || type == typeof(System.Numerics.Decimal128))
 0110            {
 0111                return JsonValueKind.Number;
 112            }
 113#endif
 0114            return Type.GetTypeCode(type) switch
 0115            {
 0116                TypeCode.Boolean => JsonValueKind.Undefined, // Can vary dependending on value.
 0117                TypeCode.SByte => JsonValueKind.Number,
 0118                TypeCode.Byte => JsonValueKind.Number,
 0119                TypeCode.Int16 => JsonValueKind.Number,
 0120                TypeCode.UInt16 => JsonValueKind.Number,
 0121                TypeCode.Int32 => JsonValueKind.Number,
 0122                TypeCode.UInt32 => JsonValueKind.Number,
 0123                TypeCode.Int64 => JsonValueKind.Number,
 0124                TypeCode.UInt64 => JsonValueKind.Number,
 0125                TypeCode.Single => JsonValueKind.Number,
 0126                TypeCode.Double => JsonValueKind.Number,
 0127                TypeCode.Decimal => JsonValueKind.Number,
 0128                TypeCode.String => JsonValueKind.String,
 0129                TypeCode.Char => JsonValueKind.String,
 0130                _ => null,
 0131            };
 0132        }
 133
 134        [ExcludeFromCodeCoverage] // Justification = "Design-time"
 135        [DebuggerDisplay("{Json,nq}")]
 136        private sealed class DebugView
 137        {
 138            [DebuggerBrowsable(DebuggerBrowsableState.Never)]
 139            public JsonValue<TValue> _node;
 140
 141            public DebugView(JsonValue<TValue> node)
 142            {
 143                _node = node;
 144            }
 145
 146            public string Json => _node.ToJsonString();
 147            public string Path => _node.GetPath();
 148            public TValue? Value => _node.Value;
 149        }
 150    }
 151}
 152