Skip to content

Commit

Permalink
init public beta
Browse files Browse the repository at this point in the history
  • Loading branch information
cham-s committed Oct 31, 2024
0 parents commit 4953499
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.DS_Store
/.build
/Packages
xcuserdata/
DerivedData/
.swiftpm/configuration/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
30 changes: 30 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// swift-tools-version: 6.0

import PackageDescription

let package = Package(
name: "general-types",
platforms: [
.iOS(.v13),
.macOS(.v10_15),
.tvOS(.v13),
.watchOS(.v6),
.visionOS(.v1)
],
products: [
.library(name: "AsyncStreamTypes", targets: ["AsyncStreamTypes"]),
.library(name: "DebuggingTypes", targets: ["DebuggingTypes"])
],
dependencies: [
],
targets: [
.target(name: "AsyncStreamTypes"),
.target(name: "DebuggingTypes"),
.testTarget(
name: "AsyncStreamTypesTests",
dependencies: [
"AsyncStreamTypes",
]
),
]
)
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# General Types

> [!WARNING]
>
> Please be aware that this package is experimental, integration in a production code should be carefully considered.
## Overview

Shared types used in different Swift packages.

### AsyncStream additions

`Stream` and `ThrowingStream`are simple typealiases.

```swift
/// A stream with its continuation.
public typealias Stream<Element> = (
stream: AsyncStream<Element>,
continuation: AsyncStream<Element>.Continuation
)

/// A throwing stream with its continuation.
public typealias ThrowingStream<Element, E: Error> = (
stream: AsyncThrowingStream<Element, E>,
continuation: AsyncThrowingStream<Element, E>.Continuation
)
```

For `AsyncStream` and `AsyncThrowingStream` where `Element` is `Sendable` an additional `yield(finalValue: Element)` method has been added to combine two operations in one: Yielding a final value and finishing the stream.

Small gain but it makes the intent more explicit and help avoid situations where we intend to send a final value and close the stream but we forget to finish the stream leaving the subscriber hanging.

```swift
let intStream = AsyncStream<Int>.makeStream()
// Enqueues values
intStream.continuation.yield(0)
intStream.continuation.yield(1)
intStream.continuation.yield(2)
intStream.continuation.yield(3)

// Yields the final value and ends the stream.
intStream.continuation.yield(finalValue: 4)
/*
Equivalent of:
intStream.continuation.yield(4)
intStream.continuation.finish()
*/
```
39 changes: 39 additions & 0 deletions Sources/AsyncStreamTypes/Stream.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/// A stream with its continuation.
public typealias Stream<Element> = (
stream: AsyncStream<Element>,
continuation: AsyncStream<Element>.Continuation
)

/// A throwing stream with its continuation.
public typealias ThrowingStream<Element, E: Error> = (
stream: AsyncThrowingStream<Element, E>,
continuation: AsyncThrowingStream<Element, E>.Continuation
)

extension AsyncStream.Continuation where Element: Sendable {
/// Yields a final value before finishing.
///
/// Encapuslates two operations:
/// ```swift
///contiunation.yield(value)
///contiunation.finish()
/// ```
public func yield(finalValue: Element) {
self.yield(finalValue)
self.finish()
}
}

extension AsyncThrowingStream.Continuation where Element: Sendable {
/// Yields a final value before finishing.
///
/// Encapuslates two operations:
/// ```swift
///contiunation.yield(value)
///contiunation.finish()
/// ```
public func yield(finalValue: Element) {
self.yield(finalValue)
self.finish()
}
}
17 changes: 17 additions & 0 deletions Sources/DebuggingTypes/Debugging.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/// A type used to throw an error on purpose when debuging and testing for throwring logic.
public struct DebugThrow: Error {
public let line: Int
public let file: String
public let comment: String

public init(
line: Int = #line,
file: String = #file,
comment: String = ""
) {
self.line = line
self.file = file
self.comment = comment
}
}

23 changes: 23 additions & 0 deletions Tests/AsyncStreamTypesTests/YieldFinalValueTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import Testing
import AsyncStreamTypes

@Test func YieldFinalValue() async throws {
let intStream = AsyncStream<Int>.makeStream()

// Enqueues values
intStream.continuation.yield(0)
intStream.continuation.yield(1)
intStream.continuation.yield(2)
intStream.continuation.yield(3)

// Yields the final value
intStream.continuation.yield(finalValue: 4)

var iterator = intStream.stream.makeAsyncIterator()
#expect(await iterator.next() == 0)
#expect(await iterator.next() == 1)
#expect(await iterator.next() == 2)
#expect(await iterator.next() == 3)
#expect(await iterator.next() == 4)
#expect(await iterator.next() == nil)
}

0 comments on commit 4953499

Please sign in to comment.