Skip to content

Commit 1380f2b

Browse files
committed
add propertiesUInt64 as available additional property type
1 parent 6df4e75 commit 1380f2b

File tree

5 files changed

+110
-6
lines changed

5 files changed

+110
-6
lines changed

Sources/FoundationEssentials/ProgressManager/ProgressManager+Properties+Accessors.swift

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ extension ProgressManager {
3939
propertiesDouble: [:],
4040
propertiesString: [:],
4141
propertiesURL: [:],
42+
propertiesUInt64: [:],
4243
observers: [],
4344
interopType: nil,
4445
)
@@ -56,7 +57,8 @@ extension ProgressManager {
5657
propertiesInt: [:],
5758
propertiesDouble: [:],
5859
propertiesString: [:],
59-
propertiesURL: [:]
60+
propertiesURL: [:],
61+
propertiesUInt64: [:]
6062
)
6163
#endif
6264
let result = try closure(&values)
@@ -115,6 +117,12 @@ extension ProgressManager {
115117
markSelfDirty(property: property, parents: values.state.parents)
116118
}
117119
}
120+
121+
if values.dirtyPropertiesUInt64.count > 0 {
122+
for property in values.dirtyPropertiesUInt64 {
123+
markSelfDirty(property: property, parents: values.state.parents)
124+
}
125+
}
118126
#if FOUNDATION_FRAMEWORK
119127
if let observerState = values.observerState {
120128
switch state.interopType {
@@ -152,6 +160,7 @@ extension ProgressManager {
152160
internal var dirtyPropertiesDouble: [MetatypeWrapper<Double, Double>] = []
153161
internal var dirtyPropertiesString: [MetatypeWrapper<String?, [String?]>] = []
154162
internal var dirtyPropertiesURL: [MetatypeWrapper<URL?, [URL?]>] = []
163+
internal var dirtyPropertiesUInt64: [MetatypeWrapper<UInt64, [UInt64]>] = []
155164
#if FOUNDATION_FRAMEWORK
156165
internal var observerState: ObserverState?
157166
#endif
@@ -410,6 +419,22 @@ extension ProgressManager {
410419
}
411420
}
412421

422+
public subscript<P: Property>(dynamicMember key: KeyPath<ProgressManager.Properties, P.Type>) -> UInt64? where P.Value == UInt64, P.Summary == [UInt64] {
423+
get {
424+
return state.propertiesUInt64[MetatypeWrapper(P.self)] ?? P.self.defaultValue
425+
}
426+
427+
set {
428+
guard newValue != state.propertiesUInt64[MetatypeWrapper(P.self)] else {
429+
return
430+
}
431+
432+
state.propertiesUInt64[MetatypeWrapper(P.self)] = newValue
433+
434+
dirtyPropertiesUInt64.append(MetatypeWrapper(P.self))
435+
}
436+
}
437+
413438
#if FOUNDATION_FRAMEWORK
414439
private mutating func interopNotifications() {
415440
switch state.interopType {
@@ -477,6 +502,10 @@ extension ProgressManager {
477502
return getUpdatedURLSummary(property: MetatypeWrapper(property))
478503
}
479504

505+
public func summary<P: Property>(of property: P.Type) -> P.Summary where P.Value == UInt64, P.Summary == [UInt64] {
506+
return getUpdatedUInt64Summary(property: MetatypeWrapper(property))
507+
}
508+
480509
/// Returns the total file count across the progress subtree.
481510
///
482511
/// - Parameter property: The `TotalFileCount` property type.

Sources/FoundationEssentials/ProgressManager/ProgressManager+Properties+Helpers.swift

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,48 @@ extension ProgressManager {
191191
}
192192
}
193193

194+
internal func getUpdatedUInt64Summary(property: MetatypeWrapper<UInt64, [UInt64]>) -> [UInt64] {
195+
return state.withLock { state in
196+
197+
var value: [UInt64] = property.defaultSummary
198+
property.reduce(&value, state.propertiesUInt64[property] ?? property.defaultValue)
199+
200+
guard !state.children.isEmpty else {
201+
return value
202+
}
203+
204+
for (idx, childState) in state.children.enumerated() {
205+
if let childPropertyState = childState.childPropertiesUInt64[property] {
206+
if childPropertyState.isDirty {
207+
// Update dirty path
208+
if let child = childState.child {
209+
let updatedSummary = child.getUpdatedUInt64Summary(property: property)
210+
let newChildPropertyState = PropertyStateThroughput(value: updatedSummary, isDirty: false)
211+
state.children[idx].childPropertiesUInt64[property] = newChildPropertyState
212+
value = property.merge(value, updatedSummary)
213+
}
214+
} else {
215+
if let _ = childState.child {
216+
// Merge non-dirty, updated value
217+
value = property.merge(value, childPropertyState.value)
218+
} else {
219+
value = property.terminate(value, childPropertyState.value)
220+
}
221+
}
222+
} else {
223+
// First fetch of value
224+
if let child = childState.child {
225+
let childSummary = child.getUpdatedUInt64Summary(property: property)
226+
let newChildPropertyState = PropertyStateThroughput(value: childSummary, isDirty: false)
227+
state.children[idx].childPropertiesUInt64[property] = newChildPropertyState
228+
value = property.merge(value, childSummary)
229+
}
230+
}
231+
}
232+
return value
233+
}
234+
}
235+
194236
internal func getUpdatedFileCount(type: CountType) -> Int {
195237
switch type {
196238
case .total:
@@ -443,6 +485,12 @@ extension ProgressManager {
443485
}
444486
}
445487

488+
internal func markSelfDirty(property: MetatypeWrapper<UInt64, [UInt64]>, parents: [ParentState]) {
489+
for parentState in parents {
490+
parentState.parent.markChildDirty(property: property, at: parentState.positionInParent)
491+
}
492+
}
493+
446494
internal func markSelfDirty(property: ProgressManager.Properties.TotalFileCount.Type, parents: [ParentState]) {
447495
for parentState in parents {
448496
parentState.parent.markChildDirty(property: property, at: parentState.positionInParent)
@@ -516,6 +564,14 @@ extension ProgressManager {
516564
}
517565
markSelfDirty(property: property, parents: parents)
518566
}
567+
568+
internal func markChildDirty(property: MetatypeWrapper<UInt64, [UInt64]>, at position: Int) {
569+
let parents = state.withLock { state in
570+
state.children[position].childPropertiesUInt64[property]?.isDirty = true
571+
return state.parents
572+
}
573+
markSelfDirty(property: property, parents: parents)
574+
}
519575

520576
internal func markChildDirty(property: ProgressManager.Properties.TotalFileCount.Type, at position: Int) {
521577
let parents = state.withLock { state in
@@ -574,7 +630,7 @@ extension ProgressManager {
574630
}
575631

576632
//MARK: Method to preserve values of properties upon deinit
577-
internal func setChildDeclaredAdditionalProperties(at position: Int, totalFileCount: Int, completedFileCount: Int, totalByteCount: UInt64, completedByteCount: UInt64, throughput: [UInt64], estimatedTimeRemaining: Duration, fileURL: [URL?], propertiesInt: [MetatypeWrapper<Int, Int>: Int], propertiesDouble: [MetatypeWrapper<Double, Double>: Double], propertiesString: [MetatypeWrapper<String?, [String?]>: [String?]], propertiesURL: [MetatypeWrapper<URL?, [URL?]>: [URL?]]) {
633+
internal func setChildDeclaredAdditionalProperties(at position: Int, totalFileCount: Int, completedFileCount: Int, totalByteCount: UInt64, completedByteCount: UInt64, throughput: [UInt64], estimatedTimeRemaining: Duration, fileURL: [URL?], propertiesInt: [MetatypeWrapper<Int, Int>: Int], propertiesDouble: [MetatypeWrapper<Double, Double>: Double], propertiesString: [MetatypeWrapper<String?, [String?]>: [String?]], propertiesURL: [MetatypeWrapper<URL?, [URL?]>: [URL?]], propertiesUInt64: [MetatypeWrapper<UInt64, [UInt64]>: [UInt64]]) {
578634
state.withLock { state in
579635
state.children[position].totalFileCount = PropertyStateInt(value: totalFileCount, isDirty: false)
580636
state.children[position].completedFileCount = PropertyStateInt(value: completedFileCount, isDirty: false)
@@ -599,6 +655,10 @@ extension ProgressManager {
599655
for (propertyKey, propertyValue) in propertiesURL {
600656
state.children[position].childPropertiesURL[propertyKey] = PropertyStateURL(value: propertyValue, isDirty: false)
601657
}
658+
659+
for (propertyKey, propertyValue) in propertiesUInt64 {
660+
state.children[position].childPropertiesUInt64[propertyKey] = PropertyStateThroughput(value: propertyValue, isDirty: false)
661+
}
602662
}
603663
}
604664
}

Sources/FoundationEssentials/ProgressManager/ProgressManager+State.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ extension ProgressManager {
9494
var childPropertiesDouble: [MetatypeWrapper<Double, Double>: PropertyStateDouble]
9595
var childPropertiesString: [MetatypeWrapper<String?, [String?]>: PropertyStateString]
9696
var childPropertiesURL: [MetatypeWrapper<URL?, [URL?]>: PropertyStateURL]
97+
var childPropertiesUInt64: [MetatypeWrapper<UInt64, [UInt64]>: PropertyStateThroughput]
9798
}
9899

99100
internal struct ParentState {
@@ -128,6 +129,7 @@ extension ProgressManager {
128129
var propertiesDouble: [MetatypeWrapper<Double, Double>: Double]
129130
var propertiesString: [MetatypeWrapper<String?, [String?]>: String?]
130131
var propertiesURL: [MetatypeWrapper<URL?, [URL?]>: URL?]
132+
var propertiesUInt64: [MetatypeWrapper<UInt64, [UInt64]>: UInt64]
131133
#if FOUNDATION_FRAMEWORK
132134
var observers: [@Sendable (ObserverState) -> Void]
133135
var interopType: InteropType?

Sources/FoundationEssentials/ProgressManager/ProgressManager.swift

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ internal import _FoundationCollections
9494
propertiesDouble: [:],
9595
propertiesString: [:],
9696
propertiesURL: [:],
97+
propertiesUInt64: [:],
9798
observers: [],
9899
interopType: .interopObservation(InteropObservation(subprogressBridge: subprogressBridge))
99100
)
@@ -245,7 +246,8 @@ internal import _FoundationCollections
245246
childPropertiesInt: [:],
246247
childPropertiesDouble: [:],
247248
childPropertiesString: [:],
248-
childPropertiesURL: [:])
249+
childPropertiesURL: [:],
250+
childPropertiesUInt64: [:])
249251
state.children.append(childState)
250252
return (state.children.count - 1, state.parents)
251253
}
@@ -303,8 +305,8 @@ internal import _FoundationCollections
303305
}
304306
}
305307

306-
let (propertiesInt, propertiesDouble, propertiesString, propertiesURL, parents) = state.withLock { state in
307-
return (state.propertiesInt, state.propertiesDouble, state.propertiesString, state.propertiesURL, state.parents)
308+
let (propertiesInt, propertiesDouble, propertiesString, propertiesURL, propertiesUInt64, parents) = state.withLock { state in
309+
return (state.propertiesInt, state.propertiesDouble, state.propertiesString, state.propertiesURL, state.propertiesUInt64, state.parents)
308310
}
309311

310312
var finalSummaryInt: [MetatypeWrapper<Int, Int>: Int] = [:]
@@ -331,6 +333,12 @@ internal import _FoundationCollections
331333
finalSummaryURL[property] = updatedSummary
332334
}
333335

336+
var finalSummaryUInt64: [MetatypeWrapper<UInt64, [UInt64]>: [UInt64]] = [:]
337+
for property in propertiesUInt64.keys {
338+
let updatedSummary = self.getUpdatedUInt64Summary(property: property)
339+
finalSummaryUInt64[property] = updatedSummary
340+
}
341+
334342
let totalFileCount = self.getUpdatedFileCount(type: .total)
335343
let completedFileCount = self.getUpdatedFileCount(type: .completed)
336344
let totalByteCount = self.getUpdatedByteCount(type: .total)
@@ -352,7 +360,8 @@ internal import _FoundationCollections
352360
propertiesInt: finalSummaryInt,
353361
propertiesDouble: finalSummaryDouble,
354362
propertiesString: finalSummaryString,
355-
propertiesURL: finalSummaryURL
363+
propertiesURL: finalSummaryURL,
364+
propertiesUInt64: finalSummaryUInt64
356365
)
357366
}
358367
}

Sources/FoundationEssentials/ProgressManager/ProgressReporter.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ import Observation
118118
return manager.summary(of: property)
119119
}
120120

121+
public func summary<P: ProgressManager.Property>(of property: P.Type) -> [UInt64] where P.Value == UInt64, P.Summary == [UInt64] {
122+
return manager.summary(of: property)
123+
}
124+
121125
/// Returns the total file count across the progress subtree.
122126
///
123127
/// - Parameter property: The `TotalFileCount` property type.

0 commit comments

Comments
 (0)