@@ -206,9 +206,22 @@ open class NSData : NSObject, NSCopying, NSMutableCopying, NSSecureCoding {
206
206
207
207
/// Initializes a data object with the given Base64 encoded string.
208
208
public init ? ( base64Encoded base64String: String , options: Base64DecodingOptions = [ ] ) {
209
- guard var decodedBytes = NSData . base64DecodeBytes ( base64String. utf8, options: options) else {
210
- return nil
209
+
210
+ let result : UnsafeMutableRawBufferPointer ?
211
+ if let _result = base64String. utf8. withContiguousStorageIfAvailable ( { buffer -> UnsafeMutableRawBufferPointer ? in
212
+ let rawBuffer = UnsafeRawBufferPointer ( start: buffer. baseAddress!, count: buffer. count)
213
+ return NSData . base64DecodeBytes ( rawBuffer, options: options)
214
+ } ) {
215
+ result = _result
216
+ } else {
217
+ // Slow path, unlikely that withContiguousStorageIfAvailable will fail but if it does, fall back to .utf8CString.
218
+ // This will allocate and copy but it is the simplest way to get a contiguous buffer.
219
+ result = base64String. utf8CString. withUnsafeBufferPointer { buffer -> UnsafeMutableRawBufferPointer ? in
220
+ let rawBuffer = UnsafeRawBufferPointer ( start: buffer. baseAddress!, count: buffer. count - 1 ) // -1 to ignore the terminating NUL
221
+ return NSData . base64DecodeBytes ( rawBuffer, options: options)
222
+ }
211
223
}
224
+ guard let decodedBytes = result else { return nil }
212
225
super. init ( )
213
226
_init ( bytes: decodedBytes. baseAddress!, length: decodedBytes. count, copy: false , deallocator: { ( ptr, length) in
214
227
ptr. deallocate ( )
@@ -217,7 +230,9 @@ open class NSData : NSObject, NSCopying, NSMutableCopying, NSSecureCoding {
217
230
218
231
/// Initializes a data object with the given Base64 encoded data.
219
232
public init ? ( base64Encoded base64Data: Data , options: Base64DecodingOptions = [ ] ) {
220
- guard var decodedBytes = NSData . base64DecodeBytes ( base64Data, options: options) else {
233
+ guard let decodedBytes = base64Data. withUnsafeBytes ( { rawBuffer in
234
+ NSData . base64DecodeBytes ( rawBuffer, options: options)
235
+ } ) else {
221
236
return nil
222
237
}
223
238
super. init ( )
@@ -638,7 +653,7 @@ open class NSData : NSObject, NSCopying, NSMutableCopying, NSSecureCoding {
638
653
- parameter options: Options for handling invalid input
639
654
- returns: The decoded bytes.
640
655
*/
641
- private static func base64DecodeBytes< T : Collection > ( _ bytes: T , options: Base64DecodingOptions = [ ] ) -> UnsafeMutableRawBufferPointer ? where T . Element == UInt8 {
656
+ private static func base64DecodeBytes( _ bytes: UnsafeRawBufferPointer , options: Base64DecodingOptions = [ ] ) -> UnsafeMutableRawBufferPointer ? {
642
657
643
658
// This table maps byte values 0-127, input bytes >127 are always invalid.
644
659
// Map the ASCII characters "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" -> 0...63
0 commit comments