예제 #1
0
        public void WriteField <TBufferWriter>(ref Writer <TBufferWriter> writer, uint fieldIdDelta, Type expectedType, object value) where TBufferWriter : IBufferWriter <byte>
        {
            if (ReferenceCodec.TryWriteReferenceField(ref writer, fieldIdDelta, expectedType, value))
            {
                return;
            }

            var type = value.GetType();

            writer.WriteFieldHeader(fieldIdDelta, expectedType, CodecType, WireType.TagDelimited);
            _typeCodec.WriteField(ref writer, 0, typeof(Type), type);

            if (type.IsValueType)
            {
                var serializer = _valueTypeSerializerFactory.GetSerializer(type);
                serializer.WriteValue(ref writer, value);
            }
            else
            {
                _objectSerializer.WriteValue(ref writer, value);
            }

            writer.WriteEndObject();
        }
예제 #2
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;
            }
        }
예제 #3
0
        public void DeserializeNew <TInput>(ref global::Hagar.Buffers.Reader <TInput> reader, global::Benchmarks.Models.IntClass instance)
        {
            int   id     = 0;
            Field header = default;

            while (true)
            {
                id = ReadHeader(ref reader, ref header, id);

                if (id == 0)
                {
                    ReferenceCodec.MarkValueField(reader.Session);
                    instance.MyProperty1 = reader.ReadInt32(header.WireType);
                    id = ReadHeader(ref reader, ref header, id);
                }

                if (id == 1)
                {
                    ReferenceCodec.MarkValueField(reader.Session);
                    instance.MyProperty2 = reader.ReadInt32(header.WireType);
                    id = ReadHeader(ref reader, ref header, id);
                }

                if (id == 2)
                {
                    ReferenceCodec.MarkValueField(reader.Session);
                    instance.MyProperty3 = reader.ReadInt32(header.WireType);
                    id = ReadHeader(ref reader, ref header, id);
                }

                if (id == 3)
                {
                    ReferenceCodec.MarkValueField(reader.Session);
                    instance.MyProperty4 = reader.ReadInt32(header.WireType);
                    id = ReadHeader(ref reader, ref header, id);
                }

                if (id == 4)
                {
                    ReferenceCodec.MarkValueField(reader.Session);
                    instance.MyProperty5 = reader.ReadInt32(header.WireType);
                    id = ReadHeader(ref reader, ref header, id);
                }

                if (id == 5)
                {
                    ReferenceCodec.MarkValueField(reader.Session);
                    instance.MyProperty6 = reader.ReadInt32(header.WireType);
                    id = ReadHeader(ref reader, ref header, id);
                }

                if (id == 6)
                {
                    ReferenceCodec.MarkValueField(reader.Session);
                    instance.MyProperty7 = reader.ReadInt32(header.WireType);
                    id = ReadHeader(ref reader, ref header, id);
                }

                if (id == 7)
                {
                    ReferenceCodec.MarkValueField(reader.Session);
                    instance.MyProperty8 = reader.ReadInt32(header.WireType);
                    id = ReadHeader(ref reader, ref header, id);
                }

                if (id == 8)
                {
                    ReferenceCodec.MarkValueField(reader.Session);
                    instance.MyProperty9 = reader.ReadInt32(header.WireType);
                    id = ReadHeaderExpectingEndBaseOrEndObject(ref reader, ref header, id);
                }

                if (id == -1)
                {
                    break;
                }

                reader.ConsumeUnknownField(header);
            }
        }
예제 #4
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);
    }