From 0067c13bd8cdb7012de08d7861537296df50ee3d Mon Sep 17 00:00:00 2001 From: fumoboy007 <2100868+fumoboy007@users.noreply.github.com> Date: Sun, 27 Aug 2023 17:22:47 -0700 Subject: [PATCH] Avoid unnecessarily allocating an array when initializing `String` from a sequence of bytes. --- .../Foundation-swiftoverlay/NSStringAPI.swift | 19 ++++++++++++++----- Sources/Foundation/NSStringAPI.swift | 19 ++++++++++++++----- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/Darwin/Foundation-swiftoverlay/NSStringAPI.swift b/Darwin/Foundation-swiftoverlay/NSStringAPI.swift index fda631f7a2..a5e6457f22 100644 --- a/Darwin/Foundation-swiftoverlay/NSStringAPI.swift +++ b/Darwin/Foundation-swiftoverlay/NSStringAPI.swift @@ -208,14 +208,23 @@ extension String { /// - encoding: The encoding to use to interpret `bytes`. public init?(bytes: __shared S, encoding: Encoding) where S.Iterator.Element == UInt8 { - let byteArray = Array(bytes) - if encoding == .utf8, - let str = byteArray.withUnsafeBufferPointer({ String._tryFromUTF8($0) }) - { - self = str + if encoding == .utf8 { + if let str = bytes.withContiguousStorageIfAvailable({ String._tryFromUTF8($0) }) { + guard let str else { + return nil + } + self = str + } else { + let byteArray = Array(bytes) + guard let str = byteArray.withUnsafeBufferPointer({ String._tryFromUTF8($0) }) else { + return nil + } + self = str + } return } + let byteArray = Array(bytes) if let ns = NSString( bytes: byteArray, length: byteArray.count, encoding: encoding.rawValue) { self = String._unconditionallyBridgeFromObjectiveC(ns) diff --git a/Sources/Foundation/NSStringAPI.swift b/Sources/Foundation/NSStringAPI.swift index 0a7c475eed..efd7b38c39 100644 --- a/Sources/Foundation/NSStringAPI.swift +++ b/Sources/Foundation/NSStringAPI.swift @@ -256,14 +256,23 @@ extension String { /// - encoding: The encoding to use to interpret `bytes`. public init?(bytes: __shared S, encoding: Encoding) where S.Iterator.Element == UInt8 { - let byteArray = Array(bytes) - if encoding == .utf8, - let str = byteArray.withUnsafeBufferPointer({ String._tryFromUTF8($0) }) - { - self = str + if encoding == .utf8 { + if let str = bytes.withContiguousStorageIfAvailable({ String._tryFromUTF8($0) }) { + guard let str else { + return nil + } + self = str + } else { + let byteArray = Array(bytes) + guard let str = byteArray.withUnsafeBufferPointer({ String._tryFromUTF8($0) }) else { + return nil + } + self = str + } return } + let byteArray = Array(bytes) if let ns = NSString( bytes: byteArray, length: byteArray.count, encoding: encoding.rawValue) { self = String._unconditionallyBridgeFromObjectiveC(ns)