Skip to content

Commit

Permalink
Merge pull request #2 from 0xLeif/develop
Browse files Browse the repository at this point in the history
0.2.0 ChainOutput
  • Loading branch information
0xLeif authored Mar 2, 2021
2 parents f094947 + bcdf63d commit a431a47
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 27 deletions.
5 changes: 4 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,16 @@ let package = Package(
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
.package(name: "E", url: "https://github.com/0xLeif/E.num", from: "0.3.0")
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "Chain",
dependencies: []),
dependencies: [
"E"
]),
.testTarget(
name: "ChainTests",
dependencies: ["Chain"]),
Expand Down
68 changes: 51 additions & 17 deletions Sources/Chain/Chain.swift
Original file line number Diff line number Diff line change
@@ -1,40 +1,74 @@
import Foundation

public typealias ChainAction = () -> Void
import E

public indirect enum Chain {
case end
case complete(ChainAction?)
case link(ChainAction, Chain)
case background(ChainAction, Chain)
case complete(E.Function?)
case link(E.Function, Chain)
case background(E.Function, Chain)
case multi([Chain])
}

public extension Chain {
func run() {
func run(
name: String? = nil,
input: Variable? = nil,
shouldFlattenOutput: Bool = false
) -> Variable {
var logInfo: String {
"[\(Date())] Chain\(name.map { " (\($0)) "} ?? ""):"
}
var output: Variable = .array([])

switch self {
case .end:
print("[\(Date())] Chain: End")
print("\(logInfo) End")

output = output.update {
.array($0 + [Variable.void])
}
case .complete(let completion):
print("[\(Date())] Chain: Complete")
completion?()
print("\(logInfo) Complete")

output = output.update {
.array($0 + [completion?.run(input) ?? Variable.void])
}
case .link(let action,
let next):
print("[\(Date())] Chain: Link")
action()
next.run()
print("\(logInfo) Link")

let actionOutput: Variable = action.run(input) ?? Variable.void

output = output.update {
.array($0 + [actionOutput] + [next.run(name: name, input: actionOutput)])
}
case .background(let action,
let next):
print("[\(Date())] Chain: Background")
print("\(logInfo) Background")
DispatchQueue.global().async {
action()
let actionOutput: Variable = action.run(input) ?? Variable.void

output = output.update {
.array($0 + [actionOutput])
}
DispatchQueue.main.async {
next.run()
output = output.update {
.array($0 + [next.run(name: name, input: actionOutput)])
}
}
}
case .multi(let links):
print("[\(Date())] Chain: Multi")
links.forEach { $0.run() }
print("\(logInfo) Multi")
output = output.update {
.array($0 + links.map { $0.run(name: name) })
}
}

// Flatten Output
if shouldFlattenOutput {
return output.flatten
}

return output
}
}
88 changes: 79 additions & 9 deletions Tests/ChainTests/ChainTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,92 @@ import XCTest
final class ChainTests: XCTestCase {
func testExample() {
var text = ""
var isLooping = false

Chain.link(
{ print(0) },
let output = Chain.link(
.void { print(0) },
.link(
{ print(1) },
.link(
{ print(3) },
.complete {
text = "Hello, World!"
}
.void { print(1) },
.multi(
[
.background(
.void {
print("Loading...")
sleep(5)
print("Loading Done!")
isLooping = false
},
.complete(.void {
XCTAssertEqual(isLooping, false)
})
),

.link(
.void {
isLooping = true
while isLooping { }
},
.complete(.void {
text = "Hello, World!"
})
)


]
)
)
)
.run()
.run(name: "ChainTests-testExample")

XCTAssertEqual(text, "Hello, World!")

guard case .array(let values) = output else {
XCTFail()
return
}

XCTAssertNotEqual(values.count, 0)
}

func testOutput() {
let output = Chain.link(
.out { "First" },
.link( .in {
print("Value: \($0)")
}, .multi(
[
.multi([
.end,
.end,
.end
]),
.link(.out {
"Link"
}, .link(
.out { "Last" },
.complete(.inout { value in
guard case .string(let value) = value else {
XCTFail()
return .void
}

return .string("\(value) !!!")
})
))
]
))

)
.run(name: "ChainTests-testOutput", shouldFlattenOutput: true)

guard case .array(let values) = output else {
XCTFail()
return
}

XCTAssertEqual(values[0], .string("First"))
XCTAssertEqual(values.last, .string("Last !!!"))
XCTAssertEqual(values.count, 8)
}

static var allTests = [
Expand Down

0 comments on commit a431a47

Please sign in to comment.