Skip to content

Commit

Permalink
Changes - doWithSource (#503)
Browse files Browse the repository at this point in the history
related #502
  • Loading branch information
muukii authored Jan 20, 2025
1 parent 0ef6efa commit b043860
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 152 deletions.
177 changes: 27 additions & 150 deletions Sources/Verge/Store/Changes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -415,29 +415,14 @@ extension Changes {
try takeIfChanged(compose, .equality())
}

/**
Performs a closure if the selected value changed from the previous one.
*/
@available(*, deprecated, message: "Use another function that returns IfChangedBox")
public func ifChanged<T, Result>(
_ selector: ChangesKeyPath<T>,
_ comparer: some TypedComparator<T>,
_ perform: (T) throws -> Result
) rethrows -> Result? {
guard let value = takeIfChanged({ $0[keyPath: selector] }, comparer) else {
return nil
}
return try perform(value)
}

public func ifChanged<Composed: Equatable>(
_ compose: (Value) -> Composed
) -> IfChangedBox<Composed> {
) -> IfChangedBox<Value, Composed> {
guard let result = takeIfChanged(compose) else {
return .init()
}

return .init(value: consume result)
return .init(value: consume result, source: innerBox)
}

/**
Expand All @@ -451,31 +436,31 @@ extension Changes {
*/
public borrowing func ifChanged<each Element: Equatable>(
_ compose: (borrowing Value) -> (repeat each Element)
) -> IfChangedBox<(repeat each Element)> {
) -> IfChangedBox<Value, (repeat each Element)> {
guard let result = _takeIfChanged_packed(compose) else {
return .init()
}

return .init(value: (repeat each result))
return .init(value: (repeat each result), source: innerBox)
}

public borrowing func ifChanged<each Element>(
_ compose: (borrowing Value) -> (repeat each Element),
comparator: some TypedComparator<(repeat each Element)>
) -> IfChangedBox<(repeat each Element)> {
) -> IfChangedBox<Value, (repeat each Element)> {
guard let result = _takeIfChanged_packed_nonEquatable(compose, comparator: comparator) else {
return .init()
}

return .init(value: (repeat each result))
return .init(value: (repeat each result), source: innerBox)
}

/**
singular variant
*/
public func ifChanged<T: Equatable>(
_ keyPath: KeyPath<Value, T>
) -> IfChangedBox<T> {
) -> IfChangedBox<Value, T> {
ifChanged({ $0[keyPath: keyPath] })
}

Expand All @@ -484,127 +469,10 @@ extension Changes {
*/
public func ifChanged<each T: Equatable>(
_ keyPaths: repeat KeyPath<Value, each T>
) -> IfChangedBox<(repeat each T)> {
) -> IfChangedBox<Value, (repeat each T)> {
ifChanged({ (repeat $0[keyPath: each keyPaths]) })
}


/**
Performs a closure if the selected value changed from the previous one.
*/
@available(*, deprecated, message: "Use another function that returns IfChangedBox")
public func ifChanged<Composed: Equatable, Result>(
_ compose: (Value) -> Composed,
_ perform: (Composed) throws -> Result
) rethrows -> Result? {
try ifChanged(compose, .equality(), perform)
}

/**
Performs a closure if the selected value changed from the previous one.
*/
@inline(__always)
@available(*, deprecated, message: "Use another function that returns IfChangedBox")
public func ifChanged<T: Equatable, Result>(
_ keyPath: ChangesKeyPath<T>,
_ perform: (T) throws -> Result
) rethrows -> Result? {
try ifChanged(keyPath, .equality(), perform)
}

/**
Performs a closure if the selected value changed from the previous one.
Selected multiple value would be packed as tuple.
*/
@inline(__always)
@available(*, deprecated, message: "Use another function that returns IfChangedBox")
public func ifChanged<T0: Equatable, T1: Equatable, Result>(
_ keyPath0: ChangesKeyPath<T0>,
_ keyPath1: ChangesKeyPath<T1>,
_ perform: ((T0, T1)) throws -> Result
) rethrows -> Result? {
try ifChanged({ ($0[keyPath: keyPath0], $0[keyPath: keyPath1]) as (T0, T1) }).do(perform)
}

/**
Performs a closure if the selected value changed from the previous one.
Selected multiple value would be packed as tuple.
*/
@inline(__always)
@available(*, deprecated, message: "Use another function that returns IfChangedBox")
public func ifChanged<T0: Equatable, T1: Equatable, T2: Equatable, Result>(
_ keyPath0: ChangesKeyPath<T0>,
_ keyPath1: ChangesKeyPath<T1>,
_ keyPath2: ChangesKeyPath<T2>,
_ perform: ((T0, T1, T2)) throws -> Result
) rethrows -> Result? {
try ifChanged(
{ ($0[keyPath: keyPath0], $0[keyPath: keyPath1], $0[keyPath: keyPath2]) as (T0, T1, T2) }
)
.do(perform)
}

/**
Performs a closure if the selected value changed from the previous one.
Selected multiple value would be packed as tuple.
*/
@inline(__always)
@available(*, deprecated, message: "Use another function that returns IfChangedBox")
public func ifChanged<T0: Equatable, T1: Equatable, T2: Equatable, T3: Equatable, Result>(
_ keyPath0: ChangesKeyPath<T0>,
_ keyPath1: ChangesKeyPath<T1>,
_ keyPath2: ChangesKeyPath<T2>,
_ keyPath3: ChangesKeyPath<T3>,
_ perform: ((T0, T1, T2, T3)) throws -> Result
) rethrows -> Result? {
try ifChanged(
{
(
$0[keyPath: keyPath0],
$0[keyPath: keyPath1],
$0[keyPath: keyPath2],
$0[keyPath: keyPath3]
) as (T0, T1, T2, T3)
}
)
.do(perform)
}

/**
Performs a closure if the selected value changed from the previous one.
Selected multiple value would be packed as tuple.
*/
@inline(__always)
@available(*, deprecated, message: "Use another function that returns IfChangedBox")
public func ifChanged<
T0: Equatable,
T1: Equatable,
T2: Equatable,
T3: Equatable,
T4: Equatable,
Result
>(
_ keyPath0: ChangesKeyPath<T0>,
_ keyPath1: ChangesKeyPath<T1>,
_ keyPath2: ChangesKeyPath<T2>,
_ keyPath3: ChangesKeyPath<T3>,
_ keyPath4: ChangesKeyPath<T4>,
_ perform: ((T0, T1, T2, T3, T4)) throws -> Result
) rethrows -> Result? {
try ifChanged(
{
(
$0[keyPath: keyPath0],
$0[keyPath: keyPath1],
$0[keyPath: keyPath2],
$0[keyPath: keyPath3],
$0[keyPath: keyPath4]
) as (T0, T1, T2, T3, T4)

}
)
.do(perform)
}

}

// MARK: - Has changes
Expand Down Expand Up @@ -689,27 +557,27 @@ extension Changes where Value: Equatable {
previousPrimitive != primitive
}

@available(*, deprecated, message: "Use another function that returns IfChangedBox")
public func ifChanged(_ perform: (Value) throws -> Void) rethrows {
try ifChanged(\.self, perform)
}

public func ifChanged() -> IfChangedBox<Value> {
public func ifChanged() -> IfChangedBox<Value, Value> {
ifChanged({ $0 })
}

}

public struct IfChangedBox<T>: ~Copyable {
public struct IfChangedBox<Source, T>: ~Copyable {

public let value: T?

@usableFromInline
let source: ReadonlyBox<Source>?

init(value: consuming T) {
init(value: consuming T, source: ReadonlyBox<Source>) {
self.value = consume value
self.source = source
}

init() {
self.value = nil
self.value = nil
self.source = nil
}

@discardableResult
Expand All @@ -720,5 +588,14 @@ public struct IfChangedBox<T>: ~Copyable {
}
return nil
}

@discardableResult
@inlinable
public consuming func doWithSource<Return>(_ perform: (consuming ReadonlyBox<Source>) throws -> Return) rethrows -> Return? {
if let source {
return try perform(source)
}
return nil
}
}

2 changes: 1 addition & 1 deletion Tests/VergeTests/ChangesTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ final class ChangesTests: XCTestCase {

measure {
for _ in 0..<1000 {
changes.ifChanged(\.name) { _ in
changes.ifChanged(\.name).do { _ in

}
}
Expand Down
2 changes: 1 addition & 1 deletion Tests/VergeTests/StateTypeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ final class StateTypeTests: XCTestCase {
current: Changes<StateTypeTests.State>
) {

current.ifChanged(\.count) { _ in
current.ifChanged(\.count).do { _ in
modifying.count2 += 1
}

Expand Down

0 comments on commit b043860

Please sign in to comment.