File: System\ServiceModel\Channels\IntDecoder.cs
Web Access
Project: src\src\System.ServiceModel.Primitives\src\System.ServiceModel.Primitives.csproj (System.ServiceModel.Primitives)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.IO;
 
namespace System.ServiceModel.Channels
{
    internal struct IntDecoderHelper
    {
        private int _value;
        private short _index;
        private const int LastIndex = 4;
 
        public int Value
        {
            get
            {
                if (!IsValueDecoded)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRP.FramingValueNotAvailable));
                }
 
                return _value;
            }
        }
 
        public bool IsValueDecoded { get; private set; }
 
        public void Reset()
        {
            _index = 0;
            _value = 0;
            IsValueDecoded = false;
        }
 
        public int Decode(byte[] buffer, int offset, int size)
        {
            ValidateSize(size);
            if (IsValueDecoded)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRP.FramingValueNotAvailable));
            }
            int bytesConsumed = 0;
            while (bytesConsumed < size)
            {
                int next = buffer[offset];
                _value |= (next & 0x7F) << (_index * 7);
                bytesConsumed++;
                if (_index == LastIndex && (next & 0xF8) != 0)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataException(SRP.FramingSizeTooLarge));
                }
                _index++;
                if ((next & 0x80) == 0)
                {
                    IsValueDecoded = true;
                    break;
                }
                offset++;
            }
            return bytesConsumed;
        }
 
        public static void ValidateSize(int size)
        {
            if (size <= 0)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(size), size, SRP.ValueMustBePositive));
            }
        }
    }
}