@@ -95,6 +95,30 @@ extension std.u32string {
9595 }
9696}
9797
98+ extension std . wstring {
99+ /// Creates a C++ wide character string having the same content as the given
100+ /// Swift string.
101+ ///
102+ /// Note that the definition of a wide character differs across platforms:
103+ /// it is UTF-16 on Windows but UTF-32 on other platforms.
104+ ///
105+ /// - Complexity: O(*n*), where *n* is the number of wide characters in the
106+ /// Swift string.
107+ @_alwaysEmitIntoClient
108+ public init ( _ string: String ) {
109+ self . init ( )
110+ #if os(Windows)
111+ for char in string. utf16 {
112+ self . push_back ( char)
113+ }
114+ #else
115+ for char in string. unicodeScalars {
116+ self . push_back ( char)
117+ }
118+ #endif
119+ }
120+ }
121+
98122// MARK: Initializing C++ string from a Swift String literal
99123
100124extension std . string : ExpressibleByStringLiteral ,
@@ -124,6 +148,15 @@ extension std.u32string: ExpressibleByStringLiteral,
124148 }
125149}
126150
151+ extension std . wstring : ExpressibleByStringLiteral ,
152+ ExpressibleByStringInterpolation {
153+
154+ @_alwaysEmitIntoClient
155+ public init ( stringLiteral value: String ) {
156+ self . init ( value)
157+ }
158+ }
159+
127160// MARK: Concatenating and comparing C++ strings
128161
129162extension std . string : Equatable , Comparable {
@@ -213,6 +246,35 @@ extension std.u32string: Equatable, Comparable {
213246 }
214247}
215248
249+ extension std . wstring : Equatable , Comparable {
250+ @_alwaysEmitIntoClient
251+ public static func == ( lhs: std . wstring , rhs: std . wstring ) -> Bool {
252+ return lhs. compare ( rhs) == 0
253+ }
254+
255+ @_alwaysEmitIntoClient
256+ public static func < ( lhs: std . wstring , rhs: std . wstring ) -> Bool {
257+ return lhs. compare ( rhs) < 0
258+ }
259+
260+ @_alwaysEmitIntoClient
261+ public static func += ( lhs: inout std . wstring , rhs: std . wstring ) {
262+ lhs. append ( rhs)
263+ }
264+
265+ @_alwaysEmitIntoClient
266+ public mutating func append( _ other: std . wstring ) {
267+ unsafe __appendUnsafe( other) // ignore the returned pointer
268+ }
269+
270+ @_alwaysEmitIntoClient
271+ public static func + ( lhs: std . wstring , rhs: std . wstring ) -> std . wstring {
272+ var copy = lhs
273+ copy += rhs
274+ return copy
275+ }
276+ }
277+
216278// MARK: Hashing C++ strings
217279
218280extension std . string : Hashable {
@@ -242,6 +304,15 @@ extension std.u32string: Hashable {
242304 }
243305}
244306
307+ extension std . wstring : Hashable {
308+ @_alwaysEmitIntoClient
309+ public func hash( into hasher: inout Hasher ) {
310+ // Call std::hash<std::wstring>::operator()
311+ let cxxHash = __swift_interopComputeHashOfWString ( self )
312+ hasher. combine ( cxxHash)
313+ }
314+ }
315+
245316// MARK: Getting a Swift description of a C++ string
246317
247318extension std . string : CustomDebugStringConvertible {
@@ -265,6 +336,13 @@ extension std.u32string: CustomDebugStringConvertible {
265336 }
266337}
267338
339+ extension std . wstring : CustomDebugStringConvertible {
340+ @_alwaysEmitIntoClient
341+ public var debugDescription : String {
342+ return " std.wstring( \( String ( self ) ) ) "
343+ }
344+ }
345+
268346extension std . string : CustomStringConvertible {
269347 @_alwaysEmitIntoClient
270348 public var description : String {
@@ -286,6 +364,13 @@ extension std.u32string: CustomStringConvertible {
286364 }
287365}
288366
367+ extension std . wstring : CustomStringConvertible {
368+ @_alwaysEmitIntoClient
369+ public var description : String {
370+ return String ( self )
371+ }
372+ }
373+
289374// MARK: Initializing Swift String from a C++ string
290375
291376extension String {
@@ -342,6 +427,36 @@ extension String {
342427 }
343428 withExtendedLifetime ( cxxU32String) { }
344429 }
430+
431+ /// Creates a String having the same content as the given C++ wide character
432+ /// string.
433+ ///
434+ /// Note that the definition of a wide character differs across platforms:
435+ /// it is UTF-16 on Windows but UTF-32 on other platforms.
436+ ///
437+ /// If `cxxString` contains ill-formed UTF code unit sequences, this
438+ /// initializer replaces them with the Unicode replacement character
439+ /// (`"\u{FFFD}"`).
440+ ///
441+ /// - Complexity: O(*n*), where *n* is the number of wide characters in the
442+ /// C++ string.
443+ @_alwaysEmitIntoClient
444+ public init ( _ cxxWString: std . wstring ) {
445+ #if os(Windows)
446+ let buffer = unsafe UnsafeBufferPointer< UInt16 > (
447+ start: cxxWString. __dataUnsafe ( ) ,
448+ count: cxxWString. size ( ) )
449+ self = unsafe String( decoding: buffer, as: UTF16 . self)
450+ #else
451+ let buffer = unsafe UnsafeBufferPointer< Unicode . Scalar > (
452+ start: cxxWString. __dataUnsafe ( ) ,
453+ count: cxxWString. size ( ) )
454+ self = unsafe buffer. withMemoryRebound ( to: UInt32 . self) {
455+ unsafe String( decoding: $0, as: UTF32 . self)
456+ }
457+ #endif
458+ withExtendedLifetime ( cxxWString) { }
459+ }
345460}
346461
347462// MARK: Initializing Swift String from a C++ string_view
@@ -403,6 +518,24 @@ extension String {
403518 }
404519 unsafe withExtendedLifetime ( cxxU32StringView) { }
405520 }
521+
522+ @_alwaysEmitIntoClient
523+ public init ( _ cxxWStringView: std . wstring_view ) {
524+ #if os(Windows)
525+ let buffer = unsafe UnsafeBufferPointer< UInt16 > (
526+ start: cxxWStringView. __dataUnsafe ( ) ,
527+ count: cxxWStringView. size ( ) )
528+ self = unsafe String( decoding: buffer, as: UTF16 . self)
529+ #else
530+ let buffer = unsafe UnsafeBufferPointer< Unicode . Scalar > (
531+ start: cxxWStringView. __dataUnsafe ( ) ,
532+ count: cxxWStringView. size ( ) )
533+ self = unsafe buffer. withMemoryRebound ( to: UInt32 . self) {
534+ unsafe String( decoding: $0, as: UTF32 . self)
535+ }
536+ #endif
537+ withExtendedLifetime ( cxxWStringView) { }
538+ }
406539}
407540
408541@available ( SwiftCompatibilitySpan 5 . 0 , * )
@@ -463,3 +596,18 @@ extension std.u32string {
463596 }
464597 }
465598}
599+
600+ @available ( SwiftCompatibilitySpan 5 . 0 , * )
601+ extension std . wstring {
602+ public var span : Span < CWideChar > {
603+ @_lifetime ( borrow self)
604+ @_alwaysEmitIntoClient
605+ borrowing get {
606+ let buffer = unsafe UnsafeBufferPointer( start: self . __dataUnsafe ( ) , count: Int ( self . size ( ) ) )
607+ let rawBuffer = UnsafeRawBufferPointer ( buffer)
608+ let bufferWithFixedType = unsafe rawBuffer. assumingMemoryBound ( to: CWideChar . self)
609+ let span = unsafe Span( _unsafeElements: bufferWithFixedType)
610+ return unsafe _cxxOverrideLifetime ( span, borrowing: self )
611+ }
612+ }
613+ }
0 commit comments