Skip to content

Commit

Permalink
Adopting primary associated types
Browse files Browse the repository at this point in the history
  • Loading branch information
tevelee committed Jul 29, 2022
1 parent 1fab670 commit 56228ff
Show file tree
Hide file tree
Showing 22 changed files with 316 additions and 68 deletions.
10 changes: 9 additions & 1 deletion Sources/AsyncHTTP/Loader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,19 @@ import Foundation
import FoundationNetworking
#endif

public protocol Loader {
#if compiler(>=5.7)
@rethrows public protocol Loader<Input, Output> {
associatedtype Input
associatedtype Output
func load(_ input: Input) async throws -> Output
}
#else
@rethrows public protocol Loader {
associatedtype Input
associatedtype Output
func load(_ input: Input) async throws -> Output
}
#endif

extension Loader {
public func loadResult(_ input: Input) async -> Result<Output, Error> {
Expand Down
20 changes: 17 additions & 3 deletions Sources/AsyncHTTP/Loaders/Capture.swift
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
import Foundation

extension Loader {
#if compiler(>=5.7)
@_disfavoredOverload
public func capture(input: @escaping (Input) -> Void) -> some Loader<Input, Output> {
Loaders.Capture(self, captureInput: input)
}
#endif

public func capture(input: @escaping (Input) -> Void) -> Loaders.Capture<Self> {
Loaders.Capture<Self>(self, captureInput: input)
.init(self, captureInput: input)
}

#if compiler(>=5.7)
@_disfavoredOverload
public func capture(output: @escaping (Input, Output) -> Void) -> some Loader<Input, Output> {
Loaders.Capture(self, captureOutput: output)
}
#endif

public func capture(output: @escaping (Input, Output) -> Void) -> Loaders.Capture<Self> {
Loaders.Capture<Self>(self, captureOutput: output)
.init(self, captureOutput: output)
}
}

Expand All @@ -27,7 +41,7 @@ extension Loaders {
self.captureOutput = captureOutput
}

public func load(_ input: Input) async throws -> Output {
public func load(_ input: Input) async rethrows -> Output {
captureInput?(input)
let output = try await original.load(input)
captureOutput?(input, output)
Expand Down
24 changes: 20 additions & 4 deletions Sources/AsyncHTTP/Loaders/Decode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,28 @@ import Combine
import Foundation

extension Loader where Output: Decodable {
public func decode<DecodedOutput, Decoder: TopLevelDecoder>(using decoder: Decoder, to type: DecodedOutput.Type = DecodedOutput.self) -> Loaders.Decoded<Self, DecodedOutput, Decoder> where Decoder.Input == Output {
Loaders.Decoded<Self, DecodedOutput, Decoder>(self, decoder: decoder)
#if compiler(>=5.7)
@_disfavoredOverload
public func decode<DecodedOutput: Decodable, Decoder: TopLevelDecoder>(using decoder: Decoder, to type: DecodedOutput.Type = DecodedOutput.self) -> some Loader<Input, DecodedOutput> where Decoder.Input == Output {
Loaders.Decoded(self, decoder: decoder)
}
#endif

public func decode<DecodedOutput: Decodable, Decoder: TopLevelDecoder>(using decoder: Decoder, to type: DecodedOutput.Type = DecodedOutput.self) -> Loaders.Decoded<Self, DecodedOutput, Decoder> where Decoder.Input == Output {
.init(self, decoder: decoder)
}
}

extension Loader where Output == Data {
#if compiler(>=5.7)
@_disfavoredOverload
public func decode<DecodedOutput: Decodable>(using decoder: JSONDecoder = JSONDecoder(), to type: DecodedOutput.Type = DecodedOutput.self) -> some Loader<Input, DecodedOutput> {
Loaders.Decoded(self, decoder: decoder)
}
#endif

public func decode<DecodedOutput>(using decoder: JSONDecoder = JSONDecoder(), to type: DecodedOutput.Type = DecodedOutput.self) -> Loaders.Decoded<Self, DecodedOutput, JSONDecoder> {
Loaders.Decoded<Self, DecodedOutput, JSONDecoder>(self, decoder: decoder)
public func decode<DecodedOutput: Decodable>(using decoder: JSONDecoder = JSONDecoder(), to type: DecodedOutput.Type = DecodedOutput.self) -> Loaders.Decoded<Self, DecodedOutput, JSONDecoder> {
.init(self, decoder: decoder)
}
}

Expand Down
43 changes: 38 additions & 5 deletions Sources/AsyncHTTP/Loaders/FlatMap.swift
Original file line number Diff line number Diff line change
@@ -1,13 +1,31 @@
import Foundation

extension Loader {
public func flatMap<NewLoader: Loader>(_ transform: @escaping (Output) throws -> NewLoader) -> Loaders.FlatMap<Self, NewLoader> where Output == NewLoader.Input {
Loaders.FlatMap<Self, NewLoader>(self, transform)
#if compiler(>=5.7)
@_disfavoredOverload
public func flatMap<NewLoader: Loader>(_ transform: @escaping (Output) throws -> NewLoader) -> some Loader<Input, NewLoader.Output> where Output == NewLoader.Input {
Loaders.ThrowingFlatMap(self, transform)
}
#endif

public func flatMap<NewLoader: Loader>(_ transform: @escaping (Output) throws -> NewLoader) -> Loaders.ThrowingFlatMap<Self, NewLoader> where Output == NewLoader.Input {
.init(self, transform)
}

#if compiler(>=5.7)
@_disfavoredOverload
public func flatMap<NewLoader: Loader>(_ transform: @escaping (Output) -> NewLoader) -> some Loader<Input, NewLoader.Output> where Output == NewLoader.Input {
Loaders.FlatMap(self, transform)
}
#endif

public func flatMap<NewLoader: Loader>(_ transform: @escaping (Output) -> NewLoader) -> Loaders.FlatMap<Self, NewLoader> where Output == NewLoader.Input {
.init(self, transform)
}
}

extension Loaders {
public struct FlatMap<Upstream: Loader, NewLoader: Loader>: Loader where NewLoader.Input == Upstream.Output {
public struct ThrowingFlatMap<Upstream: Loader, NewLoader: Loader>: Loader where NewLoader.Input == Upstream.Output {
public typealias Input = Upstream.Input

private let upstream: Upstream
Expand All @@ -23,6 +41,21 @@ extension Loaders {
return try await transform(output).load(output)
}
}
}

extension Loaders.FlatMap: HTTPLoader where Input == HTTPRequest, Output == HTTPResponse {}
public struct FlatMap<Upstream: Loader, NewLoader: Loader>: Loader where NewLoader.Input == Upstream.Output {
public typealias Input = Upstream.Input

private let upstream: Upstream
private let transform: (Upstream.Output) -> NewLoader

init(_ upstream: Upstream, _ transform: @escaping (Upstream.Output) -> NewLoader) {
self.upstream = upstream
self.transform = transform
}

public func load(_ input: Input) async rethrows -> NewLoader.Output {
let output = try await upstream.load(input)
return try await transform(output).load(output)
}
}
}
17 changes: 14 additions & 3 deletions Sources/AsyncHTTP/Loaders/HTTP.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,24 @@ import FoundationNetworking
#endif

extension Loader where Input == URLRequest, Output == (Data, URLResponse) {
public func httpLoader(modify: ((HTTPRequest, inout URLRequest) -> Void)? = nil) -> Loaders.HTTP<Self> { .init(loader: self, modify: modify) }
#if compiler(>=5.7)
@_disfavoredOverload
public func httpLoader(modify: ((HTTPRequest, inout URLRequest) -> Void)? = nil) -> some HTTPLoader {
Loaders.HTTP(loader: self, modify: modify)
}
#endif

public func httpLoader(modify: ((HTTPRequest, inout URLRequest) -> Void)? = nil) -> Loaders.HTTP<Self> {
Loaders.HTTP(loader: self, modify: modify)
}
}

public protocol HTTPLoader: Loader where Input == HTTPRequest, Output == HTTPResponse {}
#if compiler(>=5.7)
public typealias HTTPLoader = Loader<HTTPRequest, HTTPResponse>
#endif

extension Loaders {
public struct HTTP<Wrapped: Loader>: CompositeLoader, HTTPLoader where Wrapped.Input == URLRequest, Wrapped.Output == (Data, URLResponse) {
public struct HTTP<Wrapped: Loader>: CompositeLoader where Wrapped.Input == URLRequest, Wrapped.Output == (Data, URLResponse) {
private let loader: Wrapped
private let modify: ((HTTPRequest, inout URLRequest) -> Void)?

Expand Down
11 changes: 9 additions & 2 deletions Sources/AsyncHTTP/Loaders/Intercept.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import Foundation

extension Loader {
#if compiler(>=5.7)
@_disfavoredOverload
public func intercept(transform: @escaping (inout Input) -> Void) -> some Loader<Input, Output> {
Loaders.Intercept(self, transform: transform)
}
#endif

public func intercept(transform: @escaping (inout Input) -> Void) -> Loaders.Intercept<Self> {
Loaders.Intercept<Self>(self, transform: transform)
.init(self, transform: transform)
}
}

Expand All @@ -20,7 +27,7 @@ extension Loaders {
self.transform = transform
}

public func load(_ input: Input) async throws -> Output {
public func load(_ input: Input) async rethrows -> Output {
var modified = input
transform?(&modified)
return try await original.load(modified)
Expand Down
42 changes: 37 additions & 5 deletions Sources/AsyncHTTP/Loaders/Map.swift
Original file line number Diff line number Diff line change
@@ -1,13 +1,31 @@
import Foundation

extension Loader {
public func map<NewOutput>(_ transform: @escaping (Output) throws -> NewOutput) -> Loaders.Map<Self, NewOutput> {
Loaders.Map<Self, NewOutput>(self, transform)
#if compiler(>=5.7)
@_disfavoredOverload
public func map<NewOutput>(_ transform: @escaping (Output) throws -> NewOutput) -> some Loader<Input, NewOutput> {
Loaders.ThrowingMap(self, transform)
}
#endif

public func map<NewOutput>(_ transform: @escaping (Output) throws -> NewOutput) -> Loaders.ThrowingMap<Self, NewOutput> {
.init(self, transform)
}

#if compiler(>=5.7)
@_disfavoredOverload
public func map<NewOutput>(_ transform: @escaping (Output) -> NewOutput) -> some Loader<Input, NewOutput> {
Loaders.Map(self, transform)
}
#endif

public func map<NewOutput>(_ transform: @escaping (Output) -> NewOutput) -> Loaders.Map<Self, NewOutput> {
.init(self, transform)
}
}

extension Loaders {
public struct Map<Upstream: Loader, Output>: Loader {
public struct ThrowingMap<Upstream: Loader, Output>: Loader {
public typealias Input = Upstream.Input

private let upstream: Upstream
Expand All @@ -22,6 +40,20 @@ extension Loaders {
try await transform(upstream.load(input))
}
}
}

extension Loaders.Map: HTTPLoader where Input == HTTPRequest, Output == HTTPResponse {}
public struct Map<Upstream: Loader, Output>: Loader {
public typealias Input = Upstream.Input

private let upstream: Upstream
private let transform: (Upstream.Output) -> Output

init(_ upstream: Upstream, _ transform: @escaping (Upstream.Output) -> Output) {
self.upstream = upstream
self.transform = transform
}

public func load(_ input: Input) async rethrows -> Output {
try await transform(upstream.load(input))
}
}
}
11 changes: 9 additions & 2 deletions Sources/AsyncHTTP/Loaders/Pipe.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import Foundation

extension Loader {
public func pipe<Other: Loader>(_ other: Other) -> Loaders.Pipe<Self, Other> {
#if compiler(>=5.7)
@_disfavoredOverload
public func pipe<Other: Loader>(_ other: Other) -> some Loader<Input, Other.Output> where Output == Other.Input {
Loaders.Pipe(self, other)
}
#endif

public func pipe<Other: Loader>(_ other: Other) -> Loaders.Pipe<Self, Other> where Output == Other.Input {
.init(self, other)
}
}

extension Loaders {
Expand All @@ -19,7 +26,7 @@ extension Loaders {
self.downstream = downstream
}

public func load(_ input: Input) async throws -> Output {
public func load(_ input: Input) async rethrows -> Output {
try await downstream.load(upstream.load(input))
}
}
Expand Down
11 changes: 9 additions & 2 deletions Sources/AsyncHTTP/Loaders/Pullback.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import Foundation

extension Loader {
#if compiler(>=5.7)
@_disfavoredOverload
public func pullback<NewInput>(transform: @escaping (NewInput) -> Input) -> some Loader<NewInput, Output> {
Loaders.Pullback(self, transform)
}
#endif

public func pullback<NewInput>(transform: @escaping (NewInput) -> Input) -> Loaders.Pullback<Self, NewInput> {
Loaders.Pullback<Self, NewInput>(self, transform)
.init(self, transform)
}
}

Expand All @@ -18,7 +25,7 @@ extension Loaders {
self.transform = transform
}

public func load(_ input: Input) async throws -> Output {
public func load(_ input: Input) async rethrows -> Output {
try await downstream.load(transform(input))
}
}
Expand Down
12 changes: 11 additions & 1 deletion Sources/AsyncHTTP/Loaders/URLSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,23 @@ extension URLSession {
#endif

extension URLSession {
#if compiler(>=5.7)
public var dataLoader: some Loader<URLRequest, (Data, URLResponse)> {
Loaders.URLSessionData(urlSession: self)
}

public var httpLoader: some HTTPLoader {
dataLoader.httpLoader()
}
#else
public var dataLoader: Loaders.URLSessionData {
.init(urlSession: self)
Loaders.URLSessionData(urlSession: self)
}

public var httpLoader: Loaders.HTTP<Loaders.URLSessionData> {
dataLoader.httpLoader()
}
#endif
}

extension Loaders {
Expand Down
9 changes: 7 additions & 2 deletions Sources/AsyncHTTP/Plugins/Deduplication.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import Foundation

extension Loader {
#if compiler(>=5.7)
@_disfavoredOverload
public func deduplicate() -> some Loader<Input, Output> where Input: Hashable {
Loaders.Deduplicate(loader: self)
}
#endif

public func deduplicate() -> Loaders.Deduplicate<Self> where Input: Hashable {
.init(loader: self)
}
Expand Down Expand Up @@ -30,5 +37,3 @@ extension Loaders {
}
}
}

extension Loaders.Deduplicate: HTTPLoader where Input == HTTPRequest, Output == HTTPResponse {}
9 changes: 7 additions & 2 deletions Sources/AsyncHTTP/Plugins/Delay.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import Foundation

extension Loader {
#if compiler(>=5.7)
@_disfavoredOverload
public func delay(seconds: TimeInterval) -> some Loader<Input, Output> {
Loaders.Delay(loader: self, seconds: seconds)
}
#endif

public func delay(seconds: TimeInterval) -> Loaders.Delay<Self> {
.init(loader: self, seconds: seconds)
}
Expand All @@ -26,5 +33,3 @@ extension Loaders {
}
}
}

extension Loaders.Delay: HTTPLoader where Input == HTTPRequest, Output == HTTPResponse {}
Loading

0 comments on commit 56228ff

Please sign in to comment.