From f593d924a3e7e7bd036f99cf4afe203d8bad8dc3 Mon Sep 17 00:00:00 2001 From: Tony Parker Date: Mon, 24 Mar 2025 15:02:23 -0700 Subject: [PATCH] Add callout for FoundationEssentials to handle non-UTF encodings (#5193) --- Sources/Foundation/NSString.swift | 13 ++++++++++++- Tests/Foundation/TestNSString.swift | 12 ++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/Sources/Foundation/NSString.swift b/Sources/Foundation/NSString.swift index 79ec002d5b..d95433fe32 100644 --- a/Sources/Foundation/NSString.swift +++ b/Sources/Foundation/NSString.swift @@ -7,7 +7,7 @@ // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // - +@_spi(SwiftCorelibsFoundation) @_exported import FoundationEssentials @_implementationOnly import CoreFoundation internal import Synchronization @@ -1669,3 +1669,14 @@ extension String : CVarArg, _CVarArgObject { } } #endif + +// Upcall from swift-foundation for conversion of less frequently-used encodings +@_dynamicReplacement(for: _cfStringEncodingConvert(string:using:allowLossyConversion:)) +private func _cfStringEncodingConvert_corelibs_foundation(string: String, using encoding: UInt, allowLossyConversion: Bool) -> Data? { + return (string as NSString).data(using: encoding, allowLossyConversion: allowLossyConversion) +} + +@_dynamicReplacement(for: _cfMakeStringFromBytes(_:encoding:)) +private func _cfMakeStringFromBytes_corelibs_foundation(_ bytes: UnsafeBufferPointer, encoding: UInt) -> String? { + return NSString(bytes: bytes.baseAddress!, length: bytes.count, encoding: encoding) as? String +} diff --git a/Tests/Foundation/TestNSString.swift b/Tests/Foundation/TestNSString.swift index b3e24278a3..4febbc5046 100644 --- a/Tests/Foundation/TestNSString.swift +++ b/Tests/Foundation/TestNSString.swift @@ -1725,4 +1725,16 @@ class TestNSString: LoopbackServerTest { XCTAssertNotNil(str) XCTAssertEqual(str?.isEmpty, true) } + + func test_windows1252Encoding() { + // Define an array of CP1252 encoded bytes representing "Hallo " followed by the Euro sign + let cp1252Bytes: [UInt8] = [72, 97, 108, 108, 111, 32, 0x80] + let cp1252Data = Data(cp1252Bytes) + + let nativeString = String(data: cp1252Data, encoding: .windowsCP1252) + XCTAssertEqual(nativeString, "Hallo €") + + let producedData = nativeString?.data(using: .windowsCP1252) + XCTAssertEqual(producedData, cp1252Data) + } }