Skip to content

Commit

Permalink
Added IAsyncEnumerable<T>.ToAsyncEnumerable() extension method.
Browse files Browse the repository at this point in the history
Added `AsyncEnumerable<T>.Create` functions.
Fixed `AsyncEnumerable<T>.ConfigureAwait(false)` to match behavior of `IAsyncEnumerable<T>ConfigureAwait(false)`.
Enabled C#8 for `await foreach` support.
  • Loading branch information
timcassell committed Nov 3, 2023
1 parent e69588d commit d28ec09
Show file tree
Hide file tree
Showing 6 changed files with 605 additions and 11 deletions.
35 changes: 25 additions & 10 deletions Package/Core/Linq/AsyncEnumerable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,13 @@ public static class AsyncEnumerable
/// Create a new <see cref="AsyncEnumerable{T}"/> async stream from the specified <paramref name="asyncIterator"/> function.
/// </summary>
public static AsyncEnumerable<T> Create<T>(Func<AsyncStreamWriter<T>, CancelationToken, AsyncEnumerableMethod> asyncIterator)
{
var enumerable = Internal.AsyncEnumerableImpl<T, Internal.AsyncIterator<T>>.GetOrCreate(new Internal.AsyncIterator<T>(asyncIterator));
return new AsyncEnumerable<T>(enumerable);
}
=> AsyncEnumerable<T>.Create(asyncIterator);

/// <summary>
/// Create a new <see cref="AsyncEnumerable{T}"/> async stream from the specified <paramref name="captureValue"/> and <paramref name="asyncIterator"/> function.
/// </summary>
public static AsyncEnumerable<T> Create<T, TCapture>(TCapture captureValue, Func<TCapture, AsyncStreamWriter<T>, CancelationToken, AsyncEnumerableMethod> asyncIterator)
{
var enumerable = Internal.AsyncEnumerableImpl<T, Internal.AsyncIterator<T, TCapture>>.GetOrCreate(new Internal.AsyncIterator<T, TCapture>(captureValue, asyncIterator));
return new AsyncEnumerable<T>(enumerable);
}
=> AsyncEnumerable<T>.Create(captureValue, asyncIterator);
}

/// <summary>
Expand All @@ -47,7 +41,28 @@ public static AsyncEnumerable<T> Create<T, TCapture>(TCapture captureValue, Func
#if !PROTO_PROMISE_DEVELOPER_MODE
[DebuggerNonUserCode, StackTraceHidden]
#endif
public readonly struct AsyncEnumerable<T> : IAsyncEnumerable<T>
public readonly partial struct AsyncEnumerable<T> : IAsyncEnumerable<T>
{
/// <summary>
/// Create a new <see cref="AsyncEnumerable{T}"/> async stream from the specified <paramref name="asyncIterator"/> function.
/// </summary>
public static AsyncEnumerable<T> Create(Func<AsyncStreamWriter<T>, CancelationToken, AsyncEnumerableMethod> asyncIterator)
{
var enumerable = Internal.AsyncEnumerableImpl<T, Internal.AsyncIterator<T>>.GetOrCreate(new Internal.AsyncIterator<T>(asyncIterator));
return new AsyncEnumerable<T>(enumerable);
}

/// <summary>
/// Create a new <see cref="AsyncEnumerable{T}"/> async stream from the specified <paramref name="captureValue"/> and <paramref name="asyncIterator"/> function.
/// </summary>
public static AsyncEnumerable<T> Create<TCapture>(TCapture captureValue, Func<TCapture, AsyncStreamWriter<T>, CancelationToken, AsyncEnumerableMethod> asyncIterator)
{
var enumerable = Internal.AsyncEnumerableImpl<T, Internal.AsyncIterator<T, TCapture>>.GetOrCreate(new Internal.AsyncIterator<T, TCapture>(captureValue, asyncIterator));
return new AsyncEnumerable<T>(enumerable);
}
}

public readonly partial struct AsyncEnumerable<T> : IAsyncEnumerable<T>
{
private readonly Internal.PromiseRefBase.AsyncEnumerableBase<T> _target;
private readonly int _id;
Expand Down Expand Up @@ -120,7 +135,7 @@ public ConfiguredAsyncEnumerable<T> WithCancellation(CancellationToken cancellat

[EditorBrowsable(EditorBrowsableState.Never)]
public ConfiguredAsyncEnumerable<T> ConfigureAwait(bool continueOnCapturedContext)
=> continueOnCapturedContext ? ConfigureAwait(SynchronizationContext.Current) : ConfigureAwait(SynchronizationOption.Background);
=> continueOnCapturedContext ? ConfigureAwait(SynchronizationContext.Current) : ConfigureAwait(SynchronizationOption.Synchronous);
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
}

Expand Down
30 changes: 30 additions & 0 deletions Package/Core/Linq/AsyncEnumerableExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System.Collections.Generic;
using System.Diagnostics;

namespace Proto.Promises.Linq
{
#if NET47_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NETCOREAPP || UNITY_2021_2_OR_NEWER
/// <summary>
/// Provides extension methods for <see cref="AsyncEnumerable{T}"/>.
/// </summary>
#if !PROTO_PROMISE_DEVELOPER_MODE
[DebuggerNonUserCode, StackTraceHidden]
#endif
public static class AsyncEnumerableExtensions
{
/// <summary>
/// Convert the <see cref="IAsyncEnumerable{T}"/> <paramref name="source"/> to an <see cref="AsyncEnumerable{T}"/>.
/// </summary>
public static AsyncEnumerable<T> ToAsyncEnumerable<T>(this IAsyncEnumerable<T> source)
{
return AsyncEnumerable<T>.Create(source, async (_source, writer, cancelationToken) =>
{
await foreach (T item in System.Threading.Tasks.TaskAsyncEnumerableExtensions.WithCancellation(source, cancelationToken.ToCancellationToken()).ConfigureAwait(false))
{
await writer.YieldAsync(item);
}
});
}
}
#endif // NET47_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NETCOREAPP || UNITY_2021_2_OR_NEWER
}
11 changes: 11 additions & 0 deletions Package/Core/Linq/AsyncEnumerableExtensions.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit d28ec09

Please sign in to comment.