private static bool HandleNull(ref Utf8JsonReader reader, ref ReadStack state, JsonSerializerOptions options)
        {
            if (state.Current.Skip())
            {
                return(false);
            }

            JsonPropertyInfo propertyInfo = state.Current.JsonPropertyInfo;

            if (!propertyInfo.CanBeNull)
            {
                ThrowHelper.ThrowJsonReaderException_DeserializeCannotBeNull(reader, state);
            }

            if (state.Current.IsEnumerable() || state.Current.IsPropertyEnumerable())
            {
                ReadStackFrame.SetReturnValue(null, options, ref state.Current);
                return(false);
            }

            if (state.Current.ReturnValue == null)
            {
                return(true);
            }

            if (!propertyInfo.IgnoreNullPropertyValueOnRead(options))
            {
                state.Current.JsonPropertyInfo.SetValueAsObject(state.Current.ReturnValue, null, options);
            }

            return(false);
        }
Пример #2
0
        protected override object CreateObject(ref ReadStackFrame frame)
        {
            var    args = frame.PropertyValueCache;
            string id   = (string)args[nameof(TimeZoneInfo.Id)];

            try
            {
                TimeZoneInfo ti = TimeZoneInfo.FindSystemTimeZoneById(id);
                if (ti != null)
                {
                    return(ti);
                }
            }
            catch (TimeZoneNotFoundException)
            {
            }
            return(TimeZoneInfo.CreateCustomTimeZone(
                       id,
                       (TimeSpan)args[nameof(TimeZoneInfo.BaseUtcOffset)],
                       (string)args[nameof(TimeZoneInfo.DisplayName)],
                       (string)args[nameof(TimeZoneInfo.StandardName)],
                       (string)args[nameof(TimeZoneInfo.DaylightName)],
                       (TimeZoneInfo.AdjustmentRule[])args[nameof(TimeZoneInfo.GetAdjustmentRules)]
                       ));
        }
        private static bool HandleEndObject(JsonSerializerOptions options, ref ReadStack state)
        {
            bool isLastFrame = state.IsLastFrame;

            if (state.Current.Drain)
            {
                state.Pop();
                return(isLastFrame);
            }

            state.Current.JsonClassInfo.UpdateSortedPropertyCache(ref state.Current);

            object value = state.Current.ReturnValue;

            if (isLastFrame)
            {
                state.Current.Reset();
                state.Current.ReturnValue = value;
                return(true);
            }

            state.Pop();
            ReadStackFrame.SetReturnValue(value, options, ref state.Current);
            return(false);
        }
Пример #4
0
        protected override object CreateObject(ref ReadStackFrame frame)
        {
            var createObject = (JsonClassInfo.ParameterizedConstructorDelegate <T, TArg0, TArg1, TArg2, TArg3>)
                               frame.JsonClassInfo.CreateObjectWithArgs !;
            var arguments = (Arguments <TArg0, TArg1, TArg2, TArg3>)frame.CtorArgumentState !.Arguments;

            return(createObject !(arguments.Arg0, arguments.Arg1, arguments.Arg2, arguments.Arg3));
        }
Пример #5
0
        protected override object CreateObject(ref ReadStackFrame frame)
        {
            var args = frame.PropertyValueCache;

            return(TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(
                       (DateTime)args[nameof(TimeZoneInfo.AdjustmentRule.DateStart)],
                       (DateTime)args[nameof(TimeZoneInfo.AdjustmentRule.DateEnd)],
                       (TimeSpan)args[nameof(TimeZoneInfo.AdjustmentRule.DaylightDelta)],
                       (TimeZoneInfo.TransitionTime)args[nameof(TimeZoneInfo.AdjustmentRule.DaylightTransitionStart)],
                       (TimeZoneInfo.TransitionTime)args[nameof(TimeZoneInfo.AdjustmentRule.DaylightTransitionEnd)]
                       ));
        }
Пример #6
0
        protected override object CreateObject(ref ReadStackFrame frame)
        {
            object[] arguments = (object[])frame.CtorArgumentState!.Arguments;

            var createObject = (JsonClassInfo.ParameterizedConstructorDelegate<T>?)frame.JsonClassInfo.CreateObjectWithArgs;

            if (createObject == null)
            {
                // This means this constructor has more than 64 parameters.
                ThrowHelper.ThrowNotSupportedException_ConstructorMaxOf64Parameters(ConstructorInfo!, TypeToConvert);
            }

            object obj = createObject(arguments);

            ArrayPool<object>.Shared.Return(arguments, clearArray: true);
            return obj;
        }
        protected override object CreateObject(ref ReadStackFrame frame)
        {
            var  args            = frame.PropertyValueCache;
            bool isFixedDateRule = (bool)args[nameof(TimeZoneInfo.TransitionTime.IsFixedDateRule)];

            if (isFixedDateRule)
            {
                return(TimeZoneInfo.TransitionTime.CreateFixedDateRule(
                           (DateTime)args[nameof(TimeZoneInfo.TransitionTime.TimeOfDay)],
                           (int)args[nameof(TimeZoneInfo.TransitionTime.Month)],
                           (int)args[nameof(TimeZoneInfo.TransitionTime.Day)]
                           ));
            }
            return(TimeZoneInfo.TransitionTime.CreateFloatingDateRule(
                       (DateTime)args[nameof(TimeZoneInfo.TransitionTime.TimeOfDay)],
                       (int)args[nameof(TimeZoneInfo.TransitionTime.Month)],
                       (int)args[nameof(TimeZoneInfo.TransitionTime.Day)],
                       (DayOfWeek)args[nameof(TimeZoneInfo.TransitionTime.DayOfWeek)]
                       ));
        }
        protected override object CreateObject(ref ReadStackFrame frame)
        {
            var arguments = (Arguments <TArg0, TArg1, TArg2, TArg3>)frame.CtorArgumentState !.Arguments !;

            return(_createObject !(arguments.Arg0, arguments.Arg1, arguments.Arg2, arguments.Arg3) !);
        }
Пример #9
0
        internal JsonPropertyInfo GetProperty(
            ReadOnlySpan <byte> propertyName,
            ref ReadStackFrame frame,
            out byte[] utf8PropertyName)
        {
            PropertyRef propertyRef;

            ValidateCanBeUsedForMetadataSerialization();
            ulong key = GetKey(propertyName);

            // Keep a local copy of the cache in case it changes by another thread.
            PropertyRef[]? localPropertyRefsSorted = _propertyRefsSorted;

            // If there is an existing cache, then use it.
            if (localPropertyRefsSorted != null)
            {
                // Start with the current property index, and then go forwards\backwards.
                int propertyIndex = frame.PropertyIndex;

                int count     = localPropertyRefsSorted.Length;
                int iForward  = Math.Min(propertyIndex, count);
                int iBackward = iForward - 1;

                while (true)
                {
                    if (iForward < count)
                    {
                        propertyRef = localPropertyRefsSorted[iForward];
                        if (IsPropertyRefEqual(propertyRef, propertyName, key))
                        {
                            utf8PropertyName = propertyRef.NameFromJson;
                            return(propertyRef.Info);
                        }

                        ++iForward;

                        if (iBackward >= 0)
                        {
                            propertyRef = localPropertyRefsSorted[iBackward];
                            if (IsPropertyRefEqual(propertyRef, propertyName, key))
                            {
                                utf8PropertyName = propertyRef.NameFromJson;
                                return(propertyRef.Info);
                            }

                            --iBackward;
                        }
                    }
                    else if (iBackward >= 0)
                    {
                        propertyRef = localPropertyRefsSorted[iBackward];
                        if (IsPropertyRefEqual(propertyRef, propertyName, key))
                        {
                            utf8PropertyName = propertyRef.NameFromJson;
                            return(propertyRef.Info);
                        }

                        --iBackward;
                    }
                    else
                    {
                        // Property was not found.
                        break;
                    }
                }
            }

            // No cached item was found. Try the main dictionary which has all of the properties.
#if DEBUG
            if (PropertyCache == null)
            {
                Debug.Fail($"Property cache is null. {GetPropertyDebugInfo(propertyName)}");
            }
#endif

            if (PropertyCache !.TryGetValue(JsonHelpers.Utf8GetString(propertyName), out JsonPropertyInfo? info))
            {
                Debug.Assert(info != null, "PropertyCache contains null JsonPropertyInfo");

                if (Options.PropertyNameCaseInsensitive)
                {
                    if (propertyName.SequenceEqual(info.NameAsUtf8Bytes))
                    {
#if DEBUG
                        ulong recomputedKey = GetKey(info.NameAsUtf8Bytes.AsSpan());
                        if (key != recomputedKey)
                        {
                            string propertyNameStr = JsonHelpers.Utf8GetString(propertyName);
                            Debug.Fail($"key {key} [propertyName={propertyNameStr}] does not match re-computed value {recomputedKey} for the same sequence (case-insensitive). {info.GetDebugInfo()}");
                        }
#endif

                        // Use the existing byte[] reference instead of creating another one.
                        utf8PropertyName = info.NameAsUtf8Bytes !;
                    }
                    else
                    {
                        // Make a copy of the original Span.
                        utf8PropertyName = propertyName.ToArray();
                    }
                }
                else
                {
#if DEBUG
                    ulong recomputedKey = GetKey(info.NameAsUtf8Bytes.AsSpan());
                    if (key != recomputedKey)
                    {
                        string propertyNameStr = JsonHelpers.Utf8GetString(propertyName);
                        Debug.Fail($"key {key} [propertyName={propertyNameStr}] does not match re-computed value {recomputedKey} for the same sequence (case-sensitive). {info.GetDebugInfo()}");
                    }
#endif
                    utf8PropertyName = info.NameAsUtf8Bytes;
                }
            }
Пример #10
0
        internal JsonParameterInfo?GetParameter(
            ReadOnlySpan <byte> propertyName,
            ref ReadStackFrame frame,
            out byte[] utf8PropertyName)
        {
            ParameterRef parameterRef;

            ulong key = GetKey(propertyName);

            // Keep a local copy of the cache in case it changes by another thread.
            ParameterRef[]? localParameterRefsSorted = _parameterRefsSorted;

            // If there is an existing cache, then use it.
            if (localParameterRefsSorted != null)
            {
                // Start with the current parameter index, and then go forwards\backwards.
                int parameterIndex = frame.CtorArgumentState !.ParameterIndex;

                int count     = localParameterRefsSorted.Length;
                int iForward  = Math.Min(parameterIndex, count);
                int iBackward = iForward - 1;

                while (true)
                {
                    if (iForward < count)
                    {
                        parameterRef = localParameterRefsSorted[iForward];
                        if (IsParameterRefEqual(parameterRef, propertyName, key))
                        {
                            utf8PropertyName = parameterRef.NameFromJson;
                            return(parameterRef.Info);
                        }

                        ++iForward;

                        if (iBackward >= 0)
                        {
                            parameterRef = localParameterRefsSorted[iBackward];
                            if (IsParameterRefEqual(parameterRef, propertyName, key))
                            {
                                utf8PropertyName = parameterRef.NameFromJson;
                                return(parameterRef.Info);
                            }

                            --iBackward;
                        }
                    }
                    else if (iBackward >= 0)
                    {
                        parameterRef = localParameterRefsSorted[iBackward];
                        if (IsParameterRefEqual(parameterRef, propertyName, key))
                        {
                            utf8PropertyName = parameterRef.NameFromJson;
                            return(parameterRef.Info);
                        }

                        --iBackward;
                    }
                    else
                    {
                        // Property was not found.
                        break;
                    }
                }
            }

            // No cached item was found. Try the main dictionary which has all of the parameters.
            Debug.Assert(ParameterCache != null);

            if (ParameterCache.TryGetValue(JsonHelpers.Utf8GetString(propertyName), out JsonParameterInfo? info))
            {
                Debug.Assert(info != null);

                if (Options.PropertyNameCaseInsensitive)
                {
                    if (propertyName.SequenceEqual(info.NameAsUtf8Bytes))
                    {
                        Debug.Assert(key == GetKey(info.NameAsUtf8Bytes.AsSpan()));

                        // Use the existing byte[] reference instead of creating another one.
                        utf8PropertyName = info.NameAsUtf8Bytes !;
                    }
                    else
                    {
                        // Make a copy of the original Span.
                        utf8PropertyName = propertyName.ToArray();
                    }
                }
                else
                {
                    Debug.Assert(key == GetKey(info.NameAsUtf8Bytes !.AsSpan()));
                    utf8PropertyName = info.NameAsUtf8Bytes !;
                }
            }
            else
            {
                Debug.Assert(info == null);

                // Make a copy of the original Span.
                utf8PropertyName = propertyName.ToArray();
            }

            // Check if we should add this to the cache.
            // Only cache up to a threshold length and then just use the dictionary when an item is not found in the cache.
            int cacheCount = 0;

            if (localParameterRefsSorted != null)
            {
                cacheCount = localParameterRefsSorted.Length;
            }

            // Do a quick check for the stable (after warm-up) case.
            if (cacheCount < ParameterNameCountCacheThreshold)
            {
                // Do a slower check for the warm-up case.
                if (frame.CtorArgumentState !.ParameterRefCache != null)
                {
                    cacheCount += frame.CtorArgumentState.ParameterRefCache.Count;
                }

                // Check again to append the cache up to the threshold.
                if (cacheCount < ParameterNameCountCacheThreshold)
                {
                    if (frame.CtorArgumentState.ParameterRefCache == null)
                    {
                        frame.CtorArgumentState.ParameterRefCache = new List <ParameterRef>();
                    }

                    parameterRef = new ParameterRef(key, info !, utf8PropertyName);
                    frame.CtorArgumentState.ParameterRefCache.Add(parameterRef);
                }
            }

            return(info);
        }
 protected abstract object CreateObject(ref ReadStackFrame frame);