-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathMini.swift
594 lines (424 loc) · 19.4 KB
/
Mini.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
import Dispatch
import Foundation
import NIOConcurrencyHelpers
import RxSwift
import SwiftOnoneSupport
/**
Protocol that has to be conformed by any object that can be dispatcher
by a `Dispatcher` object.
*/
public protocol Action {
/// Equality function between `Action` objects
/// - Returns: If an `Action` is the same as other.
func isEqual(to other: Mini.Action) -> Bool
}
extension Action {
/// String used as tag of the given Action based on his name.
/// - Returns: The name of the action as a String.
public var innerTag: String { get }
}
extension Action {
/// Equality operator between `Action` objects.
/// - Returns: If the `Action`s are equal or not.
public static func == (lhs: Self, rhs: Self) -> Bool
}
extension Action where Self: Equatable {
/// Convenience `isEqual` implementation when the `Action` object
/// implements `Equatable`.
/// - Returns: Whether the `Action` object is the same as other.
public func isEqual(to other: Mini.Action) -> Bool
}
public protocol Chain {
var proceed: Mini.Next { get }
}
public protocol CompletableAction: Mini.Action, Mini.PayloadAction {}
public final class Dispatcher {
public struct DispatchMode {
public enum UI {
case sync
case async
}
}
public var subscriptionCount: Int { get }
public static let defaultPriority: Int
public init()
public func add(middleware: Mini.Middleware)
public func remove(middleware: Mini.Middleware)
public func register(service: Mini.Service)
public func unregister(service: Mini.Service)
public func subscribe(priority: Int, tag: String, completion: @escaping (Mini.Action) -> Void) -> Mini.DispatcherSubscription
public func registerInternal(subscription: Mini.DispatcherSubscription) -> Mini.DispatcherSubscription
public func unregisterInternal(subscription: Mini.DispatcherSubscription)
public func subscribe<T>(completion: @escaping (T) -> Void) -> Mini.DispatcherSubscription where T: Mini.Action
public func subscribe<T>(tag: String, completion: @escaping (T) -> Void) -> Mini.DispatcherSubscription where T: Mini.Action
public func subscribe(tag: String, completion: @escaping (Mini.Action) -> Void) -> Mini.DispatcherSubscription
public func dispatch(_ action: Mini.Action, mode: Mini.Dispatcher.DispatchMode.UI)
}
public final class DispatcherSubscription: Comparable, RxSwift.Disposable {
public let id: Int
public let tag: String
public init(dispatcher: Mini.Dispatcher, id: Int, priority: Int, tag: String, completion: @escaping (Mini.Action) -> Void)
/// Dispose resource.
public func dispose()
public func on(_ action: Mini.Action)
/// Returns a Boolean value indicating whether two values are equal.
///
/// Equality is the inverse of inequality. For any values `a` and `b`,
/// `a == b` implies that `a != b` is `false`.
///
/// - Parameters:
/// - lhs: A value to compare.
/// - rhs: Another value to compare.
public static func == (lhs: Mini.DispatcherSubscription, rhs: Mini.DispatcherSubscription) -> Bool
/// Returns a Boolean value indicating whether the value of the first
/// argument is greater than that of the second argument.
///
/// - Parameters:
/// - lhs: A value to compare.
/// - rhs: Another value to compare.
public static func > (lhs: Mini.DispatcherSubscription, rhs: Mini.DispatcherSubscription) -> Bool
/// Returns a Boolean value indicating whether the value of the first
/// argument is less than that of the second argument.
///
/// This function is the only requirement of the `Comparable` protocol. The
/// remainder of the relational operator functions are implemented by the
/// standard library for any type that conforms to `Comparable`.
///
/// - Parameters:
/// - lhs: A value to compare.
/// - rhs: Another value to compare.
public static func < (lhs: Mini.DispatcherSubscription, rhs: Mini.DispatcherSubscription) -> Bool
/// Returns a Boolean value indicating whether the value of the first
/// argument is greater than or equal to that of the second argument.
///
/// - Parameters:
/// - lhs: A value to compare.
/// - rhs: Another value to compare.
public static func >= (lhs: Mini.DispatcherSubscription, rhs: Mini.DispatcherSubscription) -> Bool
/// Returns a Boolean value indicating whether the value of the first
/// argument is less than or equal to that of the second argument.
///
/// - Parameters:
/// - lhs: A value to compare.
/// - rhs: Another value to compare.
public static func <= (lhs: Mini.DispatcherSubscription, rhs: Mini.DispatcherSubscription) -> Bool
}
public protocol EmptyAction: Mini.Action, Mini.PayloadAction where Self.Payload == Void {
init(promise: Mini.Promise<Void>)
}
extension EmptyAction {
public init(promise _: Mini.Promise<Self.Payload>)
}
public final class ForwardingChain: Mini.Chain {
public var proceed: Mini.Next { get }
public init(next: @escaping Mini.Next)
}
public protocol Group: RxSwift.Disposable {
var disposeBag: RxSwift.CompositeDisposable { get }
}
public protocol KeyedCompletableAction: Mini.Action, Mini.KeyedPayloadAction {}
public protocol KeyedPayloadAction {
associatedtype Payload
associatedtype Key: Hashable
init(promise: [Self.Key: Mini.Promise<Self.Payload>])
}
public protocol Middleware {
var id: UUID { get }
var perform: Mini.MiddlewareChain { get }
}
public typealias MiddlewareChain = (Mini.Action, Mini.Chain) -> Mini.Action
public typealias Next = (Mini.Action) -> Mini.Action
/**
An Ordered Set is a collection where all items in the set follow an ordering,
usually ordered from 'least' to 'most'. The way you value and compare items
can be user-defined.
*/
public class OrderedSet<T> where T: Comparable {
public init(initial: [T] = [])
/// Returns the number of elements in the OrderedSet.
public var count: Int { get }
/// Inserts an item. Performance: O(n)
public func insert(_ item: T) -> Bool
/// Insert an array of items
public func insert(_ items: [T]) -> Bool
/// Removes an item if it exists. Performance: O(n)
public func remove(_ item: T) -> Bool
/// Returns true if and only if the item exists somewhere in the set.
public func exists(_ item: T) -> Bool
/// Returns the index of an item if it exists, or nil otherwise.
public func indexOf(_ item: T) -> Int?
/// Returns the item at the given index.
/// Assertion fails if the index is out of the range of [0, count).
public subscript(_: Int) -> T { get }
/// Returns the 'maximum' or 'largest' value in the set.
public var max: T? { get }
/// Returns the 'minimum' or 'smallest' value in the set.
public var min: T? { get }
/// Returns the k-th largest element in the set, if k is in the range
/// [1, count]. Returns nil otherwise.
public func kLargest(element: Int) -> T?
/// Returns the k-th smallest element in the set, if k is in the range
/// [1, count]. Returns nil otherwise.
public func kSmallest(element: Int) -> T?
/// For each function
public func forEach(_ body: (T) -> Void)
/// Enumerated function
public func enumerated() -> EnumeratedSequence<[T]>
}
public protocol PayloadAction {
associatedtype Payload
init(promise: Mini.Promise<Self.Payload>)
}
@dynamicMemberLookup public final class Promise<T>: Mini.PromiseType {
public typealias Element = T
public class func value(_ value: T) -> Mini.Promise<T>
public class func error(_ error: Error) -> Mini.Promise<T>
public init(error: Error)
public init()
public class func idle(with options: [String: Any] = [:]) -> Mini.Promise<T>
public class func pending(options: [String: Any] = [:]) -> Mini.Promise<T>
public var result: Result<T, Error>? { get }
/// - Note: `fulfill` do not trigger an object reassignment,
/// so no notifications about it can be triggered. It is recommended
/// to call the method `notify` afterwards.
public func fulfill(_ value: T) -> Self
/// - Note: `reject` do not trigger an object reassignment,
/// so no notifications about it can be triggered. It is recommended
/// to call the method `notify` afterwards.
public func reject(_ error: Error) -> Self
/// Resolves the current `Promise` with the optional `Result` parameter.
/// - Returns: `self` or `nil` if no `result` was not provided.
/// - Note: The optional parameter and restun value are helpers in order to
/// make optional chaining in the `Reducer` context.
public func resolve(_ result: Result<T, Error>?) -> Self?
public subscript<T>(dynamicMember member: String) -> T?
}
extension Promise {
/**
- Returns: `true` if the promise has not yet resolved nor pending.
*/
public var isIdle: Bool { get }
/**
- Returns: `true` if the promise has not yet resolved.
*/
public var isPending: Bool { get }
/**
- Returns: `true` if the promise has completed.
*/
public var isCompleted: Bool { get }
/**
- Returns: `true` if the promise has resolved.
*/
public var isResolved: Bool { get }
/**
- Returns: `true` if the promise was fulfilled.
*/
public var isFulfilled: Bool { get }
/**
- Returns: `true` if the promise was rejected.
*/
public var isRejected: Bool { get }
/**
- Returns: The value with which this promise was fulfilled or `nil` if this promise is pending or rejected.
*/
public var value: T? { get }
/**
- Returns: The error with which this promise was rejected or `nil` if this promise is pending or fulfilled.
*/
public var error: Error? { get }
}
extension Promise where T == () {
public convenience init()
public static func empty() -> Mini.Promise<T>
}
extension Promise: Equatable where T == () {
/// Returns a Boolean value indicating whether two values are equal.
///
/// Equality is the inverse of inequality. For any values `a` and `b`,
/// `a == b` implies that `a != b` is `false`.
///
/// - Parameters:
/// - lhs: A value to compare.
/// - rhs: Another value to compare.
public static func == (lhs: Mini.Promise<T>, rhs: Mini.Promise<T>) -> Bool
}
extension Promise where T: Equatable {
public static func == (lhs: Mini.Promise<T>, rhs: Mini.Promise<T>) -> Bool
}
extension Promise {
public func notify<T>(to store: T) where T: Mini.StoreType
}
public protocol PromiseType {
associatedtype Element
var result: Result<Self.Element, Error>? { get }
var isIdle: Bool { get }
var isPending: Bool { get }
var isResolved: Bool { get }
var isFulfilled: Bool { get }
var isRejected: Bool { get }
var value: Self.Element? { get }
var error: Error? { get }
func resolve(_ result: Result<Self.Element, Error>?) -> Self?
func fulfill(_ value: Self.Element) -> Self
func reject(_ error: Error) -> Self
}
public enum Promises {}
extension Promises {
public enum Lifetime {
case once
case forever(ignoringOld: Bool)
}
}
/**
The `Reducer` defines the behavior to be executed when a certain
`Action` object is received.
*/
public class Reducer<A>: RxSwift.Disposable where A: Mini.Action {
/// The `Action` type which the `Reducer` listens to.
public let action: A.Type
/// The `Dispatcher` object that sends the `Action` objects.
public let dispatcher: Mini.Dispatcher
/// The behavior to be executed when the `Dispatcher` sends a certain `Action`
public let reducer: (A) -> Void
/**
Initializes a new `Reducer` object.
- Parameter action: The `Action` type that will be listened to.
- Parameter dispatcher: The `Dispatcher` that sends the `Action`.
- Parameter reducer: The closure that will be executed when the `Dispatcher`
sends the defined `Action` type.
*/
public init(of action: A.Type, on dispatcher: Mini.Dispatcher, reducer: @escaping (A) -> Void)
/// Dispose resource.
public func dispose()
}
public class ReducerGroup: Mini.Group {
public let disposeBag: RxSwift.CompositeDisposable
public init(_ builder: RxSwift.Disposable...)
/// Dispose resource.
public func dispose()
}
public final class RootChain: Mini.Chain {
public var proceed: Mini.Next { get }
public init(map: Mini.SubscriptionMap)
}
public protocol Service {
var id: UUID { get }
var perform: Mini.ServiceChain { get }
}
public typealias ServiceChain = (Mini.Action, Mini.Chain) -> Void
/// Wrapper class to allow pass dictionaries with a memory reference
public class SharedDictionary<Key, Value> where Key: Hashable {
public var innerDictionary: [Key: Value]
public init()
public func getOrPut(_ key: Key, defaultValue: @autoclosure () -> Value) -> Value
public func get(withKey key: Key) -> Value?
public subscript(_: Key, orPut _: @autoclosure () -> Value) -> Value { get }
public subscript(_: Key) -> Value? { get }
}
public protocol StateType {
func isEqual(to other: Mini.StateType) -> Bool
}
extension StateType where Self: Equatable {
public func isEqual(to other: Mini.StateType) -> Bool
}
public class Store<State, StoreController>: RxSwift.ObservableType, Mini.StoreType where State: Mini.StateType, StoreController: RxSwift.Disposable {
/// Type of elements in sequence.
public typealias Element = State
public typealias State = State
public typealias StoreController = StoreController
public typealias ObjectWillChangePublisher = RxSwift.BehaviorSubject<State>
public var objectWillChange: RxSwift.BehaviorSubject<State>
public let dispatcher: Mini.Dispatcher
public var storeController: StoreController
public var state: State
public var initialState: State { get }
public init(_ state: State, dispatcher: Mini.Dispatcher, storeController: StoreController)
public var reducerGroup: Mini.ReducerGroup { get }
public func notify()
public func replayOnce()
public func reset()
/**
Subscribes `observer` to receive events for this sequence.
### Grammar
**Next\* (Error | Completed)?**
* sequences can produce zero or more elements so zero or more `Next` events can be sent to `observer`
* once an `Error` or `Completed` event is sent, the sequence terminates and can't produce any other elements
It is possible that events are sent from different threads, but no two events can be sent concurrently to
`observer`.
### Resource Management
When sequence sends `Complete` or `Error` event all internal resources that compute sequence elements
will be freed.
To cancel production of sequence elements and free resources immediately, call `dispose` on returned
subscription.
- returns: Subscription for `observer` that can be used to cancel production of sequence elements and free resources.
*/
public func subscribe<Observer>(_ observer: Observer) -> RxSwift.Disposable where State == Observer.Element, Observer: RxSwift.ObserverType
}
public protocol StoreType {
associatedtype State: Mini.StateType
associatedtype StoreController: RxSwift.Disposable
var state: Self.State { get set }
var dispatcher: Mini.Dispatcher { get }
var reducerGroup: Mini.ReducerGroup { get }
func replayOnce()
}
extension StoreType {
/**
Property responsible of reduce the `State` given a certain `Action` being triggered.
```
public var reducerGroup: ReducerGroup {
ReducerGroup {[
Reducer(of: SomeAction.self, on: self.dispatcher) { (action: SomeAction)
self.state = myCoolNewState
},
Reducer(of: OtherAction.self, on: self.dispatcher) { (action: OtherAction)
// Needed work
self.state = myAnotherState
}
}
]}
```
- Note : The property has a default implementation which complies with the @_functionBuilder's current limitations, where no empty blocks can be produced in this iteration.
*/
public var reducerGroup: Mini.ReducerGroup { get }
}
public typealias SubscriptionMap = Mini.SharedDictionary<String, Mini.OrderedSet<Mini.DispatcherSubscription>?>
extension Dictionary {
/// Returns the value for the given key. If the key is not found in the map, calls the `defaultValue` function,
/// puts its result into the map under the given key and returns it.
public mutating func getOrPut(_ key: Key, defaultValue: @autoclosure () -> Value) -> Value
public subscript(_: Key, orPut _: @autoclosure () -> Value) -> Value { mutating get }
public subscript(unwrapping _: Key) -> Value! { get }
}
extension Dictionary where Value: Mini.PromiseType {
public subscript(promise _: Key) -> Value { get }
public func hasValue(for key: [Key: Value].Key) -> Bool
public func resolve(with other: [Key: Value]) -> [Key: Value]
public func mergingNew(with other: [Key: Value]) -> [Key: Value]
}
extension Dictionary where Value: Mini.PromiseType, Value.Element: Equatable {
public static func == (lhs: [Key: Value], rhs: [Key: Value]) -> Bool
}
extension DispatchQueue {
public static var isMain: Bool { get }
}
extension ObservableType {
/// Take the first element that matches the filter function.
///
/// - Parameter fn: Filter closure.
/// - Returns: The first element that matches the filter.
public func filterOne(_ condition: @escaping (Self.Element) -> Bool) -> RxSwift.Observable<Self.Element>
}
extension ObservableType where Self.Element: Mini.StoreType, Self.Element: RxSwift.ObservableType, Self.Element.Element == Self.Element.State {
public static func dispatch<A, Type, T>(using dispatcher: Mini.Dispatcher, factory action: @autoclosure @escaping () -> A, taskMap: @escaping (Self.Element.State) -> T?, on store: Self.Element, lifetime: Mini.Promises.Lifetime = .once) -> RxSwift.Observable<Self.Element.State> where A: Mini.Action, T: Mini.Promise<Type>
public static func dispatch<A, K, Type, T>(using dispatcher: Mini.Dispatcher, factory action: @autoclosure @escaping () -> A, key: K, taskMap: @escaping (Self.Element.State) -> [K: T], on store: Self.Element, lifetime: Mini.Promises.Lifetime = .once) -> RxSwift.Observable<Self.Element.State> where A: Mini.Action, K: Hashable, T: Mini.Promise<Type>
}
extension PrimitiveSequenceType where Self: RxSwift.ObservableConvertibleType, Self.Trait == RxSwift.SingleTrait {
public func dispatch<A>(action: A.Type, on dispatcher: Mini.Dispatcher, mode: Mini.Dispatcher.DispatchMode.UI = .async, fillOnError errorPayload: A.Payload? = nil) -> RxSwift.Disposable where A: Mini.CompletableAction, Self.Element == A.Payload
public func dispatch<A>(action: A.Type, key: A.Key, on dispatcher: Mini.Dispatcher, mode: Mini.Dispatcher.DispatchMode.UI = .async, fillOnError errorPayload: A.Payload? = nil) -> RxSwift.Disposable where A: Mini.KeyedCompletableAction, Self.Element == A.Payload
public func action<A>(_ action: A.Type, fillOnError errorPayload: A.Payload? = nil) -> RxSwift.Single<A> where A: Mini.CompletableAction, Self.Element == A.Payload
}
extension PrimitiveSequenceType where Self.Element == Never, Self.Trait == RxSwift.CompletableTrait {
public func dispatch<A>(action: A.Type, on dispatcher: Mini.Dispatcher, mode: Mini.Dispatcher.DispatchMode.UI = .async) -> RxSwift.Disposable where A: Mini.EmptyAction
public func action<A>(_ action: A.Type) -> RxSwift.Single<A> where A: Mini.EmptyAction
}