Skip to content

Commit f937efd

Browse files
committed
add support for UInt64 custom property type
1 parent 843c25e commit f937efd

File tree

6 files changed

+336
-44
lines changed

6 files changed

+336
-44
lines changed

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

Lines changed: 61 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@ extension ProgressManager {
2828
let throughputDirty: Bool
2929
let estimatedTimeRemainingDirty: Bool
3030
let dirtyPropertiesInt: [MetatypeWrapper<Int, Int>]
31+
let dirtyPropertiesUInt64: [MetatypeWrapper<UInt64, UInt64>]
3132
let dirtyPropertiesDouble: [MetatypeWrapper<Double, Double>]
3233
let dirtyPropertiesString: [MetatypeWrapper<String?, [String?]>]
3334
let dirtyPropertiesURL: [MetatypeWrapper<URL?, [URL?]>]
34-
let dirtyPropertiesUInt64: [MetatypeWrapper<UInt64, [UInt64]>]
35+
let dirtyPropertiesUInt64Array: [MetatypeWrapper<UInt64, [UInt64]>]
3536
#if FOUNDATION_FRAMEWORK
3637
let observerState: ObserverState?
3738
let interopType: InteropType?
@@ -61,10 +62,11 @@ extension ProgressManager {
6162
throughput: ProgressManager.Properties.Throughput.defaultValue,
6263
estimatedTimeRemaining: ProgressManager.Properties.EstimatedTimeRemaining.defaultValue,
6364
propertiesInt: [:],
65+
propertiesUInt64: [:],
6466
propertiesDouble: [:],
6567
propertiesString: [:],
6668
propertiesURL: [:],
67-
propertiesUInt64: [:],
69+
propertiesUInt64Array: [:],
6870
observers: [],
6971
interopType: nil,
7072
)
@@ -80,10 +82,11 @@ extension ProgressManager {
8082
throughput: ProgressManager.Properties.Throughput.defaultValue,
8183
estimatedTimeRemaining: ProgressManager.Properties.EstimatedTimeRemaining.defaultValue,
8284
propertiesInt: [:],
85+
propertiesUInt64: [:],
8386
propertiesDouble: [:],
8487
propertiesString: [:],
8588
propertiesURL: [:],
86-
propertiesUInt64: [:]
89+
propertiesUInt64Array: [:]
8790
)
8891
#endif
8992
let result = try closure(&values)
@@ -100,10 +103,11 @@ extension ProgressManager {
100103
throughputDirty: values.throughputDirty,
101104
estimatedTimeRemainingDirty: values.estimatedTimeRemainingDirty,
102105
dirtyPropertiesInt: values.dirtyPropertiesInt,
106+
dirtyPropertiesUInt64: values.dirtyPropertiesUInt64,
103107
dirtyPropertiesDouble: values.dirtyPropertiesDouble,
104108
dirtyPropertiesString: values.dirtyPropertiesString,
105109
dirtyPropertiesURL: values.dirtyPropertiesURL,
106-
dirtyPropertiesUInt64: values.dirtyPropertiesUInt64,
110+
dirtyPropertiesUInt64Array: values.dirtyPropertiesUInt64Array,
107111
observerState: values.observerState,
108112
interopType: state.interopType
109113
)
@@ -118,10 +122,11 @@ extension ProgressManager {
118122
throughputDirty: values.throughputDirty,
119123
estimatedTimeRemainingDirty: values.estimatedTimeRemainingDirty,
120124
dirtyPropertiesInt: values.dirtyPropertiesInt,
125+
dirtyPropertiesUInt64: values.dirtyPropertiesUInt64,
121126
dirtyPropertiesDouble: values.dirtyPropertiesDouble,
122127
dirtyPropertiesString: values.dirtyPropertiesString,
123128
dirtyPropertiesURL: values.dirtyPropertiesURL,
124-
dirtyPropertiesUInt64: values.dirtyPropertiesUInt64
129+
dirtyPropertiesUInt64Array: values.dirtyPropertiesUInt64Array
125130
)
126131
#endif
127132

@@ -180,6 +185,12 @@ extension ProgressManager {
180185
}
181186
}
182187

188+
if dirtyInfo.dirtyPropertiesUInt64.count > 0 {
189+
for property in dirtyInfo.dirtyPropertiesInt {
190+
markSelfDirty(property: property, parents: dirtyInfo.parents)
191+
}
192+
}
193+
183194
if dirtyInfo.dirtyPropertiesDouble.count > 0 {
184195
for property in dirtyInfo.dirtyPropertiesDouble {
185196
markSelfDirty(property: property, parents: dirtyInfo.parents)
@@ -198,8 +209,8 @@ extension ProgressManager {
198209
}
199210
}
200211

201-
if dirtyInfo.dirtyPropertiesUInt64.count > 0 {
202-
for property in dirtyInfo.dirtyPropertiesUInt64 {
212+
if dirtyInfo.dirtyPropertiesUInt64Array.count > 0 {
213+
for property in dirtyInfo.dirtyPropertiesUInt64Array {
203214
markSelfDirty(property: property, parents: dirtyInfo.parents)
204215
}
205216
}
@@ -219,10 +230,11 @@ extension ProgressManager {
219230
internal var throughputDirty = false
220231
internal var estimatedTimeRemainingDirty = false
221232
internal var dirtyPropertiesInt: [MetatypeWrapper<Int, Int>] = []
233+
internal var dirtyPropertiesUInt64: [MetatypeWrapper<UInt64, UInt64>] = []
222234
internal var dirtyPropertiesDouble: [MetatypeWrapper<Double, Double>] = []
223235
internal var dirtyPropertiesString: [MetatypeWrapper<String?, [String?]>] = []
224236
internal var dirtyPropertiesURL: [MetatypeWrapper<URL?, [URL?]>] = []
225-
internal var dirtyPropertiesUInt64: [MetatypeWrapper<UInt64, [UInt64]>] = []
237+
internal var dirtyPropertiesUInt64Array: [MetatypeWrapper<UInt64, [UInt64]>] = []
226238
#if FOUNDATION_FRAMEWORK
227239
internal var observerState: ObserverState?
228240
#endif
@@ -401,6 +413,29 @@ extension ProgressManager {
401413
}
402414
}
403415

416+
/// Gets or sets custom integer properties.
417+
///
418+
/// This subscript provides read-write access to custom progress properties where both the value
419+
/// and summary types are `UInt64`. If the property has not been set, the getter returns the
420+
/// property's default value.
421+
///
422+
/// - Parameter key: A key path to the custom integer property type.
423+
public subscript<P: Property>(dynamicMember key: KeyPath<ProgressManager.Properties, P.Type>) -> UInt64 where P.Value == UInt64, P.Summary == UInt64 {
424+
get {
425+
return state.propertiesUInt64[MetatypeWrapper(P.self)] ?? P.defaultValue
426+
}
427+
428+
set {
429+
guard newValue != state.propertiesUInt64[MetatypeWrapper(P.self)] else {
430+
return
431+
}
432+
433+
state.propertiesUInt64[MetatypeWrapper(P.self)] = newValue
434+
435+
dirtyPropertiesUInt64.append(MetatypeWrapper(P.self))
436+
}
437+
}
438+
404439
/// Gets or sets custom double properties.
405440
///
406441
/// This subscript provides read-write access to custom progress properties where both the value
@@ -479,17 +514,17 @@ extension ProgressManager {
479514
/// - Parameter key: A key path to the custom UInt64 property type.
480515
public subscript<P: Property>(dynamicMember key: KeyPath<ProgressManager.Properties, P.Type>) -> UInt64? where P.Value == UInt64, P.Summary == [UInt64] {
481516
get {
482-
return state.propertiesUInt64[MetatypeWrapper(P.self)] ?? P.self.defaultValue
517+
return state.propertiesUInt64Array[MetatypeWrapper(P.self)] ?? P.self.defaultValue
483518
}
484519

485520
set {
486-
guard newValue != state.propertiesUInt64[MetatypeWrapper(P.self)] else {
521+
guard newValue != state.propertiesUInt64Array[MetatypeWrapper(P.self)] else {
487522
return
488523
}
489524

490-
state.propertiesUInt64[MetatypeWrapper(P.self)] = newValue
525+
state.propertiesUInt64Array[MetatypeWrapper(P.self)] = newValue
491526

492-
dirtyPropertiesUInt64.append(MetatypeWrapper(P.self))
527+
dirtyPropertiesUInt64Array.append(MetatypeWrapper(P.self))
493528
}
494529
}
495530

@@ -529,11 +564,23 @@ extension ProgressManager {
529564
/// where both the value and summary types are `Int`.
530565
/// - Returns: An `Int` summary value for the specified property.
531566
public func summary<P: Property>(of property: P.Type) -> P.Summary where P.Value == Int, P.Summary == Int {
532-
// self[fakeKeypath: MetatypeWrapper(P.self)]
533567
accessObservation(keyPath: ProgressManager.additionalPropertiesKeyPath.withLock { $0 })
534568
return getUpdatedIntSummary(property: MetatypeWrapper(property))
535569
}
536570

571+
/// Returns a summary for a custom unsigned integer property across the progress subtree.
572+
///
573+
/// This method aggregates the values of a custom integer property from this progress manager
574+
/// and all its children, returning a consolidated summary value.
575+
///
576+
/// - Parameter property: The type of the integer property to summarize. Must be a property
577+
/// where both the value and summary types are `UInt64`.
578+
/// - Returns: An `UInt64` summary value for the specified property.
579+
public func summary<P: Property>(of property: P.Type) -> P.Summary where P.Value == UInt64, P.Summary == UInt64 {
580+
accessObservation(keyPath: ProgressManager.additionalPropertiesKeyPath.withLock { $0 })
581+
return getUpdatedUInt64Summary(property: MetatypeWrapper(property))
582+
}
583+
537584
/// Returns a summary for a custom double property across the progress subtree.
538585
///
539586
/// This method aggregates the values of a custom double property from this progress manager
@@ -583,7 +630,7 @@ extension ProgressManager {
583630
/// - Returns: A `[UInt64]` summary value for the specified property.
584631
public func summary<P: Property>(of property: P.Type) -> P.Summary where P.Value == UInt64, P.Summary == [UInt64] {
585632
accessObservation(keyPath: ProgressManager.additionalPropertiesKeyPath.withLock { $0 })
586-
return getUpdatedUInt64Summary(property: MetatypeWrapper(property))
633+
return getUpdatedUInt64ArraySummary(property: MetatypeWrapper(property))
587634
}
588635

589636
/// Returns the total file count across the progress subtree.

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

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,23 @@ extension ProgressManager {
3737
}
3838
}
3939

40+
internal func getUpdatedUInt64Summary(property: MetatypeWrapper<UInt64, UInt64>) -> UInt64 {
41+
// Collect information from state
42+
let updateInfo = state.withLock { state in
43+
state.getUInt64SummaryUpdateInfo(property: property)
44+
}
45+
46+
// Get updated summary for each dirty child
47+
let updatedSummaries = updateInfo.dirtyChildren.map { (index, child) in
48+
State.UInt64SummaryUpdate(index: index, updatedSummary: child.getUpdatedUInt64Summary(property: property))
49+
}
50+
51+
// Consolidate updated values
52+
return state.withLock { state in
53+
state.updateUInt64Summary(updateInfo, updatedSummaries)
54+
}
55+
}
56+
4057
internal func getUpdatedDoubleSummary(property: MetatypeWrapper<Double, Double>) -> Double {
4158
// Collect information from state
4259
let updateInfo = state.withLock { state in
@@ -88,20 +105,20 @@ extension ProgressManager {
88105
}
89106
}
90107

91-
internal func getUpdatedUInt64Summary(property: MetatypeWrapper<UInt64, [UInt64]>) -> [UInt64] {
108+
internal func getUpdatedUInt64ArraySummary(property: MetatypeWrapper<UInt64, [UInt64]>) -> [UInt64] {
92109
// Collect information from state
93110
let updateInfo = state.withLock { state in
94-
state.getUInt64SummaryUpdateInfo(property: property)
111+
state.getUInt64ArraySummaryUpdateInfo(property: property)
95112
}
96113

97114
// Get updated summary for each dirty child
98115
let updatedSummaries = updateInfo.dirtyChildren.map { (index, child) in
99-
State.UInt64SummaryUpdate(index: index, updatedSummary: child.getUpdatedUInt64Summary(property: property))
116+
State.UInt64ArraySummaryUpdate(index: index, updatedSummary: child.getUpdatedUInt64ArraySummary(property: property))
100117
}
101118

102119
// Consolidate updated values
103120
return state.withLock { state in
104-
state.updateUInt64Summary(updateInfo, updatedSummaries)
121+
state.updateUInt64ArraySummary(updateInfo, updatedSummaries)
105122
}
106123
}
107124

@@ -183,6 +200,14 @@ extension ProgressManager {
183200
}
184201
}
185202

203+
internal func markSelfDirty(property: MetatypeWrapper<UInt64, UInt64>, parents: [ParentState]) {
204+
mutateObservation(of: ProgressManager.additionalPropertiesKeyPath.withLock { $0 }) {
205+
for parentState in parents {
206+
parentState.parent.markChildDirty(property: property, at: parentState.positionInParent)
207+
}
208+
}
209+
}
210+
186211
internal func markSelfDirty(property: MetatypeWrapper<Double, Double>, parents: [ParentState]) {
187212
mutateObservation(of: ProgressManager.additionalPropertiesKeyPath.withLock { $0 }) {
188213
for parentState in parents {
@@ -270,6 +295,13 @@ extension ProgressManager {
270295
markSelfDirty(property: property, parents: parents)
271296
}
272297

298+
internal func markChildDirty(property: MetatypeWrapper<UInt64, UInt64>, at position: Int) {
299+
let parents = state.withLock { state in
300+
state.markChildDirty(property: property, at: position)
301+
}
302+
markSelfDirty(property: property, parents: parents)
303+
}
304+
273305
internal func markChildDirty(property: MetatypeWrapper<Double, Double>, at position: Int) {
274306
let parents = state.withLock { state in
275307
state.markChildDirty(property: property, at: position)
@@ -341,7 +373,7 @@ extension ProgressManager {
341373
}
342374

343375
//MARK: Method to preserve values of properties upon deinit
344-
internal func setChildDeclaredAdditionalProperties(at position: Int, totalFileCount: Int, completedFileCount: Int, totalByteCount: UInt64, completedByteCount: UInt64, throughput: [UInt64], estimatedTimeRemaining: Duration, 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]]) {
376+
internal func setChildDeclaredAdditionalProperties(at position: Int, totalFileCount: Int, completedFileCount: Int, totalByteCount: UInt64, completedByteCount: UInt64, throughput: [UInt64], estimatedTimeRemaining: Duration, propertiesInt: [MetatypeWrapper<Int, Int>: Int], propertiesUInt64: [MetatypeWrapper<UInt64, UInt64>: UInt64], propertiesDouble: [MetatypeWrapper<Double, Double>: Double], propertiesString: [MetatypeWrapper<String?, [String?]>: [String?]], propertiesURL: [MetatypeWrapper<URL?, [URL?]>: [URL?]], propertiesUInt64Array: [MetatypeWrapper<UInt64, [UInt64]>: [UInt64]]) {
345377
state.withLock { state in
346378
state.children[position].totalFileCount = PropertyStateInt(value: totalFileCount, isDirty: false)
347379
state.children[position].completedFileCount = PropertyStateInt(value: completedFileCount, isDirty: false)
@@ -354,6 +386,10 @@ extension ProgressManager {
354386
state.children[position].childPropertiesInt[propertyKey] = PropertyStateInt(value: propertyValue, isDirty: false)
355387
}
356388

389+
for (propertyKey, propertyValue) in propertiesUInt64 {
390+
state.children[position].childPropertiesUInt64[propertyKey] = PropertyStateUInt64(value: propertyValue, isDirty: false)
391+
}
392+
357393
for (propertyKey, propertyValue) in propertiesDouble {
358394
state.children[position].childPropertiesDouble[propertyKey] = PropertyStateDouble(value: propertyValue, isDirty: false)
359395
}
@@ -366,8 +402,8 @@ extension ProgressManager {
366402
state.children[position].childPropertiesURL[propertyKey] = PropertyStateURL(value: propertyValue, isDirty: false)
367403
}
368404

369-
for (propertyKey, propertyValue) in propertiesUInt64 {
370-
state.children[position].childPropertiesUInt64[propertyKey] = PropertyStateThroughput(value: propertyValue, isDirty: false)
405+
for (propertyKey, propertyValue) in propertiesUInt64Array {
406+
state.children[position].childPropertiesUInt64Array[propertyKey] = PropertyStateThroughput(value: propertyValue, isDirty: false)
371407
}
372408
}
373409
}

0 commit comments

Comments
 (0)