Skip to content

Commit 9b2cf7a

Browse files
committed
refactor ProgressFraction
1 parent abfae50 commit 9b2cf7a

File tree

1 file changed

+18
-10
lines changed

1 file changed

+18
-10
lines changed

Sources/FoundationEssentials/ProgressManager/ProgressFraction.swift

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ internal import _ForSwiftFoundation
1616
internal struct ProgressFraction : Sendable, Equatable, CustomDebugStringConvertible {
1717
var completed : Int
1818
var total : Int?
19+
/// Indicates whether mathematical operations on this fraction have exceeded integer limits,
20+
/// causing the fraction to fall back to floating-point representation for accuracy.
1921
private(set) var overflowed : Bool
2022

2123
init() {
@@ -69,7 +71,13 @@ internal struct ProgressFraction : Sendable, Equatable, CustomDebugStringConvert
6971
}
7072
}
7173

72-
static private func _math(lhs: ProgressFraction, rhs: ProgressFraction, whichOperator: (_ lhs : Double, _ rhs : Double) -> Double, whichOverflow : (_ lhs: Int, _ rhs: Int) -> (Int, overflow: Bool)) -> ProgressFraction {
74+
/// A closure that performs floating-point arithmetic operations
75+
private typealias FloatingPointOperation = (_ lhs: Double, _ rhs: Double) -> Double
76+
77+
/// A closure that performs integer arithmetic operations with overflow detection
78+
private typealias OverflowReportingOperation = (_ lhs: Int, _ rhs: Int) -> (Int, overflow: Bool)
79+
80+
static private func _math(lhs: ProgressFraction, rhs: ProgressFraction, operation: FloatingPointOperation, overflowOperation: OverflowReportingOperation) -> ProgressFraction {
7381
// Mathematically, it is nonsense to add or subtract something with a denominator of 0. However, for the purposes of implementing Progress' fractions, we just assume that a zero-denominator fraction is "weightless" and return the other value. We still need to check for the case where they are both nonsense though.
7482
precondition(!(lhs.total == 0 && rhs.total == 0), "Attempt to add or subtract invalid fraction")
7583
guard let lhsTotal = lhs.total, lhsTotal != 0 else {
@@ -81,14 +89,14 @@ internal struct ProgressFraction : Sendable, Equatable, CustomDebugStringConvert
8189

8290
guard !lhs.overflowed && !rhs.overflowed else {
8391
// If either has overflowed already, we preserve that
84-
return ProgressFraction(double: whichOperator(lhs.fractionCompleted, rhs.fractionCompleted), overflow: true)
92+
return ProgressFraction(double: operation(lhs.fractionCompleted, rhs.fractionCompleted), overflow: true)
8593
}
8694

8795
//TODO: rdar://148758226 Overflow check
8896
if let lcm = _leastCommonMultiple(lhsTotal, rhsTotal) {
89-
let result = whichOverflow(lhs.completed * (lcm / lhsTotal), rhs.completed * (lcm / rhsTotal))
97+
let result = overflowOperation(lhs.completed * (lcm / lhsTotal), rhs.completed * (lcm / rhsTotal))
9098
if result.overflow {
91-
return ProgressFraction(double: whichOperator(lhs.fractionCompleted, rhs.fractionCompleted), overflow: true)
99+
return ProgressFraction(double: operation(lhs.fractionCompleted, rhs.fractionCompleted), overflow: true)
92100
} else {
93101
return ProgressFraction(completed: result.0, total: lcm)
94102
}
@@ -102,30 +110,30 @@ internal struct ProgressFraction : Sendable, Equatable, CustomDebugStringConvert
102110
let lhsSimplifiedTotal = lhsSimplified.total,
103111
let rhsSimplifiedTotal = rhsSimplified.total else {
104112
// Simplification failed, fall back to double math
105-
return ProgressFraction(double: whichOperator(lhs.fractionCompleted, rhs.fractionCompleted), overflow: true)
113+
return ProgressFraction(double: operation(lhs.fractionCompleted, rhs.fractionCompleted), overflow: true)
106114
}
107115

108116
if let lcm = _leastCommonMultiple(lhsSimplifiedTotal, rhsSimplifiedTotal) {
109-
let result = whichOverflow(lhsSimplified.completed * (lcm / lhsSimplifiedTotal), rhsSimplified.completed * (lcm / rhsSimplifiedTotal))
117+
let result = overflowOperation(lhsSimplified.completed * (lcm / lhsSimplifiedTotal), rhsSimplified.completed * (lcm / rhsSimplifiedTotal))
110118
if result.overflow {
111119
// Use original lhs/rhs here
112-
return ProgressFraction(double: whichOperator(lhs.fractionCompleted, rhs.fractionCompleted), overflow: true)
120+
return ProgressFraction(double: operation(lhs.fractionCompleted, rhs.fractionCompleted), overflow: true)
113121
} else {
114122
return ProgressFraction(completed: result.0, total: lcm)
115123
}
116124
} else {
117125
// Still overflow
118-
return ProgressFraction(double: whichOperator(lhs.fractionCompleted, rhs.fractionCompleted), overflow: true)
126+
return ProgressFraction(double: operation(lhs.fractionCompleted, rhs.fractionCompleted), overflow: true)
119127
}
120128
}
121129
}
122130

123131
static internal func +(lhs: ProgressFraction, rhs: ProgressFraction) -> ProgressFraction {
124-
return _math(lhs: lhs, rhs: rhs, whichOperator: +, whichOverflow: { $0.addingReportingOverflow($1) })
132+
return _math(lhs: lhs, rhs: rhs, operation: +, overflowOperation: { $0.addingReportingOverflow($1) })
125133
}
126134

127135
static internal func -(lhs: ProgressFraction, rhs: ProgressFraction) -> ProgressFraction {
128-
return _math(lhs: lhs, rhs: rhs, whichOperator: -, whichOverflow: { $0.subtractingReportingOverflow($1) })
136+
return _math(lhs: lhs, rhs: rhs, operation: -, overflowOperation: { $0.subtractingReportingOverflow($1) })
129137
}
130138

131139
static internal func *(lhs: ProgressFraction, rhs: ProgressFraction) -> ProgressFraction? {

0 commit comments

Comments
 (0)