ClientPipeline
Represents an extensible pipeline used by clients that call cloud services
            to send and receive HTTP request and responses. Creators of
             ClientPipeline can modify how it process a
             PipelineMessage by adding  PipelinePolicy
            instances at various points in the default pipeline.
            
                using System.ClientModel.Internal;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
namespace System.ClientModel.Primitives
{
    [System.Runtime.CompilerServices.NullableContext(1)]
    [System.Runtime.CompilerServices.Nullable(0)]
    public sealed class ClientPipeline
    {
        [System.Runtime.CompilerServices.Nullable(0)]
        private struct PipelineProcessor : IReadOnlyList<PipelinePolicy>, IEnumerable<PipelinePolicy>, IEnumerable, IReadOnlyCollection<PipelinePolicy>
        {
            [System.Runtime.CompilerServices.Nullable(new byte[] {
                0,
                1
            })]
            private readonly ReadOnlyMemory<PipelinePolicy> _policies;
            [System.Runtime.CompilerServices.Nullable(2)]
            private PolicyEnumerator _enumerator;
            public PipelinePolicy this[int index] {
                get {
                    return _policies.Span[index];
                }
            }
            public int Count => _policies.Length;
            public PipelineProcessor([System.Runtime.CompilerServices.Nullable(new byte[] {
                0,
                1
            })] ReadOnlyMemory<PipelinePolicy> policies)
            {
                _enumerator = null;
                _policies = policies;
            }
            public IEnumerator<PipelinePolicy> GetEnumerator()
            {
                return _enumerator ?? (_enumerator = new PolicyEnumerator(this));
            }
            IEnumerator IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }
        }
        [System.Runtime.CompilerServices.Nullable(0)]
        private class PolicyEnumerator : IEnumerator<PipelinePolicy>, IEnumerator, IDisposable
        {
            private readonly IReadOnlyList<PipelinePolicy> _policies;
            private int _current;
            public PipelinePolicy Current {
                get {
                    if (_current >= 0 && _current < _policies.Count)
                        return _policies[_current];
                    throw new InvalidOperationException("'Current' is outside the bounds of the policy collection.");
                }
            }
            object IEnumerator.Current {
                get {
                    return Current;
                }
            }
            public PolicyEnumerator(IReadOnlyList<PipelinePolicy> policies)
            {
                _policies = policies;
                _current = -1;
            }
            public bool MoveNext()
            {
                return ++_current < _policies.Count;
            }
            public void Reset()
            {
                _current = -1;
            }
            public void Dispose()
            {
            }
        }
        [System.Runtime.CompilerServices.Nullable(0)]
        internal class RequestOptionsProcessor : IReadOnlyList<PipelinePolicy>, IEnumerable<PipelinePolicy>, IEnumerable, IReadOnlyCollection<PipelinePolicy>
        {
            private readonly int _perCallIndex;
            private readonly int _perTryIndex;
            private readonly int _beforeTransportIndex;
            private readonly int _length;
            [System.Runtime.CompilerServices.Nullable(new byte[] {
                0,
                1
            })]
            private readonly ReadOnlyMemory<PipelinePolicy> _fixedPolicies;
            [System.Runtime.CompilerServices.Nullable(new byte[] {
                0,
                1
            })]
            private readonly ReadOnlyMemory<PipelinePolicy> _customPerCallPolicies;
            [System.Runtime.CompilerServices.Nullable(new byte[] {
                0,
                1
            })]
            private readonly ReadOnlyMemory<PipelinePolicy> _customPerTryPolicies;
            [System.Runtime.CompilerServices.Nullable(new byte[] {
                0,
                1
            })]
            private readonly ReadOnlyMemory<PipelinePolicy> _customBeforeTransportPolicies;
            [System.Runtime.CompilerServices.Nullable(2)]
            private PolicyEnumerator _enumerator;
            public PipelinePolicy this[int index] {
                get {
                    TryGetPolicy(index, out PipelinePolicy policy);
                    return policy;
                }
            }
            public int Count => _length;
            public RequestOptionsProcessor([System.Runtime.CompilerServices.Nullable(new byte[] {
                0,
                1
            })] ReadOnlyMemory<PipelinePolicy> fixedPolicies, [System.Runtime.CompilerServices.Nullable(new byte[] {
                0,
                1
            })] ReadOnlyMemory<PipelinePolicy> perCallPolicies, [System.Runtime.CompilerServices.Nullable(new byte[] {
                0,
                1
            })] ReadOnlyMemory<PipelinePolicy> perTryPolicies, [System.Runtime.CompilerServices.Nullable(new byte[] {
                0,
                1
            })] ReadOnlyMemory<PipelinePolicy> beforeTransportPolicies, int perCallIndex, int perTryIndex, int beforeTransportIndex)
            {
                _fixedPolicies = fixedPolicies;
                _customPerCallPolicies = perCallPolicies;
                _customPerTryPolicies = perTryPolicies;
                _customBeforeTransportPolicies = beforeTransportPolicies;
                _perCallIndex = perCallIndex;
                _perTryIndex = perTryIndex;
                _beforeTransportIndex = beforeTransportIndex;
                _length = _fixedPolicies.Length + _customPerCallPolicies.Length + _customPerTryPolicies.Length + _customBeforeTransportPolicies.Length;
            }
            public IEnumerator<PipelinePolicy> GetEnumerator()
            {
                return _enumerator ?? (_enumerator = new PolicyEnumerator(this));
            }
            IEnumerator IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }
            private bool TryGetPolicy(int index, out PipelinePolicy policy)
            {
                if (TryGetFixedPerCallPolicy(index, out policy))
                    return true;
                if (TryGetCustomPerCallPolicy(index, out policy))
                    return true;
                if (TryGetFixedPerTryPolicy(index, out policy))
                    return true;
                if (TryGetCustomPerTryPolicy(index, out policy))
                    return true;
                if (TryGetFixedPerTransportPolicy(index, out policy))
                    return true;
                if (TryGetCustomBeforeTransportPolicy(index, out policy))
                    return true;
                if (TryGetFixedTransportPolicy(index, out policy))
                    return true;
                policy = null;
                return false;
            }
            private bool TryGetFixedPerCallPolicy(int index, out PipelinePolicy policy)
            {
                if (index < _perCallIndex) {
                    policy = _fixedPolicies.Span[index];
                    return true;
                }
                policy = null;
                return false;
            }
            private bool TryGetCustomPerCallPolicy(int index, out PipelinePolicy policy)
            {
                if (index < _perCallIndex + _customPerCallPolicies.Length) {
                    policy = _customPerCallPolicies.Span[index - _perCallIndex];
                    return true;
                }
                policy = null;
                return false;
            }
            private bool TryGetFixedPerTryPolicy(int index, out PipelinePolicy policy)
            {
                if (index < _perTryIndex + _customPerCallPolicies.Length) {
                    policy = _fixedPolicies.Span[index - _customPerCallPolicies.Length];
                    return true;
                }
                policy = null;
                return false;
            }
            private bool TryGetCustomPerTryPolicy(int index, out PipelinePolicy policy)
            {
                if (index < _perTryIndex + _customPerCallPolicies.Length + _customPerTryPolicies.Length) {
                    policy = _customPerTryPolicies.Span[index - (_perTryIndex + _customPerCallPolicies.Length)];
                    return true;
                }
                policy = null;
                return false;
            }
            private bool TryGetFixedPerTransportPolicy(int index, out PipelinePolicy policy)
            {
                if (index < _perTryIndex + _customPerCallPolicies.Length + _customPerTryPolicies.Length) {
                    policy = _fixedPolicies.Span[index - (_customPerCallPolicies.Length + _customPerTryPolicies.Length)];
                    return true;
                }
                policy = null;
                return false;
            }
            private bool TryGetCustomBeforeTransportPolicy(int index, out PipelinePolicy policy)
            {
                if (index < _perTryIndex + _customPerCallPolicies.Length + _customPerTryPolicies.Length + _customBeforeTransportPolicies.Length) {
                    policy = _customBeforeTransportPolicies.Span[index - (_beforeTransportIndex + _customPerCallPolicies.Length + _customPerTryPolicies.Length)];
                    return true;
                }
                policy = null;
                return false;
            }
            private bool TryGetFixedTransportPolicy(int index, out PipelinePolicy policy)
            {
                if (index < _length) {
                    policy = _fixedPolicies.Span[index - (_customPerCallPolicies.Length + _customPerTryPolicies.Length + _customBeforeTransportPolicies.Length)];
                    return true;
                }
                policy = null;
                return false;
            }
        }
        private readonly int _perCallIndex;
        private readonly int _perTryIndex;
        private readonly int _beforeTransportIndex;
        [System.Runtime.CompilerServices.Nullable(new byte[] {
            0,
            1
        })]
        private readonly ReadOnlyMemory<PipelinePolicy> _policies;
        private readonly PipelineTransport _transport;
        private readonly TimeSpan _networkTimeout;
        internal static TimeSpan DefaultNetworkTimeout { get; } = TimeSpan.FromSeconds(100);
        private ClientPipeline([System.Runtime.CompilerServices.Nullable(new byte[] {
            0,
            1
        })] ReadOnlyMemory<PipelinePolicy> policies, TimeSpan networkTimeout, int perCallIndex, int perTryIndex, int beforeTransportIndex)
        {
            ReadOnlySpan<PipelinePolicy> span = policies.Span;
            if (!(span[policies.Length - 1] is PipelineTransport))
                throw new ArgumentException("The last policy must be of type 'PipelineTransport'.", "policies");
            span = policies.Span;
            _transport = (PipelineTransport)span[policies.Length - 1];
            _policies = policies;
            _perCallIndex = perCallIndex;
            _perTryIndex = perTryIndex;
            _beforeTransportIndex = beforeTransportIndex;
            _networkTimeout = networkTimeout;
        }
        public static ClientPipeline Create([System.Runtime.CompilerServices.Nullable(2)] ClientPipelineOptions options = null)
        {
            return Create(options ?? ClientPipelineOptions.Default, ReadOnlySpan<PipelinePolicy>.Empty, ReadOnlySpan<PipelinePolicy>.Empty, ReadOnlySpan<PipelinePolicy>.Empty);
        }
        public static ClientPipeline Create(ClientPipelineOptions options, [System.Runtime.CompilerServices.Nullable(new byte[] {
            0,
            1
        })] ReadOnlySpan<PipelinePolicy> perCallPolicies, [System.Runtime.CompilerServices.Nullable(new byte[] {
            0,
            1
        })] ReadOnlySpan<PipelinePolicy> perTryPolicies, [System.Runtime.CompilerServices.Nullable(new byte[] {
            0,
            1
        })] ReadOnlySpan<PipelinePolicy> beforeTransportPolicies)
        {
            Argument.AssertNotNull(options, "options");
            options.Freeze();
            int num = perCallPolicies.Length + perTryPolicies.Length + beforeTransportPolicies.Length;
            PipelinePolicy[] perTryPolicies2 = options.PerTryPolicies;
            int num2 = num + ((perTryPolicies2 != null) ? perTryPolicies2.Length : 0);
            PipelinePolicy[] perCallPolicies2 = options.PerCallPolicies;
            int num3 = num2 + ((perCallPolicies2 != null) ? perCallPolicies2.Length : 0);
            PipelinePolicy[] beforeTransportPolicies2 = options.BeforeTransportPolicies;
            PipelinePolicy[] array = new PipelinePolicy[num3 + ((beforeTransportPolicies2 != null) ? beforeTransportPolicies2.Length : 0) + 1 + 1];
            int num4 = 0;
            perCallPolicies.CopyTo(array.AsSpan(num4));
            num4 += perCallPolicies.Length;
            if (options.PerCallPolicies != null) {
                options.PerCallPolicies.CopyTo(array.AsSpan(num4));
                num4 += options.PerCallPolicies.Length;
            }
            int perCallIndex = num4;
            array[num4++] = (options.RetryPolicy ?? ClientRetryPolicy.Default);
            perTryPolicies.CopyTo(array.AsSpan(num4));
            num4 += perTryPolicies.Length;
            if (options.PerTryPolicies != null) {
                options.PerTryPolicies.CopyTo(array.AsSpan(num4));
                num4 += options.PerTryPolicies.Length;
            }
            int perTryIndex = num4;
            beforeTransportPolicies.CopyTo(array.AsSpan(num4));
            num4 += beforeTransportPolicies.Length;
            if (options.BeforeTransportPolicies != null) {
                options.BeforeTransportPolicies.CopyTo(array.AsSpan(num4));
                num4 += options.BeforeTransportPolicies.Length;
            }
            int beforeTransportIndex = num4;
            array[num4++] = (options.Transport ?? HttpClientPipelineTransport.Shared);
            return new ClientPipeline(array, options.NetworkTimeout ?? DefaultNetworkTimeout, perCallIndex, perTryIndex, beforeTransportIndex);
        }
        public PipelineMessage CreateMessage()
        {
            PipelineMessage pipelineMessage = _transport.CreateMessage();
            pipelineMessage.NetworkTimeout = _networkTimeout;
            return pipelineMessage;
        }
        public void Send(PipelineMessage message)
        {
            Argument.AssertNotNull(message, "message");
            IReadOnlyList<PipelinePolicy> processor = GetProcessor(message);
            processor[0].Process(message, processor, 0);
        }
        [AsyncStateMachine(typeof(<SendAsync>d__14))]
        public ValueTask SendAsync(PipelineMessage message)
        {
            <SendAsync>d__14 stateMachine = default(<SendAsync>d__14);
            stateMachine.<>t__builder = AsyncValueTaskMethodBuilder.Create();
            stateMachine.<>4__this = this;
            stateMachine.message = message;
            stateMachine.<>1__state = -1;
            stateMachine.<>t__builder.Start(ref stateMachine);
            return stateMachine.<>t__builder.Task;
        }
        private IReadOnlyList<PipelinePolicy> GetProcessor(PipelineMessage message)
        {
            if (message.UseCustomRequestPipeline)
                return new RequestOptionsProcessor(_policies, message.PerCallPolicies, message.PerTryPolicies, message.BeforeTransportPolicies, _perCallIndex, _perTryIndex, _beforeTransportIndex);
            return new PipelineProcessor(_policies);
        }
    }
}