示例#1
0
        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);
        }
示例#2
0
        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();
        }
示例#3
0
        /// <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();
        }