Skip to content

Commit db9b634

Browse files
committed
Use typed throws everywhere to prevent allocation in the unhappy path.
1 parent 446050b commit db9b634

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
@@ -481,46 +481,55 @@ extension Base64 {
481481
static var unexpectedEnd: Self { .init(.unexpectedEnd) }
482482
}
483483

484-
static func decode(string encoded: String, options: Data.Base64DecodingOptions = []) throws -> Data {
485-
let decoded = try encoded.utf8.withContiguousStorageIfAvailable { characterPointer -> Data in
486-
// `withContiguousStorageIfAvailable` sadly does not support typed throws
487-
try Self._decodeToData(from: characterPointer, options: options)
484+
static func decode(string encoded: String, options: Data.Base64DecodingOptions = []) throws(DecodingError) -> Data {
485+
let result = encoded.utf8.withContiguousStorageIfAvailable { bufferPointer in
486+
// `withContiguousStorageIfAvailable` sadly does not support typed throws, so we need
487+
// to use Result to get the error out without allocation for the error.
488+
Result(catching: { () throws(DecodingError) -> Data in
489+
try Self._decodeToData(from: bufferPointer, options: options)
490+
})
488491
}
489492

490-
if decoded != nil {
491-
return decoded!
493+
if let result {
494+
return try result.get()
492495
}
493496

494497
var encoded = encoded
495498
encoded.makeContiguousUTF8()
496499
return try Self.decode(string: encoded, options: options)
497500
}
498501

499-
static func decode(data encoded: Data, options: Data.Base64DecodingOptions = []) throws -> Data {
500-
let decoded = try encoded.withContiguousStorageIfAvailable { bufferPointer -> Data in
501-
// `withContiguousStorageIfAvailable` sadly does not support typed throws
502-
try Self._decodeToData(from: bufferPointer, options: options)
502+
static func decode(data encoded: Data, options: Data.Base64DecodingOptions = []) throws(DecodingError) -> Data? {
503+
let result = encoded.withContiguousStorageIfAvailable { bufferPointer in
504+
// `withContiguousStorageIfAvailable` sadly does not support typed throws, so we need
505+
// to use Result to get the error out without allocation for the error.
506+
Result(catching: { () throws(DecodingError) -> Data in
507+
try Self._decodeToData(from: bufferPointer, options: options)
508+
})
503509
}
504510

505-
if decoded != nil {
506-
return decoded!
511+
if let result {
512+
return try result.get()
507513
}
508514

509515
return try Self.decode(bytes: Array(encoded), options: options)
510516
}
511517

512-
static func decode<Buffer: Collection>(bytes: Buffer, options: Data.Base64DecodingOptions = []) throws -> Data where Buffer.Element == UInt8 {
518+
static func decode<Buffer: Collection>(bytes: Buffer, options: Data.Base64DecodingOptions = []) throws(DecodingError) -> Data where Buffer.Element == UInt8 {
513519
guard bytes.count > 0 else {
514520
return Data()
515521
}
516522

517-
let decoded = try bytes.withContiguousStorageIfAvailable { bufferPointer -> Data in
518-
// `withContiguousStorageIfAvailable` sadly does not support typed throws
519-
try Self._decodeToData(from: bufferPointer, options: options)
523+
let result = bytes.withContiguousStorageIfAvailable { bufferPointer in
524+
// `withContiguousStorageIfAvailable` sadly does not support typed throws, so we need
525+
// to use Result to get the error out without allocation for the error.
526+
Result(catching: { () throws(DecodingError) -> Data in
527+
try Self._decodeToData(from: bufferPointer, options: options)
528+
})
520529
}
521530

522-
if decoded != nil {
523-
return decoded!
531+
if let result {
532+
return try result.get()
524533
}
525534

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

0 commit comments

Comments
 (0)