TField IFieldCodec <TField> .ReadValue(ref Reader reader, Field field)
        {
            if (field.WireType == WireType.Reference)
            {
                return(ReferenceCodec.ReadReference <TField>(ref reader, field));
            }
            var fieldType = field.FieldType;

            if (fieldType == null || fieldType == CodecFieldType)
            {
                var result = this.activator.Create();
                ReferenceCodec.RecordObject(reader.Session, result);
                this.serializer.Deserialize(ref reader, result);
                return(result);
            }

            // The type is a descendant, not an exact match, so get the specific serializer for it.
            var specificSerializer = reader.Session.CodecProvider.GetCodec(fieldType);

            if (specificSerializer != null)
            {
                return((TField)specificSerializer.ReadValue(ref reader, field));
            }

            ThrowSerializerNotFoundException(fieldType);
            return(null);
        }
    /// <inheritdoc/>
    public TField ReadValue <TInput>(ref Reader <TInput> reader, Field field)
    {
        if (field.WireType == WireType.Reference)
        {
            return(ReferenceCodec.ReadReference <TField, TInput>(ref reader, field));
        }

        var placeholderReferenceId = ReferenceCodec.CreateRecordPlaceholder(reader.Session);
        var fieldType = field.FieldType;

        if (fieldType is null || fieldType == _fieldType)
        {
            TSurrogate surrogate = default;
            _surrogateSerializer.Deserialize(ref reader, ref surrogate);
            var result = _converter.ConvertFromSurrogate(in surrogate);
            ReferenceCodec.RecordObject(reader.Session, result, placeholderReferenceId);
            return(result);
        }

        // The type is a descendant, not an exact match, so get the specific serializer for it.
        var specificSerializer = reader.Session.CodecProvider.GetCodec(fieldType);

        if (specificSerializer != null)
        {
            return((TField)specificSerializer.ReadValue(ref reader, field));
        }

        ThrowSerializerNotFoundException(fieldType);
        return(default);
Example #3
0
    object IFieldCodec <object> .ReadValue <TInput>(ref Reader <TInput> reader, Field field)
    {
        if (field.WireType == WireType.Reference)
        {
            return(ReferenceCodec.ReadReference <object, TInput>(ref reader, field));
        }

        if (field.WireType != WireType.TagDelimited)
        {
            ThrowUnsupportedWireTypeException(field);
        }

        var    placeholderReferenceId = ReferenceCodec.CreateRecordPlaceholder(reader.Session);
        object result  = null;
        Type   type    = null;
        uint   fieldId = 0;

        while (true)
        {
            var header = reader.ReadFieldHeader();
            if (header.IsEndBaseOrEndObject)
            {
                break;
            }

            fieldId += header.FieldIdDelta;
            switch (fieldId)
            {
            case 0:
                ReferenceCodec.MarkValueField(reader.Session);
                type = reader.Session.TypeCodec.ReadLengthPrefixed(ref reader);
                break;

            case 1:
                if (type is null)
                {
                    ThrowTypeFieldMissing();
                }

                // To possibly improve efficiency, this could be converted to read a ReadOnlySequence<byte> instead of a byte array.
                var serializedValue = StringCodec.ReadValue(ref reader, header);
                result = JsonConvert.DeserializeObject(serializedValue, type, _options.SerializerSettings);
                ReferenceCodec.RecordObject(reader.Session, result, placeholderReferenceId);
                break;

            default:
                reader.ConsumeUnknownField(header);
                break;
            }
        }

        return(result);
    }
Example #4
0
        public object ReadValue(Reader reader, SerializerSession session, Field field)
        {
            if (field.WireType == WireType.Reference)
            {
                return(ReferenceCodec.ReadReference <object>(reader, session, field, this.codecProvider));
            }

            if (field.WireType != WireType.LengthPrefixed)
            {
                ThrowUnsupportedWireTypeException(field);
            }
            var length = reader.ReadVarUInt32();
            var bytes  = reader.ReadBytes((int)length);

            // TODO: NoAlloc
            var resultString = Encoding.UTF8.GetString(bytes);
            var result       = JsonConvert.DeserializeObject(resultString, this.settings);

            ReferenceCodec.RecordObject(session, result);
            return(result);
        }
        object IFieldCodec <object> .ReadValue <TInput>(ref Reader <TInput> reader, Field field)
        {
            if (field.WireType == WireType.Reference)
            {
                return(ReferenceCodec.ReadReference <object, TInput>(ref reader, field));
            }

            if (field.WireType != WireType.LengthPrefixed)
            {
                ThrowUnsupportedWireTypeException(field);
            }

            var length = reader.ReadVarUInt32();
            var bytes  = reader.ReadBytes(length);

            // TODO: NoAlloc
            var resultString = Encoding.UTF8.GetString(bytes);
            var result       = JsonConvert.DeserializeObject(resultString, _settings);

            ReferenceCodec.RecordObject(reader.Session, result);
            return(result);
        }
Example #6
0
        public object ReadValue <TInput>(ref Reader <TInput> reader, Type type, uint placeholderReferenceId)
        {
            var callbacks = _serializationCallbacks.GetReferenceTypeCallbacks(type);

            var info   = new SerializationInfo(type, _formatterConverter);
            var result = FormatterServices.GetUninitializedObject(type);

            ReferenceCodec.RecordObject(reader.Session, result, placeholderReferenceId);
            callbacks.OnDeserializing?.Invoke(result, _streamingContext);

            uint fieldId = 0;

            while (true)
            {
                var header = reader.ReadFieldHeader();
                if (header.IsEndBaseOrEndObject)
                {
                    break;
                }

                fieldId += header.FieldIdDelta;
                if (fieldId == 1)
                {
                    var entry = _entrySerializer.ReadValue(ref reader, header);
                    info.AddValue(entry.Name, entry.Value);
                }
            }

            var constructor = _constructors.GetOrAdd(info.ObjectType, _createConstructorDelegate);

            constructor(result, info, _streamingContext);
            callbacks.OnDeserialized?.Invoke(result, _streamingContext);
            if (result is IDeserializationCallback callback)
            {
                callback.OnDeserialization(_streamingContext.Context);
            }

            return(result);
        }
Example #7
0
        private static void FormatField <TInput>(ref Reader <TInput> reader, Field field, string typeName, uint id, StringBuilder res, int indentation)
        {
            var indentString = new string(' ', indentation);

            AppendAddress(ref reader, res);
            res.Append(indentString);

            // References cannot themselves be referenced.
            if (field.WireType == WireType.Reference)
            {
                ReferenceCodec.MarkValueField(reader.Session);
                var refId  = reader.ReadVarUInt32();
                var exists = reader.Session.ReferencedObjects.TryGetReferencedObject(refId, out var refd);
                res.Append('[');
                FormatFieldHeader(res, reader.Session, field, id, typeName);
                res.Append($" Reference: {refId} ({(exists ? $"{refd}" : "unknown")})");
                res.Append(']');
                return;
            }

            // Record a placeholder so that this field can later be correctly deserialized if it is referenced.
            ReferenceCodec.RecordObject(reader.Session, new UnknownFieldMarker(field, reader.Position));
            res.Append('[');
            FormatFieldHeader(res, reader.Session, field, id, typeName);
            res.Append(']');
            res.Append(" Value: ");

            switch (field.WireType)
            {
            case WireType.VarInt:
            {
                var a = reader.ReadVarUInt64();
                if (a < 10240)
                {
                    res.Append($"{a} (0x{a:X})");
                }
                else
                {
                    res.Append($"0x{a:X}");
                }
            }
            break;

            case WireType.TagDelimited:
                // Since tag delimited fields can be comprised of other fields, recursively consume those, too.

                res.Append($"{{\n");
                reader.FormatTagDelimitedField(res, indentation + 1);
                res.AppendLine();
                AppendAddress(ref reader, res);
                res.Append($"{indentString}}}");
                break;

            case WireType.LengthPrefixed:
            {
                var length = reader.ReadVarUInt32();
                res.Append($"(length: {length}b) [");
                var a = reader.ReadBytes(length);
                FormatByteArray(res, a);
                res.Append(']');
            }
            break;

            case WireType.Fixed32:
            {
                var a = reader.ReadUInt32();
                if (a < 10240)
                {
                    res.Append($"{a} (0x{a:X})");
                }
                else
                {
                    res.Append($"0x{a:X}");
                }
            }
            break;

            case WireType.Fixed64:
            {
                var a = reader.ReadUInt64();
                if (a < 10240)
                {
                    res.Append($"{a} (0x{a:X})");
                }
                else
                {
                    res.Append($"0x{a:X}");
                }
            }
            break;

            case WireType.Extended:
                SkipFieldExtension.ThrowUnexpectedExtendedWireType(field);
                break;

            default:
                SkipFieldExtension.ThrowUnexpectedWireType(field);
                break;
            }
        }
Example #8
0
    /// <inheritdoc/>
    object IFieldCodec <object> .ReadValue <TInput>(ref Reader <TInput> reader, Field field)
    {
        if (field.WireType == WireType.Reference)
        {
            return(ReferenceCodec.ReadReference <object, TInput>(ref reader, field));
        }

        if (field.WireType != WireType.TagDelimited)
        {
            ThrowUnsupportedWireTypeException(field);
        }

        var    placeholderReferenceId = ReferenceCodec.CreateRecordPlaceholder(reader.Session);
        object result  = null;
        Type   type    = null;
        uint   fieldId = 0;

        while (true)
        {
            var header = reader.ReadFieldHeader();
            if (header.IsEndBaseOrEndObject)
            {
                break;
            }

            fieldId += header.FieldIdDelta;
            switch (fieldId)
            {
            case 0:
                ReferenceCodec.MarkValueField(reader.Session);
                type = reader.Session.TypeCodec.ReadLengthPrefixed(ref reader);
                break;

            case 1:
                if (type is null)
                {
                    ThrowTypeFieldMissing();
                }

                ReferenceCodec.MarkValueField(reader.Session);
                var length = reader.ReadVarUInt32();

                // To possibly improve efficiency, this could be converted to read a ReadOnlySequence<byte> instead of a byte array.
                ReadOnlySequence <byte> sequence = default;
                var tempBuffer = new PooledArrayBufferWriter();
                try
                {
                    reader.ReadBytes(ref tempBuffer, (int)length);
                    sequence = tempBuffer.RentReadOnlySequence();
                    var jsonReader = new Utf8JsonReader(sequence, _options.ReaderOptions);
                    result = JsonSerializer.Deserialize(ref jsonReader, type, _options.SerializerOptions);
                }
                finally
                {
                    tempBuffer.ReturnReadOnlySequence(sequence);
                    tempBuffer.Reset();
                }

                break;

            default:
                reader.ConsumeUnknownField(header);
                break;
            }
        }

        ReferenceCodec.RecordObject(reader.Session, result, placeholderReferenceId);
        return(result);
    }