< Summary

Line coverage
19%
Covered lines: 11
Uncovered lines: 45
Coverable lines: 56
Total lines: 182
Line coverage: 19.6%
Branch coverage
10%
Covered branches: 2
Total branches: 20
Branch coverage: 10%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
EndConstructorParameter()100%110%
EndProperty()100%110%
EndElement()100%11100%
IsProcessingDictionary()100%110%
IsProcessingEnumerable()100%11100%
MarkPropertyAsRead(...)0%660%
InitializePropertiesValidationState(...)50%4457.14%
ValidateAllRequiredPropertiesAreRead(...)0%440%

File(s)

C:\h\w\B31A098C\w\BB5A0A33\e\runtime-utils\Runner\runtime\src\libraries\System.Text.Json\src\System\Text\Json\Serialization\ReadStackFrame.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.Collections;
 5using System.Collections.Generic;
 6using System.Diagnostics;
 7using System.Runtime.CompilerServices;
 8using System.Runtime.InteropServices;
 9using System.Text.Json.Serialization;
 10using System.Text.Json.Serialization.Metadata;
 11
 12namespace System.Text.Json
 13{
 14    [StructLayout(LayoutKind.Auto)]
 15    [DebuggerDisplay("{DebuggerDisplay,nq}")]
 16    internal struct ReadStackFrame
 17    {
 18        // Current property values.
 19        public JsonPropertyInfo? JsonPropertyInfo;
 20        public StackFramePropertyState PropertyState;
 21        public bool UseExtensionProperty;
 22
 23        // Support JSON Path on exceptions and non-string Dictionary keys.
 24        // This is Utf8 since we don't want to convert to string until an exception is thrown.
 25        // For dictionary keys we don't want to convert to TKey until we have both key and value when parsing the dictio
 26        public byte[]? JsonPropertyName;
 27        public string? JsonPropertyNameAsString; // This is used for string dictionary keys and re-entry cases that spec
 28
 29        // Stores the non-string dictionary keys for continuation.
 30        public object? DictionaryKey;
 31
 32        /// <summary>
 33        /// Records the Utf8JsonReader Depth at the start of the current value.
 34        /// </summary>
 35        public int OriginalDepth;
 36#if DEBUG
 37        /// <summary>
 38        /// Records the Utf8JsonReader TokenType at the start of the current value.
 39        /// Only used to validate debug builds.
 40        /// </summary>
 41        public JsonTokenType OriginalTokenType;
 42#endif
 43
 44        // Current object (POCO or IEnumerable).
 45        public object? ReturnValue; // The current return value used for re-entry.
 46        public JsonTypeInfo JsonTypeInfo;
 47        public StackFrameObjectState ObjectState; // State tracking the current object.
 48
 49        // Current object can contain metadata
 50        public bool CanContainMetadata;
 51        public MetadataPropertyName LatestMetadataPropertyName;
 52        public MetadataPropertyName MetadataPropertyNames;
 53
 54        // Serialization state for value serialized by the current frame.
 55        public PolymorphicSerializationState PolymorphicSerializationState;
 56
 57        // Holds any entered polymorphic JsonTypeInfo metadata.
 58        public JsonTypeInfo? PolymorphicJsonTypeInfo;
 59
 60        // Gets the initial JsonTypeInfo metadata used when deserializing the current value.
 61        public JsonTypeInfo BaseJsonTypeInfo
 062            => PolymorphicSerializationState == PolymorphicSerializationState.PolymorphicReEntryStarted
 063                ? PolymorphicJsonTypeInfo!
 064                : JsonTypeInfo;
 65
 66        // For performance, we order the properties by the first deserialize and PropertyIndex helps find the right slot
 67        public int PropertyIndex;
 68
 69        // Tracks newly encounentered UTF-8 encoded properties during the current deserialization, to be appended to the
 70        public PropertyRefCacheBuilder? PropertyRefCacheBuilder;
 71
 72        // Holds relevant state when deserializing objects with parameterized constructors.
 73        public ArgumentState? CtorArgumentState;
 74
 75        // Whether to use custom number handling.
 76        public JsonNumberHandling? NumberHandling;
 77
 78        // Represents known (non-extension) properties which have value assigned.
 79        // Each bit corresponds to a property.
 80        // False means that property is not set (not yet occurred in the payload).
 81        // Length of the BitArray is equal to number of non-extension properties.
 82        // Every JsonPropertyInfo has PropertyIndex property which maps to an index in this BitArray.
 83        public BitArray? AssignedProperties;
 84
 85        // Tracks state related to property population.
 86        public bool HasParentObject;
 87        public bool IsPopulating;
 88
 89        public void EndConstructorParameter()
 090        {
 091            CtorArgumentState!.JsonParameterInfo = null;
 092            JsonPropertyName = null;
 093            PropertyState = StackFramePropertyState.None;
 094        }
 95
 96        public void EndProperty()
 097        {
 098            JsonPropertyInfo = null!;
 099            JsonPropertyName = null;
 0100            JsonPropertyNameAsString = null;
 0101            PropertyState = StackFramePropertyState.None;
 102
 103            // No need to clear these since they are overwritten each time:
 104            //  NumberHandling
 105            //  UseExtensionProperty
 0106        }
 107
 108        public void EndElement()
 10109        {
 10110            JsonPropertyNameAsString = null;
 10111            PropertyState = StackFramePropertyState.None;
 10112        }
 113
 114        /// <summary>
 115        /// Is the current object a Dictionary.
 116        /// </summary>
 117        public bool IsProcessingDictionary()
 0118        {
 0119            return JsonTypeInfo.Kind is JsonTypeInfoKind.Dictionary;
 0120        }
 121
 122        /// <summary>
 123        /// Is the current object an Enumerable.
 124        /// </summary>
 125        public bool IsProcessingEnumerable()
 57506126        {
 57506127            return JsonTypeInfo.Kind is JsonTypeInfoKind.Enumerable;
 57506128        }
 129
 130        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 131        public void MarkPropertyAsRead(JsonPropertyInfo propertyInfo)
 0132        {
 0133            if (AssignedProperties is { })
 0134            {
 0135                if (!propertyInfo.Options.AllowDuplicateProperties)
 0136                {
 0137                    if (AssignedProperties[propertyInfo.PropertyIndex])
 0138                    {
 0139                        ThrowHelper.ThrowJsonException_DuplicatePropertyNotAllowed(propertyInfo);
 140                    }
 0141                }
 142
 0143                AssignedProperties[propertyInfo.PropertyIndex] = true;
 0144            }
 0145        }
 146
 147        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 148        internal void InitializePropertiesValidationState(JsonTypeInfo typeInfo)
 30149        {
 30150            Debug.Assert(AssignedProperties is null);
 151
 30152            if (typeInfo.ShouldTrackRequiredProperties || !typeInfo.Options.AllowDuplicateProperties)
 0153            {
 154                // This may be slightly larger than required (e.g. if there's an extension property)
 0155                AssignedProperties = new BitArray(typeInfo.Properties.Count);
 0156            }
 30157        }
 158
 159        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 160        internal void ValidateAllRequiredPropertiesAreRead(JsonTypeInfo typeInfo)
 0161        {
 0162            if (typeInfo.ShouldTrackRequiredProperties)
 0163            {
 0164                Debug.Assert(AssignedProperties is not null);
 0165                Debug.Assert(typeInfo.OptionalPropertiesMask is not null);
 166
 167                // All properties must be either assigned or optional
 0168                BitArray assignedOrNotRequiredPropertiesSet = AssignedProperties.Or(typeInfo.OptionalPropertiesMask);
 169
 0170                if (!assignedOrNotRequiredPropertiesSet.HasAllSet())
 0171                {
 0172                    ThrowHelper.ThrowJsonException_JsonRequiredPropertyMissing(typeInfo, assignedOrNotRequiredProperties
 173                }
 0174            }
 175
 0176            AssignedProperties = null;
 0177        }
 178
 179        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
 0180        private string DebuggerDisplay => $"ConverterStrategy.{JsonTypeInfo?.Converter.ConverterStrategy}, {JsonTypeInfo
 181    }
 182}