Skip to content

Commit 2fb0ff4

Browse files
committed
Use typed throws everywhere to prevent allocation in the unhappy path.
1 parent 6176cd8 commit 2fb0ff4

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
@@ -431,46 +431,55 @@ extension Base64 {
431431
static var unexpectedEnd: Self { .init(.unexpectedEnd) }
432432
}
433433

434-
static func decode(string encoded: String, options: Data.Base64DecodingOptions = []) throws -> Data {
435-
let decoded = try encoded.utf8.withContiguousStorageIfAvailable { characterPointer -> Data in
436-
// `withContiguousStorageIfAvailable` sadly does not support typed throws
437-
try Self._decodeToData(from: characterPointer, options: options)
434+
static func decode(string encoded: String, options: Data.Base64DecodingOptions = []) throws(DecodingError) -> Data {
435+
let result = encoded.utf8.withContiguousStorageIfAvailable { bufferPointer in
436+
// `withContiguousStorageIfAvailable` sadly does not support typed throws, so we need
437+
// to use Result to get the error out without allocation for the error.
438+
Result(catching: { () throws(DecodingError) -> Data in
439+
try Self._decodeToData(from: bufferPointer, options: options)
440+
})
438441
}
439442

440-
if decoded != nil {
441-
return decoded!
443+
if let result {
444+
return try result.get()
442445
}
443446

444447
var encoded = encoded
445448
encoded.makeContiguousUTF8()
446449
return try Self.decode(string: encoded, options: options)
447450
}
448451

449-
static func decode(data encoded: Data, options: Data.Base64DecodingOptions = []) throws -> Data {
450-
let decoded = try encoded.withContiguousStorageIfAvailable { bufferPointer -> Data in
451-
// `withContiguousStorageIfAvailable` sadly does not support typed throws
452-
try Self._decodeToData(from: bufferPointer, options: options)
452+
static func decode(data encoded: Data, options: Data.Base64DecodingOptions = []) throws(DecodingError) -> Data? {
453+
let result = encoded.withContiguousStorageIfAvailable { bufferPointer in
454+
// `withContiguousStorageIfAvailable` sadly does not support typed throws, so we need
455+
// to use Result to get the error out without allocation for the error.
456+
Result(catching: { () throws(DecodingError) -> Data in
457+
try Self._decodeToData(from: bufferPointer, options: options)
458+
})
453459
}
454460

455-
if decoded != nil {
456-
return decoded!
461+
if let result {
462+
return try result.get()
457463
}
458464

459465
return try Self.decode(bytes: Array(encoded), options: options)
460466
}
461467

462-
static func decode<Buffer: Collection>(bytes: Buffer, options: Data.Base64DecodingOptions = []) throws -> Data where Buffer.Element == UInt8 {
468+
static func decode<Buffer: Collection>(bytes: Buffer, options: Data.Base64DecodingOptions = []) throws(DecodingError) -> Data where Buffer.Element == UInt8 {
463469
guard bytes.count > 0 else {
464470
return Data()
465471
}
466472

467-
let decoded = try bytes.withContiguousStorageIfAvailable { bufferPointer -> Data in
468-
// `withContiguousStorageIfAvailable` sadly does not support typed throws
469-
try Self._decodeToData(from: bufferPointer, options: options)
473+
let result = bytes.withContiguousStorageIfAvailable { bufferPointer in
474+
// `withContiguousStorageIfAvailable` sadly does not support typed throws, so we need
475+
// to use Result to get the error out without allocation for the error.
476+
Result(catching: { () throws(DecodingError) -> Data in
477+
try Self._decodeToData(from: bufferPointer, options: options)
478+
})
470479
}
471480

472-
if decoded != nil {
473-
return decoded!
481+
if let result {
482+
return try result.get()
474483
}
475484

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

0 commit comments

Comments
 (0)