Skip to content

Commit 2b66b2b

Browse files
committed
Merge bugfixes into main
2 parents 5c55203 + 9b8f676 commit 2b66b2b

File tree

10 files changed

+207
-85
lines changed

10 files changed

+207
-85
lines changed

Package.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@ let package = Package(
2020
.library(name: "StorageCrypto",
2121
targets: ["ComposableStorageCrypto"])],
2222
// Package dependencies.
23-
dependencies: [.package(url: "https://github.com/sbertix/Swiftchain.git",
24-
.upToNextMinor(from: "1.0.0"))],
23+
dependencies: [.package(url: "https://github.com/kishikawakatsumi/KeychainAccess",
24+
.upToNextMinor(from: "4.2.2"))],
2525
// All targets.
2626
targets: [.target(name: "ComposableRequest"),
2727
.target(name: "ComposableStorage",
2828
dependencies: []),
2929
.target(name: "ComposableStorageCrypto",
30-
dependencies: ["ComposableStorage", "Swiftchain"]),
30+
dependencies: ["ComposableStorage", "KeychainAccess"]),
3131
.testTarget(name: "ComposableRequestTests",
3232
dependencies: ["ComposableRequest", "ComposableStorage", "ComposableStorageCrypto"])]
3333
)

Sources/ComposableRequest/Providers/Pager/ComposableOptionalType.swift

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,49 @@
77

88
import Foundation
99

10+
/// A `protocol` defining a `ComposableRequest` abstraction for `nil`-checking `Optional`s.
11+
public protocol ComposableNonNilType {
12+
/// Check whether it's `nil` or not.
13+
var composableIsNone: Bool { get }
14+
}
15+
1016
/// A `protocol` defining a `ComposableRequest` abtrasction into `Optional`.
11-
public protocol ComposableOptionalType {
17+
public protocol ComposableOptionalType: ComposableNonNilType {
1218
associatedtype Wrapped
1319

1420
/// The associated `nil` value.
15-
static var optionalTypeNone: Self { get }
21+
static var composableNone: Self { get }
22+
23+
/// Return the actual `Optional`.
24+
var composableOptional: Wrapped? { get }
25+
}
26+
27+
extension ComposableOptionalType {
28+
/// Flat map the current value.
29+
///
30+
/// - parameter transformer: A valid mapper.
31+
/// - returns: An optional value.
32+
func composableFlatMap<T>(_ transformer: (Wrapped) -> T?) -> T? {
33+
composableOptional.flatMap(transformer)
34+
}
1635
}
1736

1837
extension Optional: ComposableOptionalType {
1938
/// The associated `nil` value.
20-
public static var optionalTypeNone: Self { .none }
39+
public static var composableNone: Self {
40+
.none
41+
}
42+
43+
/// Check whether it's `nil` or not.
44+
public var composableIsNone: Bool {
45+
switch self {
46+
case .none: return true
47+
default: return false
48+
}
49+
}
50+
51+
/// Return the actual `Optional`.
52+
public var composableOptional: Wrapped? {
53+
self
54+
}
2155
}

Sources/ComposableRequest/Providers/Pager/PagerProviderType.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public extension PagerProviderType where Offset: ComposableOptionalType {
4141
/// - parameter count: A valid `Int`.
4242
/// - returns: Some `Content`.
4343
func pages(_ count: Int) -> Output {
44-
self.pages(count, offset: .optionalTypeNone)
44+
self.pages(count, offset: .composableNone)
4545
}
4646
}
4747

@@ -66,7 +66,7 @@ public extension PagerProviderType where Offset: Ranked, Offset.Offset: Composab
6666
/// - rank: A valid `Rank`.
6767
/// - returns: Some `Content`.
6868
func pages(_ count: Int, rank: Offset.Rank) -> Output {
69-
self.pages(count, offset: .init(offset: .optionalTypeNone, rank: rank))
69+
self.pages(count, offset: .init(offset: .composableNone, rank: rank))
7070
}
7171
}
7272

@@ -78,7 +78,7 @@ public extension PagerProviderType where Offset: Ranked, Offset.Rank: Composable
7878
/// - offset: A valid `Offset`.
7979
/// - returns: Some `Content`.
8080
func pages(_ count: Int, offset: Offset.Offset) -> Output {
81-
self.pages(count, offset: .init(offset: offset, rank: .optionalTypeNone))
81+
self.pages(count, offset: .init(offset: offset, rank: .composableNone))
8282
}
8383
}
8484

@@ -88,6 +88,6 @@ public extension PagerProviderType where Offset: Ranked, Offset.Offset: Composab
8888
/// - parameter count: A valid `Int`.
8989
/// - returns: Some `Content`.
9090
func pages(_ count: Int) -> Output {
91-
self.pages(count, offset: .init(offset: .optionalTypeNone, rank: .optionalTypeNone))
91+
self.pages(count, offset: .init(offset: .composableNone, rank: .composableNone))
9292
}
9393
}

Sources/ComposableRequest/Publishers/Pager/Pager+Iteration.swift

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,24 @@ public extension Pager {
1414
/// The underlying stream.
1515
public let stream: Stream
1616
/// The underlying offset generator.
17-
public let offset: ([Output]) -> Offset?
17+
public let offset: ([Output]) -> Instruction<Offset>
1818
}
1919
}
2020

21+
/// An `enum` listing all valid instructions.
22+
public enum Instruction<Offset> {
23+
/// Stop paginating.
24+
case stop
25+
/// Load next offset.
26+
case load(Offset)
27+
}
28+
2129
public extension Publisher {
2230
/// Create the iteration.
2331
///
2432
/// - parameter offset: A valid offset generator.
2533
/// - returns: A valid `Pager.Iteration`.
26-
func iterate<O>(with offset: @escaping ([Output]) -> O?) -> Pager<O, Self>.Iteration {
34+
func iterate<O>(with offset: @escaping ([Output]) -> Instruction<O>) -> Pager<O, Self>.Iteration {
2735
.init(stream: self, offset: offset)
2836
}
2937

@@ -34,8 +42,15 @@ public extension Publisher {
3442
/// - offet: A valid offset generator.
3543
/// - returns: A valid `Pager.Iteration`.
3644
func iterate<O>(stoppingAt exception: @escaping (O) -> Bool,
37-
with offset: @escaping ([Output]) -> O?) -> Pager<O, Self>.Iteration {
38-
iterate { offset($0).flatMap { exception($0) ? nil : $0 }}
45+
with offset: @escaping ([Output]) -> Instruction<O>) -> Pager<O, Self>.Iteration {
46+
iterate {
47+
switch offset($0) {
48+
case .stop:
49+
return .stop
50+
case .load(let next):
51+
return exception(next) ? .stop : .load(next)
52+
}
53+
}
3954
}
4055

4156
/// Create the iteration, making sure we don't get stuck inside an infinite loop.
@@ -45,15 +60,15 @@ public extension Publisher {
4560
/// - offet: A valid offset generator.
4661
/// - returns: A valid `Pager.Iteration`.
4762
func iterate<O>(stoppingAt exception: O,
48-
with offset: @escaping ([Output]) -> O?) -> Pager<O, Self>.Iteration where O: Equatable {
63+
with offset: @escaping ([Output]) -> Instruction<O>) -> Pager<O, Self>.Iteration where O: Equatable {
4964
iterate(stoppingAt: { $0 == exception }, with: offset)
5065
}
5166

5267
/// Create the iteration, after only one output.
5368
///
5469
/// - parameter offset: A valid offset generator.
5570
/// - returns: A valid `Pager.Iteration`.
56-
func iterateFirst<O>(with offset: @escaping (Output?) -> O?) -> Pager<O, Publishers.Output<Self>>.Iteration {
71+
func iterateFirst<O>(with offset: @escaping (Output?) -> Instruction<O>) -> Pager<O, Publishers.Output<Self>>.Iteration {
5772
prefix(1).iterate { offset($0.first) }
5873
}
5974

@@ -64,8 +79,15 @@ public extension Publisher {
6479
/// - offet: A valid offset generator.
6580
/// - returns: A valid `Pager.Iteration`.
6681
func iterateFirst<O>(stoppingAt exception: @escaping (O) -> Bool,
67-
with offset: @escaping (Output?) -> O?) -> Pager<O, Publishers.Output<Self>>.Iteration {
68-
iterateFirst { offset($0).flatMap { exception($0) ? nil : $0 }}
82+
with offset: @escaping (Output?) -> Instruction<O>) -> Pager<O, Publishers.Output<Self>>.Iteration {
83+
iterateFirst {
84+
switch offset($0) {
85+
case .stop:
86+
return .stop
87+
case .load(let next):
88+
return exception(next) ? .stop : .load(next)
89+
}
90+
}
6991
}
7092

7193
/// Create the iteration, after only one output, making sure we don't get stuck inside an infinite loop.
@@ -75,15 +97,15 @@ public extension Publisher {
7597
/// - offet: A valid offset generator.
7698
/// - returns: A valid `Pager.Iteration`.
7799
func iterateFirst<O>(stoppingAt exception: O,
78-
with offset: @escaping (Output?) -> O?) -> Pager<O, Publishers.Output<Self>>.Iteration where O: Equatable {
100+
with offset: @escaping (Output?) -> Instruction<O>) -> Pager<O, Publishers.Output<Self>>.Iteration where O: Equatable {
79101
iterateFirst(stoppingAt: { $0 == exception }, with: offset)
80102
}
81103

82104
/// Create the iteration, on the last output alone.
83105
///
84106
/// - parameter offset: A valid offset generator.
85107
/// - returns: A valid `Pager.Iteration`.
86-
func iterateLast<O>(with offset: @escaping (Output?) -> O?) -> Pager<O, Publishers.Last<Self>>.Iteration {
108+
func iterateLast<O>(with offset: @escaping (Output?) -> Instruction<O>) -> Pager<O, Publishers.Last<Self>>.Iteration {
87109
last().iterate { offset($0.first) }
88110
}
89111

@@ -94,8 +116,15 @@ public extension Publisher {
94116
/// - offet: A valid offset generator.
95117
/// - returns: A valid `Pager.Iteration`.
96118
func iterateLast<O>(stoppingAt exception: @escaping (O) -> Bool,
97-
with offset: @escaping (Output?) -> O?) -> Pager<O, Publishers.Last<Self>>.Iteration {
98-
iterateLast { offset($0).flatMap { exception($0) ? nil : $0 }}
119+
with offset: @escaping (Output?) -> Instruction<O>) -> Pager<O, Publishers.Last<Self>>.Iteration {
120+
iterateLast {
121+
switch offset($0) {
122+
case .stop:
123+
return .stop
124+
case .load(let next):
125+
return exception(next) ? .stop : .load(next)
126+
}
127+
}
99128
}
100129

101130
/// Create the iteration, on the last output alone., making sure we don't get stuck inside an infinite loop.
@@ -105,7 +134,7 @@ public extension Publisher {
105134
/// - offet: A valid offset generator.
106135
/// - returns: A valid `Pager.Iteration`.
107136
func iterateLast<O>(stoppingAt exception: O,
108-
with offset: @escaping (Output?) -> O?) -> Pager<O, Publishers.Last<Self>>.Iteration where O: Equatable {
137+
with offset: @escaping (Output?) -> Instruction<O>) -> Pager<O, Publishers.Last<Self>>.Iteration where O: Equatable {
109138
iterateLast(stoppingAt: { $0 == exception }, with: offset)
110139
}
111140

@@ -114,7 +143,7 @@ public extension Publisher {
114143
/// - parameter continue: A valid offset boolean generator.
115144
/// - returns: A valid `Pager.Iteration`.
116145
func iterate(_ `continue`: @escaping ([Output]) -> Bool = { _ in true }) -> Pager<Void, Self>.Iteration {
117-
.init(stream: self) { `continue`($0) ? () : nil }
146+
.init(stream: self) { `continue`($0) ? .load(()) : .stop }
118147
}
119148
}
120149

@@ -124,7 +153,7 @@ public extension Publisher where Failure == Never {
124153
/// - warning: The `Publisher` is still not guaranteed to return an output. You should only use this when you're certain it will.
125154
/// - parameter offset: A valid offset generator.
126155
/// - returns: A valid `Pager.Iteration`.
127-
func iterateFirst<O>(with offset: @escaping (Output) -> O?) -> Pager<O, Publishers.Output<Self>>.Iteration {
156+
func iterateFirst<O>(with offset: @escaping (Output) -> Instruction<O>) -> Pager<O, Publishers.Output<Self>>.Iteration {
128157
iterateFirst { offset($0!) }
129158
}
130159

@@ -135,7 +164,7 @@ public extension Publisher where Failure == Never {
135164
/// - offet: A valid offset generator.
136165
/// - returns: A valid `Pager.Iteration`.
137166
func iterateFirst<O>(stoppingAt exception: @escaping (O) -> Bool,
138-
with offset: @escaping (Output) -> O?) -> Pager<O, Publishers.Output<Self>>.Iteration {
167+
with offset: @escaping (Output) -> Instruction<O>) -> Pager<O, Publishers.Output<Self>>.Iteration {
139168
iterateFirst(stoppingAt: exception) { offset($0!) }
140169
}
141170

@@ -146,7 +175,7 @@ public extension Publisher where Failure == Never {
146175
/// - offet: A valid offset generator.
147176
/// - returns: A valid `Pager.Iteration`.
148177
func iterateFirst<O>(stoppingAt exception: O,
149-
with offset: @escaping (Output) -> O?) -> Pager<O, Publishers.Output<Self>>.Iteration where O: Equatable {
178+
with offset: @escaping (Output) -> Instruction<O>) -> Pager<O, Publishers.Output<Self>>.Iteration where O: Equatable {
150179
iterateFirst(stoppingAt: { $0 == exception }, with: offset)
151180
}
152181

@@ -155,7 +184,7 @@ public extension Publisher where Failure == Never {
155184
/// - warning: The `Publisher` is still not guaranteed to return an output. You should only use this when you're certain it will.
156185
/// - parameter offset: A valid offset generator.
157186
/// - returns: A valid `Pager.Iteration`.
158-
func iterateLast<O>(with offset: @escaping (Output) -> O?) -> Pager<O, Publishers.Last<Self>>.Iteration {
187+
func iterateLast<O>(with offset: @escaping (Output) -> Instruction<O>) -> Pager<O, Publishers.Last<Self>>.Iteration {
159188
iterateLast { offset($0!) }
160189
}
161190

@@ -166,7 +195,7 @@ public extension Publisher where Failure == Never {
166195
/// - offet: A valid offset generator.
167196
/// - returns: A valid `Pager.Iteration`.
168197
func iterateLast<O>(stoppingAt exception: @escaping (O) -> Bool,
169-
with offset: @escaping (Output) -> O?) -> Pager<O, Publishers.Last<Self>>.Iteration {
198+
with offset: @escaping (Output) -> Instruction<O>) -> Pager<O, Publishers.Last<Self>>.Iteration {
170199
iterateLast(stoppingAt: exception) { offset($0!) }
171200
}
172201

@@ -178,7 +207,7 @@ public extension Publisher where Failure == Never {
178207
/// - offet: A valid offset generator.
179208
/// - returns: A valid `Pager.Iteration`.
180209
func iterateLast<O>(stoppingAt exception: O,
181-
with offset: @escaping (Output) -> O?) -> Pager<O, Publishers.Last<Self>>.Iteration where O: Equatable {
210+
with offset: @escaping (Output) -> Instruction<O>) -> Pager<O, Publishers.Last<Self>>.Iteration where O: Equatable {
182211
iterateLast(stoppingAt: { $0 == exception }, with: offset)
183212
}
184213
}

Sources/ComposableRequest/Publishers/Pager/Pager.swift

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,24 @@ public extension Publishers {
5858
Empty().subscribe(subscriber)
5959
return
6060
}
61-
// The actual stream.
62-
let iteration = generator(offset)
63-
iteration.stream
61+
// Prepare the iterator.
62+
let iterator = generator(offset)
63+
iterator.stream
6464
.collect()
6565
.flatMap { [count, generator] outputs -> AnyPublisher<Output, Failure> in
66-
Publishers.Sequence(sequence: outputs.map { Just($0).setFailureType(to: Failure.self) })
67-
.flatMap(maxPublishers: Subscribers.Demand.max(1)) { $0 }
68-
.append(iteration.offset(outputs).flatMap { Pager(count-1, offset: $0, generator: generator) }?.eraseToAnyPublisher()
69-
?? Empty().eraseToAnyPublisher())
70-
.eraseToAnyPublisher()
66+
// The current publisher.
67+
let current = Publishers.Sequence(sequence: outputs.map(Just.init))
68+
.flatMap(maxPublishers: .max(1)) { $0 }
69+
.setFailureType(to: Failure.self)
70+
// The next instruction.
71+
switch iterator.offset(outputs) {
72+
case .stop:
73+
return current.eraseToAnyPublisher()
74+
case .load(let next):
75+
return current
76+
.append(Pager(count-1, offset: next, generator: generator))
77+
.eraseToAnyPublisher()
78+
}
7179
}
7280
.subscribe(subscriber)
7381
}
@@ -122,7 +130,7 @@ public extension Pager where Offset: ComposableOptionalType {
122130
/// - count: A valid `Int`. Defaults to `.max`.
123131
/// - generator: A valid generator.
124132
init(_ count: Int = .max, generator: @escaping (_ offset: Offset) -> Iteration) {
125-
self.init(count, offset: .optionalTypeNone, generator: generator)
133+
self.init(count, offset: .composableNone, generator: generator)
126134
}
127135
}
128136

@@ -138,7 +146,14 @@ public extension Pager where Offset: Ranked {
138146
generator: @escaping (_ offset: Offset.Offset) -> Pager<Offset.Offset, Stream>.Iteration) {
139147
self.init(count, offset: offset) { offset -> Iteration in
140148
let iteration = generator(offset.offset)
141-
return .init(stream: iteration.stream) { iteration.offset($0).flatMap { .init(offset: $0, rank: offset.rank) }}
149+
return .init(stream: iteration.stream) {
150+
switch iteration.offset($0) {
151+
case .stop:
152+
return .stop
153+
case .load(let next):
154+
return .load(.init(offset: next, rank: offset.rank))
155+
}
156+
}
142157
}
143158
}
144159

0 commit comments

Comments
 (0)