public HashSet <T> ReadValue <TInput>(ref Reader <TInput> reader, Field field) { if (field.WireType == WireType.Reference) { return(ReferenceCodec.ReadReference <HashSet <T>, TInput>(ref reader, field)); } if (field.WireType != WireType.TagDelimited) { ThrowUnsupportedWireTypeException(field); } var placeholderReferenceId = ReferenceCodec.CreateRecordPlaceholder(reader.Session); HashSet <T> result = null; IEqualityComparer <T> comparer = null; uint fieldId = 0; while (true) { var header = reader.ReadFieldHeader(); if (header.IsEndBaseOrEndObject) { break; } fieldId += header.FieldIdDelta; switch (fieldId) { case 0: comparer = _comparerCodec.ReadValue(ref reader, header); break; case 1: int length = Int32Codec.ReadValue(ref reader, header); if (length > 10240 && length > reader.Length) { ThrowInvalidSizeException(length); } break; case 2: result ??= CreateInstance(comparer, reader.Session, placeholderReferenceId); result.Add(_fieldCodec.ReadValue(ref reader, header)); break; default: reader.ConsumeUnknownField(header); break; } } result ??= CreateInstance(comparer, reader.Session, placeholderReferenceId); return(result); }
public void WriteField <TBufferWriter>(ref Writer <TBufferWriter> writer, uint fieldIdDelta, Type expectedType, List <T> value) where TBufferWriter : IBufferWriter <byte> { if (ReferenceCodec.TryWriteReferenceField(ref writer, fieldIdDelta, expectedType, value)) { return; } writer.WriteFieldHeader(fieldIdDelta, expectedType, value.GetType(), WireType.TagDelimited); Int32Codec.WriteField(ref writer, 0, Int32Codec.CodecFieldType, value.Count); uint innerFieldIdDelta = 1; foreach (var element in value) { _fieldCodec.WriteField(ref writer, innerFieldIdDelta, CodecElementType, element); innerFieldIdDelta = 0; } writer.WriteEndObject(); }
/// <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); }
/// <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(); }