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