Skip to content
This repository has been archived by the owner on Oct 1, 2024. It is now read-only.

Commit

Permalink
Add AsyncStream convenience initializer
Browse files Browse the repository at this point in the history
  • Loading branch information
josh committed Mar 25, 2024
1 parent 4a8d9e8 commit 335c151
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 0 deletions.
8 changes: 8 additions & 0 deletions Aware.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
objects = {

/* Begin PBXBuildFile section */
03162DE12BB12F3B0004BFDE /* AsyncStream+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03162DE02BB12F3B0004BFDE /* AsyncStream+Extensions.swift */; };
03162DE32BB130880004BFDE /* AsyncStreamTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03162DE22BB130880004BFDE /* AsyncStreamTests.swift */; };
0338DB392BABAE5D00C4E560 /* WatchChannelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0338DB382BABAE5D00C4E560 /* WatchChannelTests.swift */; };
033A81F92BA8078B001216AA /* WatchChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 033A81F82BA8078B001216AA /* WatchChannel.swift */; };
03409BC42B897F7C00EF8EE9 /* ActivityMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03409BC32B897F7C00EF8EE9 /* ActivityMonitor.swift */; platformFilters = (xros, ); };
Expand Down Expand Up @@ -48,6 +50,8 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
03162DE02BB12F3B0004BFDE /* AsyncStream+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AsyncStream+Extensions.swift"; sourceTree = "<group>"; };
03162DE22BB130880004BFDE /* AsyncStreamTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncStreamTests.swift; sourceTree = "<group>"; };
0338DB382BABAE5D00C4E560 /* WatchChannelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchChannelTests.swift; sourceTree = "<group>"; };
033A81F82BA8078B001216AA /* WatchChannel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchChannel.swift; sourceTree = "<group>"; };
03409BC32B897F7C00EF8EE9 /* ActivityMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityMonitor.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -103,6 +107,7 @@
0341CB6F2B9C35EE00CC0C96 /* Shared */ = {
isa = PBXGroup;
children = (
03162DE02BB12F3B0004BFDE /* AsyncStream+Extensions.swift */,
0347D59E2BAFB97300C5741E /* BackgroundTask.swift */,
0388587F2BA54DBA003E287D /* Duration+Extensions.swift */,
03F9E2301C24CCA8001DBE86 /* FormatStyle+Extensions.swift */,
Expand Down Expand Up @@ -177,6 +182,7 @@
03F9E2271C24CAD3001DBE86 /* AwareTests */ = {
isa = PBXGroup;
children = (
03162DE22BB130880004BFDE /* AsyncStreamTests.swift */,
03F9E2321C24CD2E001DBE86 /* FormatStylesTests.swift */,
0347D59A2BAF8CB200C5741E /* NotificationCenterTests.swift */,
0341CB762B9CDEC400CC0C96 /* TimerStateTests.swift */,
Expand Down Expand Up @@ -298,6 +304,7 @@
buildActionMask = 2147483647;
files = (
036DA9B52B7AF52E0066B4B2 /* App.swift in Sources */,
03162DE12BB12F3B0004BFDE /* AsyncStream+Extensions.swift in Sources */,
0347D59F2BAFB97300C5741E /* BackgroundTask.swift in Sources */,
038858802BA54DBA003E287D /* Duration+Extensions.swift in Sources */,
03F9E2311C24CCA8001DBE86 /* FormatStyle+Extensions.swift in Sources */,
Expand Down Expand Up @@ -325,6 +332,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
03162DE32BB130880004BFDE /* AsyncStreamTests.swift in Sources */,
03F9E2331C24CD2E001DBE86 /* FormatStylesTests.swift in Sources */,
0347D59B2BAF8CB200C5741E /* NotificationCenterTests.swift in Sources */,
0341CB772B9CDEC400CC0C96 /* TimerStateTests.swift in Sources */,
Expand Down
39 changes: 39 additions & 0 deletions Aware/Shared/AsyncStream+Extensions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//
// AsyncStream+Extensions.swift
// Aware
//
// Created by Joshua Peek on 3/24/24.
//

extension AsyncStream {
/// Annoying wrapper to get
/// typealias Yield = @discardableResult (Element) -> Continuation.YieldResult
struct Yield: Sendable {
private let continuation: Continuation

fileprivate init(continuation: Continuation) {
self.continuation = continuation
}

@discardableResult
func callAsFunction(_ value: Element) -> Continuation.YieldResult {
continuation.yield(value)
}
}

init(
_ elementType: Element.Type = Element.self,
bufferingPolicy limit: Continuation.BufferingPolicy = .unbounded,
_ build: @Sendable @escaping (Yield) async -> Void
) {
self.init(elementType, bufferingPolicy: limit) { continuation in
let task = Task {
await build(Yield(continuation: continuation))
continuation.finish()
}
continuation.onTermination = { _ in
task.cancel()
}
}
}
}
47 changes: 47 additions & 0 deletions AwareTests/AsyncStreamTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import XCTest

@testable import Aware

final class AsyncStreamTests: XCTestCase {
func testSimpleAsyncStream() async throws {
@Sendable func answer() async -> Int {
42
}

let stream = AsyncStream { [answer] yield in
let n = await answer()
yield(n)
yield(n + 1)
yield(n + 2)
}

var numbers: [Int] = []
for await n in stream {
numbers.append(n)
}

XCTAssertEqual(numbers, [42, 43, 44])
}

func testMapAsyncStream() async throws {
let stream1 = AsyncStream { continuation in
continuation.yield(1)
continuation.yield(2)
continuation.yield(3)
continuation.finish()
}

let stream2 = AsyncStream { yield in
for await n in stream1 {
yield(n * 2)
}
}

var numbers: [Int] = []
for await n in stream2 {
numbers.append(n)
}

XCTAssertEqual(numbers, [2, 4, 6])
}
}

0 comments on commit 335c151

Please sign in to comment.