/// <inheritdoc/> object IFieldCodec <object> .ReadValue <TInput>(ref Reader <TInput> reader, Field field) { if (field.WireType == WireType.Reference) { return(ReferenceCodec.ReadReference <T[], TInput>(ref reader, field)); } if (field.WireType != WireType.TagDelimited) { ThrowUnsupportedWireTypeException(field); } var placeholderReferenceId = ReferenceCodec.CreateRecordPlaceholder(reader.Session); Array result = null; uint fieldId = 0; int[] lengths = null; int[] indices = null; var rank = 0; while (true) { var header = reader.ReadFieldHeader(); if (header.IsEndBaseOrEndObject) { break; } fieldId += header.FieldIdDelta; switch (fieldId) { case 0: { lengths = _intArrayCodec.ReadValue(ref reader, header); rank = lengths.Length; // Multi-dimensional arrays must be indexed using indexing arrays, so create one now. indices = new int[rank]; result = Array.CreateInstance(CodecElementType, lengths); ReferenceCodec.RecordObject(reader.Session, result, placeholderReferenceId); break; } case 1: { if (result is null) { return(ThrowLengthsFieldMissing()); } var element = _elementCodec.ReadValue(ref reader, header); result.SetValue(element, indices); // Increment the indices array by 1. var idx = rank - 1; while (idx >= 0 && ++indices[idx] >= lengths[idx]) { indices[idx] = 0; --idx; } break; } default: reader.ConsumeUnknownField(header); break; } } return(result); }
/// <summary> /// Writes a field. /// </summary> /// <typeparam name="TBufferWriter">The buffer writer type.</typeparam> /// <param name="writer">The writer.</param> /// <param name="fieldIdDelta">The field identifier delta.</param> /// <param name="expectedType">The expected type.</param> /// <param name="value">The value.</param> public static void WriteField <TBufferWriter>(ref Writer <TBufferWriter> writer, uint fieldIdDelta, Type expectedType, TimeSpan value) where TBufferWriter : IBufferWriter <byte> { ReferenceCodec.MarkValueField(writer.Session); writer.WriteFieldHeader(fieldIdDelta, expectedType, CodecFieldType, WireType.Fixed64); writer.WriteInt64(value.Ticks); }
/// <inheritdoc/> public List <T> ReadValue <TInput>(ref Reader <TInput> reader, Field field) { if (field.WireType == WireType.Reference) { return(ReferenceCodec.ReadReference <List <T>, TInput>(ref reader, field)); } if (field.WireType != WireType.TagDelimited) { ThrowUnsupportedWireTypeException(field); } var placeholderReferenceId = ReferenceCodec.CreateRecordPlaceholder(reader.Session); List <T> result = null; uint fieldId = 0; var length = 0; var index = 0; while (true) { var header = reader.ReadFieldHeader(); if (header.IsEndBaseOrEndObject) { break; } fieldId += header.FieldIdDelta; switch (fieldId) { case 0: length = Int32Codec.ReadValue(ref reader, header); if (length > 10240 && length > reader.Length) { ThrowInvalidSizeException(length); } result = _activator.Create(length); result.Capacity = length; ReferenceCodec.RecordObject(reader.Session, result, placeholderReferenceId); break; case 1: if (result is null) { ThrowLengthFieldMissing(); } if (index >= length) { ThrowIndexOutOfRangeException(length); } result.Add(_fieldCodec.ReadValue(ref reader, header)); ++index; break; default: reader.ConsumeUnknownField(header); break; } } return(result); }
/// <summary> /// Writes a field. /// </summary> /// <typeparam name="TBufferWriter">The buffer writer type.</typeparam> /// <param name="writer">The writer.</param> /// <param name="fieldIdDelta">The field identifier delta.</param> /// <param name="expectedType">The expected type.</param> /// <param name="value">The value.</param> public static void WriteField <TBufferWriter>(ref Writer <TBufferWriter> writer, uint fieldIdDelta, Type expectedType, char value) where TBufferWriter : IBufferWriter <byte> { ReferenceCodec.MarkValueField(writer.Session); writer.WriteFieldHeader(fieldIdDelta, expectedType, CodecFieldType, WireType.VarInt); writer.WriteVarUInt32(value); }
/// <summary> /// Reads a value. /// </summary> /// <typeparam name="TInput">The reader input type.</typeparam> /// <param name="reader">The reader.</param> /// <param name="field">The field.</param> /// <returns>The value.</returns> public static Type ReadValue <TInput>(ref Reader <TInput> reader, Field field) { if (field.WireType == WireType.Reference) { return(ReferenceCodec.ReadReference <Type, TInput>(ref reader, field)); } var placeholderReferenceId = ReferenceCodec.CreateRecordPlaceholder(reader.Session); uint fieldId = 0; var schemaType = default(SchemaType); uint id = 0; Type result = null; while (true) { var header = reader.ReadFieldHeader(); if (header.IsEndBaseOrEndObject) { break; } ReferenceCodec.MarkValueField(reader.Session); fieldId += header.FieldIdDelta; switch (fieldId) { case 0: schemaType = (SchemaType)reader.ReadVarUInt32(); break; case 1: result = reader.Session.TypeCodec.ReadLengthPrefixed(ref reader); break; case 2: id = reader.ReadVarUInt32(); break; default: reader.ConsumeUnknownField(header); break; } } switch (schemaType) { case SchemaType.Referenced: if (reader.Session.ReferencedTypes.TryGetReferencedType(id, out result)) { break; } return(ThrowUnknownReferencedType(id)); case SchemaType.WellKnown: if (reader.Session.WellKnownTypes.TryGetWellKnownType(id, out result)) { break; } return(ThrowUnknownWellKnownType(id)); case SchemaType.Encoded: if (result is not null) { break; } return(ThrowMissingType()); default: return(ThrowInvalidSchemaType(schemaType)); } ReferenceCodec.RecordObject(reader.Session, result, placeholderReferenceId); return(result); }
/// <summary> /// Writes a field. /// </summary> /// <typeparam name="TBufferWriter">The buffer writer type.</typeparam> /// <param name="writer">The writer.</param> /// <param name="fieldIdDelta">The field identifier delta.</param> /// <param name="expectedType">The expected type.</param> /// <param name="value">The value.</param> /// <param name="actualType">The actual type.</param> public static void WriteField <TBufferWriter>(ref Writer <TBufferWriter> writer, uint fieldIdDelta, Type expectedType, short value, Type actualType) where TBufferWriter : IBufferWriter <byte> { ReferenceCodec.MarkValueField(writer.Session); writer.WriteFieldHeader(fieldIdDelta, expectedType, actualType, WireType.VarInt); writer.WriteVarInt16(value); }
public static ulong ReadValue <TInput>(ref Reader <TInput> reader, Field field) { ReferenceCodec.MarkValueField(reader.Session); return(reader.ReadUInt64(field.WireType)); }
public static char ReadValue <TInput>(ref Reader <TInput> reader, Field field) { ReferenceCodec.MarkValueField(reader.Session); return((char)reader.ReadUInt16(field.WireType)); }
/// <inheritdoc /> public object ReadValue <TInput>(ref Reader <TInput> reader, Field field) { ReferenceCodec.MarkValueField(reader.Session); uint type = default; CompareOptions options = default; int lcid = default; uint fieldId = 0; while (true) { var header = reader.ReadFieldHeader(); if (header.IsEndBaseOrEndObject) { break; } fieldId += header.FieldIdDelta; switch (fieldId) { case 0: type = UInt32Codec.ReadValue(ref reader, header); break; case 1: options = (CompareOptions)UInt64Codec.ReadValue(ref reader, header); break; case 2: lcid = Int32Codec.ReadValue(ref reader, header); break; default: reader.ConsumeUnknownField(header); break; } } if (type == 0) { return(null); } else if (type == 1) { if (options.HasFlag(CompareOptions.IgnoreCase)) { return(StringComparer.OrdinalIgnoreCase); } else { return(StringComparer.Ordinal); } } else if (type == 2) { if (lcid == CultureInfo.InvariantCulture.LCID) { if (options == CompareOptions.None) { return(StringComparer.InvariantCulture); } else if (options == CompareOptions.IgnoreCase) { return(StringComparer.InvariantCultureIgnoreCase); } // Otherwise, perhaps some other options were specified, in which case we fall-through to create a new comparer. } var cultureInfo = CultureInfo.GetCultureInfo(lcid); var result = StringComparer.Create(cultureInfo, options); return(result); } ThrowNotSupported(field, type); return(null); }
/// <inheritdoc /> public void WriteField <TBufferWriter>(ref Writer <TBufferWriter> writer, uint fieldIdDelta, Type expectedType, object value) where TBufferWriter : IBufferWriter <byte> { uint type; CompareOptions compareOptions = default; CompareInfo compareInfo = default; if (value is null) { type = 0; } else { #if NET6_0_OR_GREATER var comparer = (IEqualityComparer <string>)value; if (StringComparer.IsWellKnownOrdinalComparer(comparer, out var ignoreCase)) { // Ordinal. This also handles EqualityComparer<string>.Default. type = 1; if (ignoreCase) { compareOptions = CompareOptions.IgnoreCase; } } else if (StringComparer.IsWellKnownCultureAwareComparer(comparer, out compareInfo, out compareOptions)) { type = 2; } else { ThrowNotSupported(value.GetType()); return; } #else var isOrdinal = _ordinalComparer.Equals(value) || _defaultEqualityComparer.Equals(value); var isOrdinalIgnoreCase = _ordinalIgnoreCaseComparer.Equals(value); if (isOrdinal) { type = 1; } else if (isOrdinalIgnoreCase) { type = 1; compareOptions = CompareOptions.IgnoreCase; } else if (TryGetWellKnownCultureAwareComparerInfo(value, out compareInfo, out compareOptions, out var ignoreCase)) { type = 2; if (ignoreCase) { compareOptions |= CompareOptions.IgnoreCase; } } else { ThrowNotSupported(value.GetType()); return; } #endif } ReferenceCodec.MarkValueField(writer.Session); writer.WriteFieldHeader(fieldIdDelta, expectedType, typeof(WellKnownStringComparerCodec), WireType.TagDelimited); UInt32Codec.WriteField(ref writer, 0, typeof(int), type); UInt64Codec.WriteField(ref writer, 1, typeof(ulong), (ulong)compareOptions); if (compareInfo is not null) { Int32Codec.WriteField(ref writer, 1, typeof(int), compareInfo.LCID); } writer.WriteEndObject(); }
public static void WriteField <TBufferWriter>(ref Writer <TBufferWriter> writer, uint fieldIdDelta, Type expectedType, BitVector32 value) where TBufferWriter : IBufferWriter <byte> { ReferenceCodec.MarkValueField(writer.Session); writer.WriteFieldHeader(fieldIdDelta, expectedType, typeof(BitVector32), WireType.Fixed32); writer.WriteInt32(value.Data); // BitVector32.Data gets the value of the BitVector32 as an Int32 }
void IFieldCodec <ValueTuple> .WriteField <TBufferWriter>(ref Writer <TBufferWriter> writer, uint fieldIdDelta, Type expectedType, ValueTuple value) { ReferenceCodec.MarkValueField(writer.Session); writer.WriteFieldHeader(fieldIdDelta, expectedType, value.GetType(), WireType.VarInt); writer.WriteVarUInt32(0); }