Esempio n. 1
0
 internal sealed override object?ReadCoreAsObject(
     ref Utf8JsonReader reader,
     JsonSerializerOptions options,
     scoped ref ReadStack state)
 {
     return(ReadCore(ref reader, options, ref state));
 }
Esempio n. 2
0
        internal sealed override object ReadCoreAsObject(
            ref Utf8JsonReader reader,
            JsonSerializerOptions options,
            scoped ref ReadStack state)
        {
            Debug.Fail("We should never get here.");

            throw new InvalidOperationException();
        }
Esempio n. 3
0
        /// <summary>
        /// Used to support JsonObject as an extension property in a loosely-typed, trimmable manner.
        /// </summary>
        internal virtual void ReadElementAndSetProperty(
            object obj,
            string propertyName,
            ref Utf8JsonReader reader,
            JsonSerializerOptions options,
            scoped ref ReadStack state)
        {
            Debug.Fail("Should not be reachable.");

            throw new InvalidOperationException();
        }
        public static void ThrowNotSupportedException_ObjectWithParameterizedCtorRefMetadataNotSupported(
            ReadOnlySpan <byte> propertyName,
            ref Utf8JsonReader reader,
            scoped ref ReadStack state)
        {
            JsonTypeInfo jsonTypeInfo = state.GetTopJsonTypeInfoWithParameterizedConstructor();

            state.Current.JsonPropertyName = propertyName.ToArray();

            NotSupportedException ex = new NotSupportedException(
                SR.Format(SR.ObjectWithParameterizedCtorRefMetadataNotSupported, jsonTypeInfo.Type));

            ThrowNotSupportedException(ref state, reader, ex);
        }
Esempio n. 5
0
        internal override void ReadElementAndSetProperty(
            object obj,
            string propertyName,
            ref Utf8JsonReader reader,
            JsonSerializerOptions options,
            scoped ref ReadStack state)
        {
            bool success = JsonNodeConverter.Instance.TryRead(ref reader, typeof(JsonNode), options, ref state, out JsonNode? value);

            Debug.Assert(success); // Node converters are not resumable.

            Debug.Assert(obj is JsonObject);
            JsonObject jObject = (JsonObject)obj;

            Debug.Assert(value == null || value is JsonNode);
            JsonNode?jNodeValue = value;

            jObject[propertyName] = jNodeValue;
        }
Esempio n. 6
0
 internal T?ReadCore(
     ref Utf8JsonReader reader,
     JsonSerializerOptions options,
     scoped ref ReadStack state)
 {
     try
     {
         if (!state.IsContinuation)
         {
             if (!SingleValueReadWithReadAhead(RequiresReadAhead, ref reader, ref state))
             {
                 if (state.SupportContinuation)
                 {
                     // If a Stream-based scenario, return the actual value previously found;
                     // this may or may not be the final pass through here.
                     state.BytesConsumed += reader.BytesConsumed;
                     if (state.Current.ReturnValue == null)
                     {
                         // Avoid returning null for value types.
                         return(default);
Esempio n. 7
0
 internal static ReadOnlySpan <byte> GetPropertyName(
     scoped ref ReadStack state,
        internal static bool DoSingleValueReadWithReadAhead(ref Utf8JsonReader reader, scoped ref ReadStack state)
        {
            // When we're reading ahead we always have to save the state as we don't know if the next token
            // is an opening object or an array brace.
            Utf8JsonReader restore = reader;

            if (!reader.Read())
            {
                return(false);
            }

            // Perform the actual read-ahead.
            JsonTokenType tokenType = reader.TokenType;

            if (tokenType is JsonTokenType.StartObject or JsonTokenType.StartArray)
            {
                // Attempt to skip to make sure we have all the data we need.
                bool complete = reader.TrySkip();

                // We need to restore the state in all cases as we need to be positioned back before
                // the current token to either attempt to skip again or to actually read the value.
                reader = restore;

                if (!complete)
                {
                    // Couldn't read to the end of the object, exit out to get more data in the buffer.
                    return(false);
                }

                // Success, requeue the reader to the start token.
                reader.ReadWithVerify();
                Debug.Assert(tokenType == reader.TokenType);
            }

            return(true);
        }
        internal static bool SingleValueReadWithReadAhead(bool requiresReadAhead, ref Utf8JsonReader reader, scoped ref ReadStack state)
        {
            bool readAhead = requiresReadAhead && state.ReadAhead;

            if (!readAhead)
            {
                return(reader.Read());
            }

            return(DoSingleValueReadWithReadAhead(ref reader, ref state));
        }
Esempio n. 10
0
 public bool TryReadToAny(out ReadOnlySpan <T> span, scoped ReadOnlySpan <T> delimiters, bool advancePastDelimiter = true)
Esempio n. 11
0
        internal static bool TryReadMetadata(JsonConverter converter, JsonTypeInfo jsonTypeInfo, ref Utf8JsonReader reader, scoped ref ReadStack state)
        {
            Debug.Assert(state.Current.ObjectState == StackFrameObjectState.StartToken);
            Debug.Assert(state.Current.CanContainMetadata);

            while (true)
            {
                if (state.Current.PropertyState == StackFramePropertyState.None)
                {
                    state.Current.PropertyState = StackFramePropertyState.ReadName;

                    // Read the property name.
                    if (!reader.Read())
                    {
                        return(false);
                    }
                }

                if (state.Current.PropertyState < StackFramePropertyState.Name)
                {
                    if (reader.TokenType == JsonTokenType.EndObject)
                    {
                        // Read the entire object while parsing for metadata.
                        return(true);
                    }

                    // We just read a property. The only valid next tokens are EndObject and PropertyName.
                    Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);

                    if (state.Current.MetadataPropertyNames.HasFlag(MetadataPropertyName.Ref))
                    {
                        // No properties whatsoever should follow a $ref property.
                        ThrowHelper.ThrowJsonException_MetadataReferenceObjectCannotContainOtherProperties(reader.GetSpan(), ref state);
                    }

                    ReadOnlySpan <byte> propertyName = reader.GetSpan();
                    switch (state.Current.LatestMetadataPropertyName = GetMetadataPropertyName(propertyName, jsonTypeInfo.PolymorphicTypeResolver))
                    {
                    case MetadataPropertyName.Id:
                        state.Current.JsonPropertyName = s_idPropertyName;

                        if (state.ReferenceResolver is null)
                        {
                            // Found an $id property in a type that doesn't support reference preservation
                            ThrowHelper.ThrowJsonException_MetadataUnexpectedProperty(propertyName, ref state);
                        }
                        if ((state.Current.MetadataPropertyNames & (MetadataPropertyName.Id | MetadataPropertyName.Ref)) != 0)
                        {
                            // No $id or $ref properties should precede $id properties.
                            ThrowHelper.ThrowJsonException_MetadataIdIsNotFirstProperty(propertyName, ref state);
                        }
                        if (!converter.CanHaveMetadata)
                        {
                            // Should not be permitted unless the converter is capable of handling metadata.
                            ThrowHelper.ThrowJsonException_MetadataCannotParsePreservedObjectIntoImmutable(converter.TypeToConvert);
                        }

                        break;

                    case MetadataPropertyName.Ref:
                        state.Current.JsonPropertyName = s_refPropertyName;

                        if (state.ReferenceResolver is null)
                        {
                            // Found a $ref property in a type that doesn't support reference preservation
                            ThrowHelper.ThrowJsonException_MetadataUnexpectedProperty(propertyName, ref state);
                        }
                        if (converter.IsValueType)
                        {
                            // Should not be permitted if the converter is a struct.
                            ThrowHelper.ThrowJsonException_MetadataInvalidReferenceToValueType(converter.TypeToConvert);
                        }
                        if (state.Current.MetadataPropertyNames != 0)
                        {
                            // No metadata properties should precede a $ref property.
                            ThrowHelper.ThrowJsonException_MetadataReferenceObjectCannotContainOtherProperties(reader.GetSpan(), ref state);
                        }

                        break;

                    case MetadataPropertyName.Type:
                        state.Current.JsonPropertyName = jsonTypeInfo.PolymorphicTypeResolver?.TypeDiscriminatorPropertyNameUtf8 ?? s_typePropertyName;

                        if (jsonTypeInfo.PolymorphicTypeResolver is null)
                        {
                            // Found a $type property in a type that doesn't support polymorphism
                            ThrowHelper.ThrowJsonException_MetadataUnexpectedProperty(propertyName, ref state);
                        }
                        if (state.PolymorphicTypeDiscriminator != null)
                        {
                            ThrowHelper.ThrowJsonException_MetadataDuplicateTypeProperty();
                        }

                        break;

                    case MetadataPropertyName.Values:
                        state.Current.JsonPropertyName = s_valuesPropertyName;

                        if (state.Current.MetadataPropertyNames == MetadataPropertyName.None)
                        {
                            // Cannot have a $values property unless there are preceding metadata properties.
                            ThrowHelper.ThrowJsonException_MetadataStandaloneValuesProperty(ref state, propertyName);
                        }

                        break;

                    default:
                        Debug.Assert(state.Current.LatestMetadataPropertyName == MetadataPropertyName.None);

                        // Encountered a non-metadata property, exit the reader.
                        return(true);
                    }

                    state.Current.PropertyState = StackFramePropertyState.Name;
                }

                if (state.Current.PropertyState < StackFramePropertyState.ReadValue)
                {
                    state.Current.PropertyState = StackFramePropertyState.ReadValue;

                    // Read the property value.
                    if (!reader.Read())
                    {
                        return(false);
                    }
                }

                Debug.Assert(state.Current.PropertyState == StackFramePropertyState.ReadValue);

                switch (state.Current.LatestMetadataPropertyName)
                {
                case MetadataPropertyName.Id:
                    if (reader.TokenType != JsonTokenType.String)
                    {
                        ThrowHelper.ThrowJsonException_MetadataValueWasNotString(reader.TokenType);
                    }

                    if (state.ReferenceId != null)
                    {
                        ThrowHelper.ThrowNotSupportedException_ObjectWithParameterizedCtorRefMetadataNotSupported(s_refPropertyName, ref reader, ref state);
                    }

                    state.ReferenceId = reader.GetString();
                    break;

                case MetadataPropertyName.Ref:
                    if (reader.TokenType != JsonTokenType.String)
                    {
                        ThrowHelper.ThrowJsonException_MetadataValueWasNotString(reader.TokenType);
                    }

                    if (state.ReferenceId != null)
                    {
                        ThrowHelper.ThrowNotSupportedException_ObjectWithParameterizedCtorRefMetadataNotSupported(s_refPropertyName, ref reader, ref state);
                    }

                    state.ReferenceId = reader.GetString();
                    break;

                case MetadataPropertyName.Type:
                    Debug.Assert(state.PolymorphicTypeDiscriminator == null);

                    switch (reader.TokenType)
                    {
                    case JsonTokenType.String:
                        state.PolymorphicTypeDiscriminator = reader.GetString();
                        break;

                    case JsonTokenType.Number:
                        state.PolymorphicTypeDiscriminator = reader.GetInt32();
                        break;

                    default:
                        ThrowHelper.ThrowJsonException_MetadataValueWasNotString(reader.TokenType);
                        break;
                    }

                    break;

                case MetadataPropertyName.Values:

                    if (reader.TokenType != JsonTokenType.StartArray)
                    {
                        ThrowHelper.ThrowJsonException_MetadataValuesInvalidToken(reader.TokenType);
                    }

                    state.Current.PropertyState          = StackFramePropertyState.None;
                    state.Current.MetadataPropertyNames |= state.Current.LatestMetadataPropertyName;
                    return(true);    // "$values" property contains the nested payload, exit the metadata reader now.

                default:
                    Debug.Fail("Non-metadata properties should not reach this stage.");
                    break;
                }

                state.Current.MetadataPropertyNames |= state.Current.LatestMetadataPropertyName;
                state.Current.PropertyState          = StackFramePropertyState.None;
                state.Current.JsonPropertyName       = null;
            }
        }
Esempio n. 12
0
 private void RecordNewSeenOrThrow(scoped ref AttributeKind seenAttributes, AttributeKind newAttribute)
Esempio n. 13
0
 internal abstract bool OnTryReadAsObject(ref Utf8JsonReader reader, JsonSerializerOptions options, scoped ref ReadStack state, out object?value);
Esempio n. 14
0
 /// <summary>
 /// Loosely-typed ReadCore() that forwards to strongly-typed ReadCore().
 /// </summary>
 internal abstract object?ReadCoreAsObject(ref Utf8JsonReader reader, JsonSerializerOptions options, scoped ref ReadStack state);
Esempio n. 15
0
        private static TValue?ReadCore <TValue>(ref Utf8JsonReader reader, JsonTypeInfo jsonTypeInfo, scoped ref ReadStack state)
        {
            if (jsonTypeInfo is JsonTypeInfo <TValue> typedInfo)
            {
                // Call the strongly-typed ReadCore that will not box structs.
                return(typedInfo.EffectiveConverter.ReadCore(ref reader, typedInfo.Options, ref state));
            }

            // The non-generic API was called.
            object?value = jsonTypeInfo.Converter.ReadCoreAsObject(ref reader, jsonTypeInfo.Options, ref state);

            Debug.Assert(value is null or TValue);
            return((TValue?)value);
        }
Esempio n. 16
0
 protected override bool ReadAndCacheConstructorArgument(
     scoped ref ReadStack state,
Esempio n. 17
0
 internal static bool TryHandleReferenceFromJsonElement(
     ref Utf8JsonReader reader,
     scoped ref ReadStack state,
 internal sealed override bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, scoped ref ReadStack state, [MaybeNullWhen(false)] out T value)
Esempio n. 19
0
 _extraConfiguration?.Invoke(scoped, universalCommands);
 /// <summary>Writes the specified character span to the handler.</summary>
 /// <param name="value">The span to write.</param>
 public void AppendFormatted(scoped ReadOnlySpan <char> value)
Esempio n. 21
0
 internal sealed override bool OnTryReadAsObject(
     ref Utf8JsonReader reader,
     JsonSerializerOptions options,
     scoped ref ReadStack state,
 protected sealed override bool ReadAndCacheConstructorArgument(scoped ref ReadStack state, ref Utf8JsonReader reader, JsonParameterInfo jsonParameterInfo)
        private static Utf8JsonReader GetReaderScopedToNextValue(ref Utf8JsonReader reader, scoped ref ReadStack state)
        {
            // Advances the provided reader, validating that it is pointing to a complete JSON value.
            // If successful, returns a new Utf8JsonReader that is scoped to the next value, reusing existing buffers.

            ReadOnlySpan <byte>     valueSpan     = default;
            ReadOnlySequence <byte> valueSequence = default;

            try
            {
                switch (reader.TokenType)
                {
                // A new reader was created and has never been read,
                // so we need to move to the first token.
                // (or a reader has terminated and we're about to throw)
                case JsonTokenType.None:
                // Using a reader loop the caller has identified a property they wish to
                // hydrate into a JsonDocument. Move to the value first.
                case JsonTokenType.PropertyName:
                {
                    if (!reader.Read())
                    {
                        ThrowHelper.ThrowJsonReaderException(ref reader, ExceptionResource.ExpectedOneCompleteToken);
                    }
                    break;
                }
                }

                switch (reader.TokenType)
                {
                // Any of the "value start" states are acceptable.
                case JsonTokenType.StartObject:
                case JsonTokenType.StartArray:
                    long startingOffset = reader.TokenStartIndex;

                    if (!reader.TrySkip())
                    {
                        ThrowHelper.ThrowJsonReaderException(ref reader, ExceptionResource.NotEnoughData);
                    }

                    long totalLength = reader.BytesConsumed - startingOffset;
                    ReadOnlySequence <byte> sequence = reader.OriginalSequence;

                    if (sequence.IsEmpty)
                    {
                        valueSpan = reader.OriginalSpan.Slice(
                            checked ((int)startingOffset),
                            checked ((int)totalLength));
                    }
                    else
                    {
                        valueSequence = sequence.Slice(startingOffset, totalLength);
                    }

                    Debug.Assert(reader.TokenType is JsonTokenType.EndObject or JsonTokenType.EndArray);
                    break;

                // Single-token values
                case JsonTokenType.Number:
                case JsonTokenType.True:
                case JsonTokenType.False:
                case JsonTokenType.Null:
                    if (reader.HasValueSequence)
                    {
                        valueSequence = reader.ValueSequence;
                    }
                    else
                    {
                        valueSpan = reader.ValueSpan;
                    }

                    break;

                // String's ValueSequence/ValueSpan omits the quotes, we need them back.
                case JsonTokenType.String:
                    ReadOnlySequence <byte> originalSequence = reader.OriginalSequence;

                    if (originalSequence.IsEmpty)
                    {
                        // Since the quoted string fit in a ReadOnlySpan originally
                        // the contents length plus the two quotes can't overflow.
                        int payloadLength = reader.ValueSpan.Length + 2;
                        Debug.Assert(payloadLength > 1);

                        ReadOnlySpan <byte> readerSpan = reader.OriginalSpan;

                        Debug.Assert(
                            readerSpan[(int)reader.TokenStartIndex] == (byte)'"',
                            $"Calculated span starts with {readerSpan[(int)reader.TokenStartIndex]}");

                        Debug.Assert(
                            readerSpan[(int)reader.TokenStartIndex + payloadLength - 1] == (byte)'"',
                            $"Calculated span ends with {readerSpan[(int)reader.TokenStartIndex + payloadLength - 1]}");

                        valueSpan = readerSpan.Slice((int)reader.TokenStartIndex, payloadLength);
                    }
                    else
                    {
                        long payloadLength = reader.HasValueSequence
                                ? reader.ValueSequence.Length + 2
                                : reader.ValueSpan.Length + 2;

                        valueSequence = originalSequence.Slice(reader.TokenStartIndex, payloadLength);
                        Debug.Assert(
                            valueSequence.First.Span[0] == (byte)'"',
                            $"Calculated sequence starts with {valueSequence.First.Span[0]}");

                        Debug.Assert(
                            valueSequence.ToArray()[payloadLength - 1] == (byte)'"',
                            $"Calculated sequence ends with {valueSequence.ToArray()[payloadLength - 1]}");
                    }

                    break;

                default:
                    byte displayByte = reader.HasValueSequence
                            ? reader.ValueSequence.First.Span[0]
                            : reader.ValueSpan[0];

                    ThrowHelper.ThrowJsonReaderException(
                        ref reader,
                        ExceptionResource.ExpectedStartOfValueNotFound,
                        displayByte);

                    break;
                }
            }
            catch (JsonReaderException ex)
            {
                // Re-throw with Path information.
                ThrowHelper.ReThrowWithPath(ref state, ex);
            }

            Debug.Assert(!valueSpan.IsEmpty ^ !valueSequence.IsEmpty);

            return(valueSpan.IsEmpty
                ? new Utf8JsonReader(valueSequence, reader.CurrentState.Options)
                : new Utf8JsonReader(valueSpan, reader.CurrentState.Options));
        }
 internal override bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, scoped ref ReadStack state, out T? value)
 public static void ReThrowWithPath(scoped ref ReadStack state, JsonReaderException ex)
Esempio n. 26
0
 private static void DispatchEx(scoped ref StackFrameIterator frameIter, ref ExInfo exInfo, uint startIdx)
Esempio n. 27
0
            const int StackThreshold = 64; // arbitrary limit to avoid too much space on stack

            static bool ShouldStackAlloc(IList?list, scoped ref IntPtr[]?lease, out Span <IntPtr> span)