ReadStack
struct ReadStack
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
namespace System.Text.Json
{
[StructLayout(LayoutKind.Auto)]
[DebuggerDisplay("{DebuggerDisplay,nq}")]
internal struct ReadStack
{
public ReadStackFrame Current;
private ReadStackFrame[] _stack;
private int _count;
private int _continuationCount;
public ReferenceResolver ReferenceResolver;
public bool SupportContinuation;
public string ReferenceId;
public object PolymorphicTypeDiscriminator;
public bool PreserveReferences;
public ref ReadStackFrame Parent {
[System.Runtime.CompilerServices.IsReadOnly]
get {
return ref _stack[_count - 2];
}
}
public JsonPropertyInfo ParentProperty {
[System.Runtime.CompilerServices.IsReadOnly]
get {
if (!Current.HasParentObject)
return null;
return Parent.JsonPropertyInfo;
}
}
public bool IsContinuation {
[System.Runtime.CompilerServices.IsReadOnly]
get {
return _continuationCount != 0;
}
}
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string DebuggerDisplay {
get {
return $"""{JsonPath()}""{Current.JsonTypeInfo?.Converter.ConverterStrategy}""{Current.JsonTypeInfo?.Type.Name}";
}
}
private void EnsurePushCapacity()
{
if (_stack == null)
_stack = new ReadStackFrame[4];
else if (_count - 1 == _stack.Length) {
Array.Resize(ref _stack, 2 * _stack.Length);
}
}
internal void Initialize(JsonTypeInfo jsonTypeInfo, bool supportContinuation = false)
{
JsonSerializerOptions options = jsonTypeInfo.Options;
if (options.ReferenceHandlingStrategy == ReferenceHandlingStrategy.Preserve) {
ReferenceResolver = options.ReferenceHandler.CreateResolver(false);
PreserveReferences = true;
}
Current.JsonTypeInfo = jsonTypeInfo;
Current.JsonPropertyInfo = jsonTypeInfo.PropertyInfoForTypeInfo;
Current.NumberHandling = Current.JsonPropertyInfo.EffectiveNumberHandling;
Current.CanContainMetadata = (PreserveReferences || (jsonTypeInfo.PolymorphicTypeResolver?.UsesTypeDiscriminators ?? false));
SupportContinuation = supportContinuation;
}
public void Push()
{
if (_continuationCount == 0) {
if (_count == 0)
_count = 1;
else {
JsonTypeInfo jsonTypeInfo = Current.JsonPropertyInfo?.JsonTypeInfo ?? Current.CtorArgumentState.JsonParameterInfo.JsonTypeInfo;
JsonNumberHandling? numberHandling = Current.NumberHandling;
EnsurePushCapacity();
_stack[_count - 1] = Current;
Current = default(ReadStackFrame);
_count++;
Current.JsonTypeInfo = jsonTypeInfo;
Current.JsonPropertyInfo = jsonTypeInfo.PropertyInfoForTypeInfo;
Current.NumberHandling = (numberHandling ?? Current.JsonPropertyInfo.EffectiveNumberHandling);
Current.CanContainMetadata = (PreserveReferences || (jsonTypeInfo.PolymorphicTypeResolver?.UsesTypeDiscriminators ?? false));
}
} else {
if (_count++ > 0) {
_stack[_count - 2] = Current;
Current = _stack[_count - 1];
}
if (_continuationCount == _count)
_continuationCount = 0;
}
SetConstructorArgumentState();
}
public void Pop(bool success)
{
if (!success) {
if (_continuationCount == 0) {
if (_count == 1) {
_continuationCount = 1;
_count = 0;
return;
}
EnsurePushCapacity();
_continuationCount = _count--;
} else if (--_count == 0) {
return;
}
_stack[_count] = Current;
Current = _stack[_count - 1];
} else if (--_count > 0) {
Current = _stack[_count - 1];
}
}
public JsonConverter InitializePolymorphicReEntry(JsonTypeInfo derivedJsonTypeInfo)
{
Current.PolymorphicJsonTypeInfo = Current.JsonTypeInfo;
Current.JsonTypeInfo = derivedJsonTypeInfo;
Current.JsonPropertyInfo = derivedJsonTypeInfo.PropertyInfoForTypeInfo;
ref JsonNumberHandling? numberHandling = ref Current.NumberHandling;
JsonNumberHandling? nullable = numberHandling;
if (!nullable.HasValue)
numberHandling = Current.JsonPropertyInfo.NumberHandling;
Current.PolymorphicSerializationState = PolymorphicSerializationState.PolymorphicReEntryStarted;
SetConstructorArgumentState();
return derivedJsonTypeInfo.Converter;
}
public JsonConverter ResumePolymorphicReEntry()
{
ref JsonTypeInfo jsonTypeInfo = ref Current.JsonTypeInfo;
ref JsonTypeInfo polymorphicJsonTypeInfo = ref Current.PolymorphicJsonTypeInfo;
JsonTypeInfo polymorphicJsonTypeInfo2 = Current.PolymorphicJsonTypeInfo;
JsonTypeInfo jsonTypeInfo2 = Current.JsonTypeInfo;
jsonTypeInfo = polymorphicJsonTypeInfo2;
polymorphicJsonTypeInfo = jsonTypeInfo2;
Current.PolymorphicSerializationState = PolymorphicSerializationState.PolymorphicReEntryStarted;
return Current.JsonTypeInfo.Converter;
}
public void ExitPolymorphicConverter(bool success)
{
ref JsonTypeInfo jsonTypeInfo = ref Current.JsonTypeInfo;
ref JsonTypeInfo polymorphicJsonTypeInfo = ref Current.PolymorphicJsonTypeInfo;
JsonTypeInfo polymorphicJsonTypeInfo2 = Current.PolymorphicJsonTypeInfo;
JsonTypeInfo jsonTypeInfo2 = Current.JsonTypeInfo;
jsonTypeInfo = polymorphicJsonTypeInfo2;
polymorphicJsonTypeInfo = jsonTypeInfo2;
Current.PolymorphicSerializationState = ((!success) ? PolymorphicSerializationState.PolymorphicReEntrySuspended : PolymorphicSerializationState.None);
}
public string JsonPath()
{
StringBuilder stringBuilder = new StringBuilder("$");
int continuationCount = _continuationCount;
(int, bool) valueTuple;
switch (continuationCount) {
case 0:
valueTuple = (_count - 1, true);
break;
case 1:
valueTuple = (0, true);
break;
default:
valueTuple = (continuationCount, false);
break;
}
(int, bool) valueTuple2 = valueTuple;
int item = valueTuple2.Item1;
bool item2 = valueTuple2.Item2;
for (int i = 0; i < item; i++) {
<JsonPath>g__AppendStackFrame|22_0(stringBuilder, ref _stack[i]);
}
if (item2)
<JsonPath>g__AppendStackFrame|22_0(stringBuilder, ref Current);
return stringBuilder.ToString();
}
public JsonTypeInfo GetTopJsonTypeInfoWithParameterizedConstructor()
{
for (int i = 0; i < _count - 1; i++) {
if (_stack[i].JsonTypeInfo.UsesParameterizedConstructor)
return _stack[i].JsonTypeInfo;
}
return Current.JsonTypeInfo;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void SetConstructorArgumentState()
{
if (Current.JsonTypeInfo.UsesParameterizedConstructor) {
ref ArgumentState ctorArgumentState = ref Current.CtorArgumentState;
if (ctorArgumentState == null)
ctorArgumentState = new ArgumentState();
}
}
}
}