using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;

namespace System.Threading.Channels
{
	[Nullable(0)]
	[NullableContext(1)]
	public abstract class ChannelReader<[Nullable(2)] T>
	{
		public virtual Task Completion
		{
			get
			{
				return ChannelUtilities.s_neverCompletingTask;
			}
		}

		public virtual bool CanCount
		{
			get
			{
				return false;
			}
		}

		public virtual bool CanPeek
		{
			get
			{
				return false;
			}
		}

		public virtual int Count
		{
			get
			{
				throw new NotSupportedException();
			}
		}

		public abstract bool TryRead([MaybeNullWhen(false)] out T item);

		public virtual bool TryPeek([MaybeNullWhen(false)] out T item)
		{
			item = default(T);
			return false;
		}

		[NullableContext(0)]
		public abstract ValueTask<bool> WaitToReadAsync(CancellationToken cancellationToken = default(CancellationToken));

		[return: Nullable(new byte[] { 0, 1 })]
		public virtual ValueTask<T> ReadAsync(CancellationToken cancellationToken = default(CancellationToken))
		{
			if (cancellationToken.IsCancellationRequested)
			{
				return new ValueTask<T>(Task.FromCanceled<T>(cancellationToken));
			}
			try
			{
				T t;
				if (this.TryRead(out t))
				{
					return new ValueTask<T>(t);
				}
			}
			catch (Exception ex) when (!(ex is ChannelClosedException) && !(ex is OperationCanceledException))
			{
				return new ValueTask<T>(Task.FromException<T>(ex));
			}
			return this.method_0(cancellationToken);
		}

		[CompilerGenerated]
		private async ValueTask<T> method_0(CancellationToken ct)
		{
			T t;
			do
			{
				ConfiguredValueTaskAwaitable<bool>.ConfiguredValueTaskAwaiter configuredValueTaskAwaiter = this.WaitToReadAsync(ct).ConfigureAwait(false).GetAwaiter();
				if (!configuredValueTaskAwaiter.IsCompleted)
				{
					await configuredValueTaskAwaiter;
					ConfiguredValueTaskAwaitable<bool>.ConfiguredValueTaskAwaiter configuredValueTaskAwaiter2;
					configuredValueTaskAwaiter = configuredValueTaskAwaiter2;
					configuredValueTaskAwaiter2 = default(ConfiguredValueTaskAwaitable<bool>.ConfiguredValueTaskAwaiter);
				}
				if (!configuredValueTaskAwaiter.GetResult())
				{
					goto IL_0072;
				}
			}
			while (!this.TryRead(out t));
			return t;
			IL_0072:
			throw new ChannelClosedException();
		}
	}
}
