Skip to content

Commit

Permalink
refactor(BidirectionalStream): build support throws (#4)
Browse files Browse the repository at this point in the history
* chore(package): add platform

* refactor(BidirectionalStream): build support throws
  • Loading branch information
rockmagma02 authored Apr 21, 2024
1 parent d86854a commit 579c993
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .swiftlint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ opt_in_rules: # some rules are turned off by default, so you need to opt-in
- joined_default_parameter
- last_where
- legacy_multiple
- legacy_objc_type
# - legacy_objc_type
- let_var_whitespace
- literal_expression_end_indentation
- local_doc_comment
Expand Down
8 changes: 8 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ import PackageDescription

let package = Package(
name: "SyncStream",
platforms: [
.macOS(.v13),
.iOS(.v16),
.watchOS(.v9),
.visionOS(.v1),
.macCatalyst(.v16),
.tvOS(.v16),
],
products: [
// Products define the executables and libraries a package produces, making them visible to other packages.
.library(
Expand Down
45 changes: 45 additions & 0 deletions Sources/SyncStream/BidirectionalAsyncStream.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ public class BidirectionalAsyncStream<YieldT, SendT, ReturnT> {
if case let .finished(value) = finished {
throw StopIteration<ReturnT>(value: value)
}
if case let .error(value) = finished {
throw value
}
if started {
throw WrongStreamUse(
message: "The BidirectionalSyncStream has already started, " +
Expand All @@ -72,6 +75,10 @@ public class BidirectionalAsyncStream<YieldT, SendT, ReturnT> {
finished = .finished(value)
throw StopIteration(value: value)

case let .error(value):
finished = .error(value)
throw value

default:
throw WrongStreamUse(message: "yield or return must be called in the continuation closure")
}
Expand Down Expand Up @@ -99,6 +106,9 @@ public class BidirectionalAsyncStream<YieldT, SendT, ReturnT> {
if case let .finished(value) = finished {
throw StopIteration<ReturnT>(value: value)
}
if case let .error(value) = finished {
throw value
}

continuation.sendValue = element
continuation.state = .sended(element)
Expand All @@ -113,6 +123,10 @@ public class BidirectionalAsyncStream<YieldT, SendT, ReturnT> {
finished = .finished(value)
throw StopIteration(value: value)

case let .error(value):
finished = .error(value)
throw value

default:
throw WrongStreamUse(message: "yield or return must be called in the continuation closure")
}
Expand All @@ -126,6 +140,7 @@ public class BidirectionalAsyncStream<YieldT, SendT, ReturnT> {
case waitingForSend
case sended(SendT)
case finished(ReturnT)
case error(Terminated)
}

// MARK: Private
Expand Down Expand Up @@ -185,6 +200,36 @@ public extension BidirectionalAsyncStream {
await yieldSemaphore.signal()
}

/// Throws an error to the stream and finishes the stream.
/// This is the last call in the stream.
///
/// - Parameters:
/// - error: The error to throw.
public func `throw`(
error: any Error,
fileName: String = #file,
functionName: String = #function,
lineNumber: Int = #line,
columnNumber: Int = #column
) async {
if finished {
fatalError("The stream has finished. Cannot return any more.")
}

finished = true

let filename = (fileName as NSString).lastPathComponent
let terminated = Terminated(
fileName: fileName,
functionName: functionName,
lineNumber: lineNumber,
columnNumber: columnNumber,
error: error
)
state = .error(terminated)
await yieldSemaphore.signal()
}

// MARK: Internal

internal var state: State = .idle
Expand Down
72 changes: 71 additions & 1 deletion Sources/SyncStream/BidirectionalSyncStream.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,35 @@ public struct WrongStreamUse: Error {
public var message: String
}

// MARK: - Terminated

/// An error to indicate that the stream has been terminated.
/// i.e. an error has occurred in the stream.
public struct Terminated: Error {
/// The file name where the error occurred.
public var fileName: String
/// The function name where the error occurred.
public var functionName: String
/// The line number where the error occurred.
public var lineNumber: Int
/// The column number where the error occurred.
public var columnNumber: Int
/// The error that occurred.
public var error: any Error

public var localizedDescription: String {
"Terminated in \(fileName) at \(functionName):\(lineNumber):\(columnNumber) "
+ "with error: \(error.localizedDescription)"
}
}

// MARK: - NoneType

/// A type to represent `None` in Python.
public struct NoneType {}
public struct NoneType {
/// Creates a new `NoneType`.
public init() {}
}

// MARK: - BidirectionalSyncStream

Expand Down Expand Up @@ -72,6 +97,9 @@ public class BidirectionalSyncStream<YieldT, SendT, ReturnT> {
if case let .finished(value) = finished {
throw StopIteration<ReturnT>(value: value)
}
if case let .error(value) = finished {
throw value
}
if started {
throw WrongStreamUse(
message: "The BidirectionalSyncStream has already started, " +
Expand All @@ -90,6 +118,10 @@ public class BidirectionalSyncStream<YieldT, SendT, ReturnT> {
finished = .finished(value)
throw StopIteration(value: value)

case let .error(value):
finished = .error(value)
throw value

default:
throw WrongStreamUse(message: "yield or return must be called in the continuation closure")
}
Expand Down Expand Up @@ -117,6 +149,9 @@ public class BidirectionalSyncStream<YieldT, SendT, ReturnT> {
if case let .finished(value) = finished {
throw StopIteration<ReturnT>(value: value)
}
if case let .error(value) = finished {
throw value
}

continuation.sendValue = element
continuation.state = .sended(element)
Expand All @@ -131,6 +166,10 @@ public class BidirectionalSyncStream<YieldT, SendT, ReturnT> {
finished = .finished(value)
throw StopIteration(value: value)

case let .error(value):
finished = .error(value)
throw value

default:
throw WrongStreamUse(message: "yield or return must be called in the continuation closure")
}
Expand All @@ -144,6 +183,7 @@ public class BidirectionalSyncStream<YieldT, SendT, ReturnT> {
case waitingForSend
case sended(SendT)
case finished(ReturnT)
case error(Terminated)
}

// MARK: Private
Expand Down Expand Up @@ -204,6 +244,36 @@ public extension BidirectionalSyncStream {
yieldSemaphore.signal()
}

/// Throws an error to the stream and finishes the stream.
/// This is the last call in the stream.
///
/// - Parameters:
/// - error: The error to throw.
public func `throw`(
error: any Error,
fileName: String = #file,
functionName: String = #function,
lineNumber: Int = #line,
columnNumber: Int = #column
) {
if finished {
fatalError("The stream has finished. Cannot return any more.")
}

finished = true

let filename = (fileName as NSString).lastPathComponent
let terminated = Terminated(
fileName: fileName,
functionName: functionName,
lineNumber: lineNumber,
columnNumber: columnNumber,
error: error
)
state = .error(terminated)
yieldSemaphore.signal()
}

// MARK: Internal

internal var state: State = .idle
Expand Down

0 comments on commit 579c993

Please sign in to comment.