Skip to content

Commit c310739

Browse files
committed
Use typed throws everywhere to prevent allocation in the unhappy path.
1 parent 0ffe913 commit c310739

File tree

1 file changed

+27
-18
lines changed

1 file changed

+27
-18
lines changed

Sources/FoundationEssentials/Data/Data+Base64.swift

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -442,46 +442,55 @@ extension Base64 {
442442
static var unexpectedEnd: Self { .init(.unexpectedEnd) }
443443
}
444444

445-
static func decode(string encoded: String, options: Data.Base64DecodingOptions = []) throws -> Data {
446-
let decoded = try encoded.utf8.withContiguousStorageIfAvailable { characterPointer -> Data in
447-
// `withContiguousStorageIfAvailable` sadly does not support typed throws
448-
try Self._decodeToData(from: characterPointer, options: options)
445+
static func decode(string encoded: String, options: Data.Base64DecodingOptions = []) throws(DecodingError) -> Data {
446+
let result = encoded.utf8.withContiguousStorageIfAvailable { bufferPointer in
447+
// `withContiguousStorageIfAvailable` sadly does not support typed throws, so we need
448+
// to use Result to get the error out without allocation for the error.
449+
Result(catching: { () throws(DecodingError) -> Data in
450+
try Self._decodeToData(from: bufferPointer, options: options)
451+
})
449452
}
450453

451-
if decoded != nil {
452-
return decoded!
454+
if let result {
455+
return try result.get()
453456
}
454457

455458
var encoded = encoded
456459
encoded.makeContiguousUTF8()
457460
return try Self.decode(string: encoded, options: options)
458461
}
459462

460-
static func decode(data encoded: Data, options: Data.Base64DecodingOptions = []) throws -> Data {
461-
let decoded = try encoded.withContiguousStorageIfAvailable { bufferPointer -> Data in
462-
// `withContiguousStorageIfAvailable` sadly does not support typed throws
463-
try Self._decodeToData(from: bufferPointer, options: options)
463+
static func decode(data encoded: Data, options: Data.Base64DecodingOptions = []) throws(DecodingError) -> Data? {
464+
let result = encoded.withContiguousStorageIfAvailable { bufferPointer in
465+
// `withContiguousStorageIfAvailable` sadly does not support typed throws, so we need
466+
// to use Result to get the error out without allocation for the error.
467+
Result(catching: { () throws(DecodingError) -> Data in
468+
try Self._decodeToData(from: bufferPointer, options: options)
469+
})
464470
}
465471

466-
if decoded != nil {
467-
return decoded!
472+
if let result {
473+
return try result.get()
468474
}
469475

470476
return try Self.decode(bytes: Array(encoded), options: options)
471477
}
472478

473-
static func decode<Buffer: Collection>(bytes: Buffer, options: Data.Base64DecodingOptions = []) throws -> Data where Buffer.Element == UInt8 {
479+
static func decode<Buffer: Collection>(bytes: Buffer, options: Data.Base64DecodingOptions = []) throws(DecodingError) -> Data where Buffer.Element == UInt8 {
474480
guard bytes.count > 0 else {
475481
return Data()
476482
}
477483

478-
let decoded = try bytes.withContiguousStorageIfAvailable { bufferPointer -> Data in
479-
// `withContiguousStorageIfAvailable` sadly does not support typed throws
480-
try Self._decodeToData(from: bufferPointer, options: options)
484+
let result = bytes.withContiguousStorageIfAvailable { bufferPointer in
485+
// `withContiguousStorageIfAvailable` sadly does not support typed throws, so we need
486+
// to use Result to get the error out without allocation for the error.
487+
Result(catching: { () throws(DecodingError) -> Data in
488+
try Self._decodeToData(from: bufferPointer, options: options)
489+
})
481490
}
482491

483-
if decoded != nil {
484-
return decoded!
492+
if let result {
493+
return try result.get()
485494
}
486495

487496
return try self.decode(bytes: Array(bytes), options: options)

0 commit comments

Comments
 (0)