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