Ejemplo n.º 1
0
        public override bool TryRead(ref ReadOnlySpan <byte> remaining, out T result, PropertyMap propMap = null)
        {
            result = default;

            switch (JsonReader.GetTokenType(ref remaining))
            {
            case JsonTokenType.StartObject:
                break;

            case JsonTokenType.Null:
                remaining = remaining.Slice(4);
                result    = null;
                return(true);

            default:
                return(false);
            }
            remaining = remaining.Slice(1);

            result = _map.CreateUninitialized();;
            if (JsonReader.GetTokenType(ref remaining) == JsonTokenType.EndObject)
            {
                remaining = remaining.Slice(1);
                return(true);
            }

            uint dependencies = 0;
            var  deferred     = new DeferredPropertyList <byte, byte>();

            bool isFirst    = true;
            bool incomplete = true;

            while (incomplete)
            {
                switch (JsonReader.GetTokenType(ref remaining))
                {
                case JsonTokenType.None:
                    return(false);

                case JsonTokenType.EndObject:
                    remaining  = remaining.Slice(1);
                    incomplete = false;
                    continue;

                case JsonTokenType.ListSeparator:
                    if (isFirst)
                    {
                        return(false);
                    }
                    remaining = remaining.Slice(1);
                    break;

                default:
                    if (!isFirst)
                    {
                        return(false);
                    }
                    isFirst = false;
                    break;
                }

                if (!JsonReader.TryReadUtf8String(ref remaining, out var key))
                {
                    return(false);
                }
                if (JsonReader.GetTokenType(ref remaining) != JsonTokenType.KeyValueSeparator)
                {
                    return(false);
                }
                remaining = remaining.Slice(1);

                // Unknown Property
                if (!_map.TryGetProperty(key, out var innerPropMap, out bool isIgnored))
                {
                    if (!isIgnored)
                    {
                        _serializer.RaiseUnknownProperty(_map, key);
                    }
                    if (!JsonReader.Skip(ref remaining, out _))
                    {
                        return(false);
                    }
                    continue;
                }

                if (!innerPropMap.CanRead)
                {
                    return(false);
                }

                // Property depends on another that hasn't been deserialized yet
                if (!innerPropMap.HasReadConverter(result, dependencies))
                {
                    if (!JsonReader.Skip(ref remaining, out var skipped))
                    {
                        return(false);
                    }
                    if (!deferred.Add(key, skipped))
                    {
                        return(false);
                    }
                    continue;
                }


                var restore = remaining;
                if (!innerPropMap.TryRead(result, ref remaining, dependencies))
                {
                    if (innerPropMap.IgnoreErrors)
                    {
                        remaining = restore;
                        if (!JsonReader.Skip(ref remaining, out var skipped))
                        {
                            return(false);
                        }
                        _serializer.RaiseFailedProperty(_map, innerPropMap);
                        continue;
                    }
                    else
                    {
                        return(false);
                    }
                }

                dependencies |= innerPropMap.IndexMask;
            }

            // Process all deferred properties
            for (int i = 0; i < deferred.Count; i++)
            {
                if (!_map.TryGetProperty(deferred.GetKey(i), out var innerPropMap, out bool isIgnored))
                {
                    return(false);
                }
                var value = deferred.GetValue(i);
                if (!innerPropMap.TryRead(result, ref value, dependencies))
                {
                    if (innerPropMap.IgnoreErrors)
                    {
                        _serializer.RaiseFailedProperty(_map, innerPropMap);
                    }
                    else
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
        public override bool TryRead(ref ReadOnlySpan <byte> remaining, out T result, PropertyMap propMap = null)
        {
            if (EtfReader.TryReadNullSafe(ref remaining))
            {
                result = null;
                return(true);
            }

            result = default;

            switch (EtfReader.GetTokenType(ref remaining))
            {
            case EtfTokenType.Map:
                if (remaining.Length < 5)
                {
                    return(false);
                }
                remaining = remaining.Slice(1);

                uint arity = BinaryPrimitives.ReadUInt32BigEndian(remaining);     // count
                remaining = remaining.Slice(4);

                result = _map.CreateUninitialized();
                if (arity == 0)
                {
                    return(true);
                }

                uint dependencies = 0;
                var  deferred     = new DeferredPropertyList <byte, byte>();

                for (int i = 0; i < arity; i++)
                {
                    if (!EtfReader.TryReadUtf8String(ref remaining, out var key))
                    {
                        return(false);
                    }

                    // Unknown Property
                    if (!_map.TryGetProperty(key, out var innerPropMap, out bool isIgnored))
                    {
                        if (!isIgnored)
                        {
                            _serializer.RaiseUnknownProperty(_map, key);
                        }
                        if (!EtfReader.Skip(ref remaining, out _))
                        {
                            return(false);
                        }
                        continue;
                    }

                    if (!innerPropMap.CanRead)
                    {
                        return(false);
                    }

                    // Property depends on another that hasn't been deserialized yet
                    if (!innerPropMap.HasReadConverter(result, dependencies))
                    {
                        if (!EtfReader.Skip(ref remaining, out var skipped))
                        {
                            return(false);
                        }
                        if (!deferred.Add(key, skipped))
                        {
                            return(false);
                        }
                        continue;
                    }

                    var restore = remaining;
                    if (!innerPropMap.TryRead(result, ref remaining, dependencies))
                    {
                        if (innerPropMap.IgnoreErrors)
                        {
                            remaining = restore;
                            if (!EtfReader.Skip(ref remaining, out var skipped))
                            {
                                return(false);
                            }
                            _serializer.RaiseFailedProperty(_map, innerPropMap);
                            continue;
                        }
                        else
                        {
                            return(false);
                        }
                    }

                    dependencies |= innerPropMap.IndexMask;
                }

                // Process all deferred properties
                for (int i = 0; i < deferred.Count; i++)
                {
                    if (!_map.TryGetProperty(deferred.GetKey(i), out var innerPropMap, out _))
                    {
                        return(false);
                    }
                    var value = deferred.GetValue(i);

                    if (!innerPropMap.TryRead(result, ref value, dependencies))
                    {
                        if (innerPropMap.IgnoreErrors)
                        {
                            _serializer.RaiseFailedProperty(_map, innerPropMap);
                        }
                        else
                        {
                            return(false);
                        }
                    }
                }
                return(true);

            default:
                return(false);
            }
        }