Skip to content

Commit 98bacd8

Browse files
committed
Avoid String(format:)
This is part of an experiment to try using SwiftProtobuf in constrained environments where Foundation is unavailable.
1 parent 2cfe25d commit 98bacd8

File tree

2 files changed

+52
-12
lines changed

2 files changed

+52
-12
lines changed

Sources/SwiftProtobuf/Google_Protobuf_Duration+Extensions.swift

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,20 +94,30 @@ private func parseDuration(text: String) throws -> (Int64, Int32) {
9494
throw JSONDecodingError.malformedDuration
9595
}
9696

97+
private func formatZeroPaddedInt(_ value: Int32, digits: Int) -> String {
98+
let s = String(value)
99+
if s.count >= digits {
100+
return s
101+
} else {
102+
let pad = String(repeating: "0", count: digits - s.count)
103+
return pad + s
104+
}
105+
}
106+
97107
private func formatDuration(seconds: Int64, nanos: Int32) -> String? {
98108
let (seconds, nanos) = normalizeForDuration(seconds: seconds, nanos: nanos)
99109
guard seconds >= minDurationSeconds && seconds <= maxDurationSeconds else {
100110
return nil
101111
}
102112

103113
if nanos == 0 {
104-
return String(format: "%llds", seconds)
114+
return String(seconds) + "s"
105115
} else if nanos % 1000000 == 0 {
106-
return String(format: "%lld.%03ds", seconds, abs(nanos) / 1000000)
116+
return "\(seconds).\(formatZeroPaddedInt(abs(nanos) / 1000000, digits: 3))s"
107117
} else if nanos % 1000 == 0 {
108-
return String(format: "%lld.%06ds", seconds, abs(nanos) / 1000)
118+
return "\(seconds).\(formatZeroPaddedInt(abs(nanos) / 1000, digits: 6))s"
109119
} else {
110-
return String(format: "%lld.%09ds", seconds, abs(nanos))
120+
return "\(seconds).\(formatZeroPaddedInt(abs(nanos), digits: 9))s"
111121
}
112122
}
113123

Sources/SwiftProtobuf/Google_Protobuf_Timestamp+Extensions.swift

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,37 @@ private func parseTimestamp(s: String) throws -> (Int64, Int32) {
182182
return (seconds, nanos)
183183
}
184184

185+
private func formatZeroPaddedInt(_ value: Int32, digits: Int) -> String {
186+
let s = String(value)
187+
if s.count >= digits {
188+
return s
189+
} else {
190+
let pad = String(repeating: "0", count: digits - s.count)
191+
return pad + s
192+
}
193+
}
194+
195+
private func twoDigit(_ value: Int32) -> String {
196+
return formatZeroPaddedInt(value, digits: 2)
197+
}
198+
199+
private func threeDigit(_ value: Int32) -> String {
200+
return formatZeroPaddedInt(value, digits: 3)
201+
}
202+
203+
private func fourDigit(_ value: Int32) -> String {
204+
return formatZeroPaddedInt(value, digits: 4)
205+
}
206+
207+
private func sixDigit(_ value: Int32) -> String {
208+
return formatZeroPaddedInt(value, digits: 6)
209+
}
210+
211+
private func nineDigit(_ value: Int32) -> String {
212+
return formatZeroPaddedInt(value, digits: 9)
213+
}
214+
215+
185216
private func formatTimestamp(seconds: Int64, nanos: Int32) -> String? {
186217
let (seconds, nanos) = normalizeForTimestamp(seconds: seconds, nanos: nanos)
187218
guard seconds >= minTimestampSeconds && seconds <= maxTimestampSeconds else {
@@ -191,18 +222,17 @@ private func formatTimestamp(seconds: Int64, nanos: Int32) -> String? {
191222
let (hh, mm, ss) = timeOfDayFromSecondsSince1970(seconds: seconds)
192223
let (YY, MM, DD) = gregorianDateFromSecondsSince1970(seconds: seconds)
193224

225+
let dateString = "\(fourDigit(YY))-\(twoDigit(MM))-\(twoDigit(DD))"
226+
let timeString = "\(twoDigit(hh)):\(twoDigit(mm)):\(twoDigit(ss))"
227+
194228
if nanos == 0 {
195-
return String(format: "%04d-%02d-%02dT%02d:%02d:%02dZ",
196-
YY, MM, DD, hh, mm, ss)
229+
return "\(dateString)T\(timeString)Z"
197230
} else if nanos % 1000000 == 0 {
198-
return String(format: "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ",
199-
YY, MM, DD, hh, mm, ss, nanos / 1000000)
231+
return "\(dateString)T\(timeString).\(threeDigit(nanos / 1000000))Z"
200232
} else if nanos % 1000 == 0 {
201-
return String(format: "%04d-%02d-%02dT%02d:%02d:%02d.%06dZ",
202-
YY, MM, DD, hh, mm, ss, nanos / 1000)
233+
return "\(dateString)T\(timeString).\(sixDigit(nanos / 1000))Z"
203234
} else {
204-
return String(format: "%04d-%02d-%02dT%02d:%02d:%02d.%09dZ",
205-
YY, MM, DD, hh, mm, ss, nanos)
235+
return "\(dateString)T\(timeString).\(nineDigit(nanos))Z"
206236
}
207237
}
208238

0 commit comments

Comments
 (0)