public void WriteField <TBufferWriter>(ref Writer <TBufferWriter> writer, uint fieldIdDelta, Type expectedType, SerializationEntrySurrogate value) where TBufferWriter : IBufferWriter <byte> { ReferenceCodec.MarkValueField(writer.Session); writer.WriteFieldHeader(fieldIdDelta, expectedType, SerializationEntryType, WireType.TagDelimited); StringCodec.WriteField(ref writer, 0, typeof(string), value.Name); ObjectCodec.WriteField(ref writer, 1, typeof(object), value.Value); writer.WriteEndObject(); }
public unsafe IdSpan ReadValue <TInput>(ref Reader <TInput> reader, Field field) { ReferenceCodec.MarkValueField(reader.Session); var length = reader.ReadVarUInt32() - sizeof(int); var hashCode = reader.ReadInt32(); var payloadArray = reader.ReadBytes(length); var value = IdSpan.UnsafeCreate(payloadArray, hashCode); return(value); }
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); }
public void WriteField( Writer writer, SerializerSession session, uint fieldIdDelta, Type expectedType, SerializationEntrySurrogate value) { ReferenceCodec.MarkValueField(session); writer.WriteFieldHeader(session, fieldIdDelta, expectedType, SerializationEntryType, WireType.TagDelimited); this.stringCodec.WriteField(writer, session, 0, typeof(string), value.Name); this.objectCodec.WriteField(writer, session, 1, typeof(object), value.Value); writer.WriteEndObject(); }
void IFieldCodec <ValueTuple <T> > .WriteField <TBufferWriter>( ref Writer <TBufferWriter> writer, uint fieldIdDelta, Type expectedType, ValueTuple <T> value) { ReferenceCodec.MarkValueField(writer.Session); writer.WriteFieldHeader(fieldIdDelta, expectedType, value.GetType(), WireType.TagDelimited); _valueCodec.WriteField(ref writer, 1, typeof(T), value.Item1); writer.WriteEndObject(); }
public void WriteField <TBufferWriter>(ref Writer <TBufferWriter> writer, uint fieldIdDelta, Type expectedType, SiloAddress value) where TBufferWriter : IBufferWriter <byte> { if (value is null) { ReferenceCodec.WriteNullReference(ref writer, fieldIdDelta, expectedType); return; } ReferenceCodec.MarkValueField(writer.Session); writer.WriteStartObject(fieldIdDelta, expectedType, _codecFieldType); IPEndPointCodec.WriteField(ref writer, 0U, _iPEndPointType, value.Endpoint); Int32Codec.WriteField(ref writer, 1U, _int32Type, value.Generation); writer.WriteEndObject(); }
public unsafe IdSpan ReadValue <TInput>(ref Reader <TInput> reader, Field field) { ReferenceCodec.MarkValueField(reader.Session); byte[] payloadArray = default; var length = reader.ReadVarUInt32() - sizeof(int); var hashCode = reader.ReadInt32(); if (!reader.TryReadBytes((int)length, out var payloadSpan)) { payloadSpan = payloadArray = reader.ReadBytes(length); } // Search through var candidateHashCode = hashCode; while (_cache.TryGetValue(candidateHashCode, out var existing)) { if (existing.GetHashCode() != hashCode) { break; } var existingSpan = new ReadOnlySpan <byte>(IdSpan.UnsafeGetArray(existing)); if (existingSpan.SequenceEqual(payloadSpan)) { return(existing); } // Try the next slot. ++candidateHashCode; } if (payloadArray is null) { payloadArray = new byte[length]; payloadSpan.CopyTo(payloadArray); } var value = IdSpan.UnsafeCreate(payloadArray, hashCode); while (!_cache.TryAdd(candidateHashCode++, value)) { // Insert the value at the first available position. } return(value); }
public void WriteField <TBufferWriter>( ref Writer <TBufferWriter> writer, uint fieldIdDelta, Type expectedType, IdSpan value) where TBufferWriter : IBufferWriter <byte> { ReferenceCodec.MarkValueField(writer.Session); writer.WriteFieldHeaderExpected(fieldIdDelta, WireType.LengthPrefixed); var hashCode = value.GetHashCode(); var bytes = IdSpan.UnsafeGetArray(value); var bytesLength = value.IsDefault ? 0 : bytes.Length; writer.WriteVarUInt32((uint)(sizeof(int) + bytesLength)); writer.WriteInt32(hashCode); writer.Write(bytes); }
/// <inheritdoc/> void IFieldCodec <object> .WriteField <TBufferWriter>(ref Writer <TBufferWriter> writer, uint fieldIdDelta, Type expectedType, object value) { if (ReferenceCodec.TryWriteReferenceField(ref writer, fieldIdDelta, expectedType, value)) { return; } // The schema type when serializing the field is the type of the codec. // In practice it could be any unique type as long as this codec is registered as the handler. // By checking against the codec type in IsSupportedType, the codec could also just be registered as an IGenericCodec. // Note that the codec is responsible for serializing the type of the value itself. writer.WriteFieldHeader(fieldIdDelta, expectedType, SelfType, WireType.TagDelimited); var type = value.GetType(); // Write the type name ReferenceCodec.MarkValueField(writer.Session); writer.WriteFieldHeader(0, typeof(byte[]), typeof(byte[]), WireType.LengthPrefixed); writer.Session.TypeCodec.WriteLengthPrefixed(ref writer, type); // Write the serialized payload // Note that the Utf8JsonWriter and PooledArrayBufferWriter could be pooled as long as they're correctly // reset at the end of each use. var bufferWriter = new BufferWriterBox <PooledArrayBufferWriter>(new PooledArrayBufferWriter()); try { using var jsonWriter = new Utf8JsonWriter(bufferWriter); JsonSerializer.Serialize(jsonWriter, value, _options.SerializerOptions); jsonWriter.Flush(); ReferenceCodec.MarkValueField(writer.Session); writer.WriteFieldHeader(1, typeof(byte[]), typeof(byte[]), WireType.LengthPrefixed); writer.WriteVarUInt32((uint)bufferWriter.Value.Length); bufferWriter.Value.CopyTo(ref writer); } finally { bufferWriter.Value.Dispose(); } writer.WriteEndObject(); }
public SiloAddress ReadValue <TReaderInput>(ref Reader <TReaderInput> reader, Field field) { if (field.WireType == WireType.Reference) { return(ReferenceCodec.ReadReference <SiloAddress, TReaderInput>(ref reader, field)); } ReferenceCodec.MarkValueField(reader.Session); int id = 0; Field header = default; IPEndPoint endpoint = default; int generation = default; while (true) { id = OrleansGeneratedCodeHelper.ReadHeader(ref reader, ref header, id); if (id == 0) { endpoint = IPEndPointCodec.ReadValue(ref reader, header); id = OrleansGeneratedCodeHelper.ReadHeader(ref reader, ref header, id); } if (id == 1) { generation = Int32Codec.ReadValue(ref reader, header); id = OrleansGeneratedCodeHelper.ReadHeaderExpectingEndBaseOrEndObject(ref reader, ref header, id); } if (id == -1) { break; } reader.ConsumeUnknownField(header); } return(SiloAddress.New(endpoint, generation)); }
public SerializationEntrySurrogate ReadValue <TInput>(ref Reader <TInput> reader, Field field) { ReferenceCodec.MarkValueField(reader.Session); var result = new SerializationEntrySurrogate(); uint fieldId = 0; while (true) { var header = reader.ReadFieldHeader(); if (header.IsEndBaseOrEndObject) { break; } fieldId += header.FieldIdDelta; switch (fieldId) { case 0: result.Name = StringCodec.ReadValue(ref reader, header); break; case 1: result.Value = ObjectCodec.ReadValue(ref reader, header); break; case 2: result.ObjectType = TypeSerializerCodec.ReadValue(ref reader, header); break; default: reader.ConsumeUnknownField(header); break; } } return(result); }
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); }