Skip to content

Commit 8851837

Browse files
author
Alex Usbergo
committed
Rename reduce into mutate
1 parent 34bf59e commit 8851837

18 files changed

+283
-359
lines changed

README.md

+10-12
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,16 @@ enum CounterAction: Action {
4848
case increase
4949
case decrease
5050

51-
func reduce(context: TransactionContext<Store<Counter>, Self>) {
51+
func mutate(context: TransactionContext<Store<Counter>, Self>) {
5252
defer {
5353
// Remember to always call `fulfill` to signal the completion of this operation.
5454
context.fulfill()
5555
}
5656
switch self {
5757
case .increase(let amount):
58-
context.reduceModel { $0.count += 1 }
58+
context.update { $0.count += 1 }
5959
case .decrease(let amount):
60-
context.reduceModel { $0.count -= 1 }
60+
context.update { $0.count -= 1 }
6161
}
6262
}
6363

@@ -71,12 +71,12 @@ Or a struct:
7171
struct IncreaseAction: Action {
7272
let count: Int
7373

74-
func reduce(context: TransactionContext<Store<Counter>, Self>) {
74+
func mutate(context: TransactionContext<Store<Counter>, Self>) {
7575
defer {
7676
// Remember to always call `fulfill` to signal the completion of this operation.
7777
context.fulfill()
7878
}
79-
context.reduceModel { $0.count += 1 }
79+
context.mutate { $0.count += 1 }
8080
}
8181

8282
func cancel(context: TransactionContext<Store<Counter>, Self>) { }
@@ -97,15 +97,15 @@ enum CounterAction: Action {
9797
case increase(amount: Int)
9898
case decrease(amount: Int)
9999

100-
func reduce(context: TransactionContext<Store<Counter>, Self>) {
100+
func mutate(context: TransactionContext<Store<Counter>, Self>) {
101101
defer {
102102
context.fulfill()
103103
}
104104
switch self {
105105
case .increase(let amount):
106-
context.reduceModel { $0.count += amount }
106+
context.update { $0.count += amount }
107107
case .decrease(let amount):
108-
context.reduceModel { $0.count -= amount }
108+
context.update { $0.count -= amount }
109109
}
110110
}
111111

@@ -139,7 +139,7 @@ struct ContentView_Previews : PreviewProvider {
139139

140140
### `class Store<M>: ObservableObject, Identifiable`
141141

142-
This class is the default implementation of the `ReducibleStore` protocol.
142+
This class is the default implementation of the `MutableStore` protocol.
143143
A store wraps a value-type model, synchronizes its mutations, and emits notifications to its
144144
observers any time the model changes.
145145

@@ -174,9 +174,7 @@ e.g.
174174
`Toggle("...", isOn: $store.binding.someProperty)`.
175175
When the binding set a new value an implicit action is being triggered and the property is
176176
updated.
177-
178-
* ` func reduceModel(transaction: AnyTransaction?, closure: (inout ModelType) -> Void)`
179-
Atomically update the model and notifies all of the observers.
177+
180178

181179
### Observation
182180

Sources/Store/action/Action.swift

+66-27
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,18 @@ import OpenCombine
77
import OpenCombineDispatch
88
#endif
99

10-
1110
/// An action represent an operation on the store.
1211
public protocol Action: Identifiable {
1312

14-
associatedtype AssociatedStoreType: ReducibleStore
13+
associatedtype AssociatedStoreType: MutableStore
1514

1615
/// Unique action identifier.
1716
/// An high level description of the action (e.g. `FETCH_USER` or `DELETE_COMMENT`)
1817
var id: String { get }
1918

2019
/// The execution body for this action.
2120
/// - note: Invoke `context.operation.finish` to signal task completion.
22-
func reduce(context: TransactionContext<AssociatedStoreType, Self>)
21+
func mutate(context: TransactionContext<AssociatedStoreType, Self>)
2322

2423
/// Used to implement custom cancellation logic for this action.
2524
/// E.g. Stop network transfer.
@@ -55,81 +54,121 @@ extension Action {
5554
///
5655
/// ```
5756
@propertyWrapper public final class CancellableStorage {
57+
5858
public var wrappedValue: AnyCancellable?
5959

6060
public init(wrappedValue: AnyCancellable? = nil) {
6161
self.wrappedValue = wrappedValue
6262
}
6363
}
6464

65-
/// Reduce the model by using the closure passed as argument.
66-
public struct Reduce<M>: Action {
65+
// MARK: - Mutate
66+
67+
extension Store {
68+
69+
/// Mutate the model with the closure passed as argument.
70+
public func mutate(
71+
id: String = _ID.mutate,
72+
mode: Executor.Mode = .sync,
73+
mutate: @escaping (inout M) -> Void
74+
) {
75+
let action = Mutate(id: id, mutate: mutate)
76+
run(action: action, mode: mode)
77+
}
78+
}
79+
80+
/// Mutate the model by using the closure passed as argument.
81+
public struct Mutate<M>: Action {
82+
6783
public let id: String
68-
public let reduce: (inout M) -> Void
84+
public let mutate: (inout M) -> Void
6985

70-
public init(id: String = _ID.reduce, reduce: @escaping (inout M) -> Void) {
86+
public init(id: String = _ID.mutate, mutate: @escaping (inout M) -> Void) {
7187
self.id = id
72-
self.reduce = reduce
88+
self.mutate = mutate
7389
}
7490

75-
public func reduce(context: TransactionContext<Store<M>, Self>) {
91+
public func mutate(context: TransactionContext<Store<M>, Self>) {
7692
defer {
7793
context.fulfill()
7894
}
79-
context.reduceModel(closure: reduce)
95+
context.update(closure: mutate)
8096
}
8197

8298
public func cancel(context: TransactionContext<Store<M>, Self<M, V>>) { }
8399
}
84100

101+
// MARK: - Assign
102+
103+
extension Store {
104+
105+
/// Mutate the model at the target key path passed as argument.
106+
public func mutate<V>(
107+
keyPath: WritableKeyPath<M, V>,
108+
value: V,
109+
mode: Executor.Mode = .sync
110+
) {
111+
let action = Assign(keyPath, value)
112+
run(action: action, mode: mode)
113+
}
114+
115+
/// Synchronously mutate the model at the target key path passed as argument.
116+
public func mutateSynchronous<V>(keyPath: WritableKeyPath<M, V?>, value: V?) {
117+
let action = Assign(keyPath, value)
118+
run(action: action, mode: .sync)
119+
}
120+
}
121+
85122
/// Assigns the value passed as argument to the model's keyPath.
86123
public struct Assign<M, V>: Action {
124+
87125
public let id: String
88-
public let keyPath: KeyPathArg<M, V>
89-
public let value: V?
90126

91-
public init(id: String = _ID.assign, _ keyPath: KeyPathArg<M, V>, _ value: V) {
92-
self.id = id
127+
private let value: V?
128+
private let keyPath: KeyPathTarget<M, V>
129+
130+
private init(_ keyPath: KeyPathTarget<M, V>, _ value: V) {
131+
self.id = _ID.assign
93132
self.keyPath = keyPath
94133
self.value = value
95134
}
96135

97-
public init(id: String = _ID.assign, _ keyPath: WritableKeyPath<M, V>, _ value: V) {
98-
self.id = "\(id)[\(keyPath.readableFormat ?? "unknown")]"
136+
public init(_ keyPath: WritableKeyPath<M, V>, _ value: V) {
137+
self.id = "\(_ID.assign)[\(keyPath.readableFormat ?? "unknown")]"
99138
self.keyPath = .value(keyPath: keyPath)
100139
self.value = value
101140
}
102141

103-
public init(id: String = _ID.assign,_ keyPath: WritableKeyPath<M, V?>, _ value: V?) {
104-
self.id = "\(id)[\(keyPath.readableFormat ?? "unknown")]"
142+
public init(_ keyPath: WritableKeyPath<M, V?>, _ value: V?) {
143+
self.id = "\(_ID.assign)[\(keyPath.readableFormat ?? "unknown")]"
105144
self.keyPath = .optional(keyPath: keyPath)
106145
self.value = value
107146
}
108147

109-
public func reduce(context: TransactionContext<Store<M>, Self>) {
148+
public func mutate(context: TransactionContext<Store<M>, Self>) {
110149
defer {
111150
context.fulfill()
112151
}
113-
context.reduceModel { model in
152+
context.update { model in
114153
_assignKeyPath(object: &model, keyPath: keyPath, value: value)
115154
}
116155
}
117156

118157
public func cancel(context: TransactionContext<Store<M>, Self<M, V>>) { }
119158
}
120159

121-
// MARK: - Internal
160+
// MARK: - Private
161+
162+
private enum KeyPathTarget<M, V> {
122163

123-
public enum KeyPathArg<M, V> {
124164
/// A non-optional writeable keyPath.
125165
case value(keyPath: WritableKeyPath<M, V>)
166+
126167
/// A optional writeable keyPath.
127168
case optional(keyPath: WritableKeyPath<M, V?>)
128169
}
129170

130-
// MARK: - Private
131-
132-
private func _assignKeyPath<M, V>(object: inout M, keyPath: KeyPathArg<M, V>, value: V?) {
171+
private func _assignKeyPath<M, V>(object: inout M, keyPath: KeyPathTarget<M, V>, value: V?) {
133172
switch keyPath {
134173
case .value(let keyPath):
135174
guard let value = value else { return }
@@ -142,6 +181,6 @@ private func _assignKeyPath<M, V>(object: inout M, keyPath: KeyPathArg<M, V>, va
142181
// MARK: - IDs
143182

144183
public struct _ID {
145-
public static let reduce = "_REDUCE"
146-
public static let assign = "_BINDING_ASSIGN"
184+
public static let mutate = "MUTATE"
185+
public static let assign = "BINDING_ASSIGN"
147186
}

Sources/Store/action/FetchedProperty.swift

-97
This file was deleted.

Sources/Store/action/KeyPath+Introspection.swift

+5-4
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@ public extension KeyPath {
1616
assertionFailure()
1717
return nil
1818
}
19-
19+
2020
let typeDescriptor = metadata.pointee.typeDescriptor
2121
let numberOfFields = Int(typeDescriptor.pointee.numberOfFields)
22-
let offsets = typeDescriptor.pointee.offsetToTheFieldOffsetVector
23-
.buffer(metadata: typePtr, count: numberOfFields)
22+
let offsets = typeDescriptor.pointee.offsetToTheFieldOffsetVector.buffer(
23+
metadata: typePtr,
24+
count: numberOfFields)
2425

2526
guard let fieldIndex = offsets.firstIndex(of: Int32(offset)) else {
2627
return nil
@@ -32,7 +33,7 @@ public extension KeyPath {
3233
}
3334
}
3435

35-
// MARK: - Internal Layout
36+
// MARK: - Memory Layout
3637

3738
private struct StructMetadata {
3839
var _kind: Int

0 commit comments

Comments
 (0)