Skip to content

Commit

Permalink
[Accumulation] doWithSource (#502)
Browse files Browse the repository at this point in the history
  • Loading branch information
muukii authored Jan 20, 2025
1 parent 15d3ce9 commit 0ef6efa
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 37 deletions.
1 change: 0 additions & 1 deletion Sources/Verge/Library/ReadonlyBox.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

// FIXME: should be noncopyable but it's not supported yet.
public final class ReadonlyBox<Value> {

public let value: Value
Expand Down
78 changes: 42 additions & 36 deletions Sources/Verge/Store/StoreDriverType+Accumulator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ extension StoreDriverType {

// sets the previous value
if let previous = previousBox.wrappedValue {
group = group.receive(other: previous)
group = group.receive(previous: previous)
}

// runs sink
Expand Down Expand Up @@ -74,7 +74,7 @@ extension StoreDriverType {

// sets the previous value
if let previous = previousBox.value.wrappedValue {
group = group.receive(other: previous)
group = group.receive(previous: previous)
}

// runs sink
Expand All @@ -91,8 +91,8 @@ extension StoreDriverType {

public protocol AccumulationSink<Source> {
associatedtype Source
consuming func receive(source: borrowing ReadonlyBox<Source>) -> Self
consuming func receive(other: consuming Self) -> Self
consuming func receive(source: ReadonlyBox<Source>) -> Self
consuming func receive(previous: consuming Self) -> Self
consuming func consume() -> Self
}

Expand All @@ -108,12 +108,12 @@ public struct AccumulationBuilder<Source>: ~Copyable {
self.previousLoader = previousLoader
}

public func ifChanged<U: Equatable>(_ selector: @escaping (borrowing Source) -> U) -> AccumulationSinkIfChanged<Source, U> {
public func ifChanged<Value: Equatable>(_ selector: @escaping (borrowing Source) -> Value) -> AccumulationSinkIfChanged<Source, Value> {
.init(
selector: selector
)
}

}

public struct AccumulationSinkIfChanged<Source, Target: Equatable>: AccumulationSink {
Expand All @@ -122,19 +122,21 @@ public struct AccumulationSinkIfChanged<Source, Target: Equatable>: Accumulation

private var latestValue: Target?
private var previousValue: Target?
private var source: ReadonlyBox<Source>?

private var counter: Int = 0
private var countToEmit: Int = 0
private var counter: UInt64 = 0
private var countToEmit: UInt64 = 0

private var handler: ((consuming Target) -> Void)?
private var handlerWithSelectedValue: ((consuming Target) -> Void)?
private var handlerWithSource: ((Source) -> Void)?

init(
selector: @escaping (borrowing Source) -> Target
) {
self.selector = selector
}

public consuming func dropFirst(_ k: Int = 1) -> Self {
public consuming func dropFirst(_ k: UInt64 = 1) -> Self {
countToEmit = k
return self
}
Expand All @@ -143,39 +145,43 @@ public struct AccumulationSinkIfChanged<Source, Target: Equatable>: Accumulation
the closure will be released after consumed.
*/
public consuming func `do`(@_inheritActorContext @_implicitSelfCapture _ perform: @escaping (consuming Target) -> Void) -> Self {
self.handler = perform
self.handlerWithSelectedValue = perform
return self
}

public consuming func `doWithSource`(@_inheritActorContext @_implicitSelfCapture _ perform: @escaping (Source) -> Void) -> Self {
self.handlerWithSource = perform
return self
}

public consuming func receive(source: borrowing ReadonlyBox<Source>) -> Self {
public consuming func receive(source: ReadonlyBox<Source>) -> Self {

self.latestValue = selector(source.value)
self.source = source

return self
}

public consuming func receive(other: consuming AccumulationSinkIfChanged<Source, Target>) -> Self {
public consuming func receive(previous: consuming Self) -> Self {

self.previousValue = other.latestValue
self.counter = other.counter
self.previousValue = previous.latestValue
self.counter = previous.counter

return self
}

public consuming func consume() -> Self {

guard let handler = handler else {
return self
}

if latestValue != previousValue {
if counter >= countToEmit {
handler(latestValue!)
if counter >= countToEmit {
handlerWithSelectedValue?(latestValue!)
handlerWithSource?(source!.value)
}
counter += 1
counter &+= 1
}

self.handler = nil
self.handlerWithSource = nil
self.handlerWithSelectedValue = nil

return self

Expand Down Expand Up @@ -213,8 +219,8 @@ public struct _AccumulationSinkGroup<Source, Component>: AccumulationSink {
return self
}

public consuming func receive(other: _AccumulationSinkGroup<Source, Component>) -> Self {
component = _receiveOther(other.component, component)
public consuming func receive(previous: Self) -> Self {
component = _receiveOther(previous.component, component)
return self
}

Expand Down Expand Up @@ -247,11 +253,11 @@ public struct _AccumulationSinkCondition<Source, TrueComponent: AccumulationSink
return self
}

public consuming func receive(other: _AccumulationSinkCondition<Source, TrueComponent, FalseComponent>) -> Self {
if let trueComponent = trueComponent, let otherTrueComponent = other.trueComponent {
self.trueComponent = trueComponent.receive(other: otherTrueComponent)
} else if let falseComponent = falseComponent, let otherFalseComponent = other.falseComponent {
self.falseComponent = falseComponent.receive(other: otherFalseComponent)
public consuming func receive(previous: Self) -> Self {
if let trueComponent = trueComponent, let previousTrueComponent = previous.trueComponent {
self.trueComponent = trueComponent.receive(previous: previousTrueComponent)
} else if let falseComponent = falseComponent, let previousFalseComponent = previous.falseComponent {
self.falseComponent = falseComponent.receive(previous: previousFalseComponent)
}
return self
}
Expand Down Expand Up @@ -284,9 +290,9 @@ struct _AccumulationSinkOptional<Source, Component: AccumulationSink>: Accumulat
return self
}

consuming func receive(other: _AccumulationSinkOptional<Source, Component>) -> Self {
if let component = component, let otherComponent = other.component {
self.component = component.receive(other: otherComponent)
consuming func receive(previous: Self) -> Self {
if let component = component, let previousComponent = previous.component {
self.component = component.receive(previous: previousComponent)
}
return self
}
Expand Down Expand Up @@ -349,11 +355,11 @@ public struct AccumulationSinkComponentBuilder<Source> {
},
receiveOther: { other, current in
// Waiting https://www.swift.org/blog/pack-iteration/
func iterate<T: AccumulationSink>(other: consuming T, current: consuming T) -> T {
return current.receive(other: other)
func iterate<T: AccumulationSink>(previous: consuming T, current: consuming T) -> T {
return current.receive(previous: previous)
}

let modified = (repeat iterate(other: each other, current: each current))
let modified = (repeat iterate(previous: each other, current: each current))

return modified
},
Expand Down

0 comments on commit 0ef6efa

Please sign in to comment.