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(); }
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; } }
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); } }
/// <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); }