@@ -749,8 +749,38 @@ extension Substring.UTF8View: BidirectionalCollection {
749749 }
750750}
751751
752+ @available ( SwiftStdlib 6 . 2 , * )
752753extension Substring . UTF8View {
753754
755+ @lifetime ( borrow self)
756+ private borrowing func _underlyingSpan( ) -> Span < UTF8 . CodeUnit > {
757+ #if _runtime(_ObjC)
758+ // handle non-UTF8 Objective-C bridging cases here
759+ if !_wholeGuts. isFastUTF8, _wholeGuts. _object. hasObjCBridgeableObject {
760+ let base : String . UTF8View = self . _base
761+ let first = base. _foreignDistance ( from: base. startIndex, to: startIndex)
762+ let count = base. _foreignDistance ( from: startIndex, to: endIndex)
763+ let span = base. _underlyingSpan ( ) . _extracting ( first..< ( first &+ count) )
764+ return unsafe _override Lifetime ( span, borrowing: self )
765+ }
766+ #endif // _runtime(_ObjC)
767+ let first = _slice. _startIndex. _encodedOffset
768+ let end = _slice. _endIndex. _encodedOffset
769+ if _wholeGuts. isSmall {
770+ let a = Builtin . addressOfBorrow ( self )
771+ let offset = first &+ ( 2 &* MemoryLayout< String . Index> . stride)
772+ let start = unsafe UnsafePointer< UTF8 . CodeUnit > ( a) . advanced ( by: offset)
773+ let span = unsafe Span( _unsafeStart: start, count: end &- first)
774+ return unsafe _override Lifetime ( span, borrowing: self )
775+ }
776+ let isFastUTF8 = _wholeGuts. isFastUTF8
777+ _precondition ( isFastUTF8, " Substring must be contiguous UTF8 " )
778+ var span = unsafe Span( _unsafeElements: _wholeGuts. _object. fastUTF8)
779+ span = span. _extracting ( first..< end)
780+ return unsafe _override Lifetime ( span, borrowing: self )
781+ }
782+
783+ #if !(os(watchOS) && _pointerBitWidth(_32))
754784 /// A span over the UTF8 code units that make up this substring.
755785 ///
756786 /// - Note: In the case of bridged UTF16 String instances (on Apple
@@ -776,32 +806,80 @@ extension Substring.UTF8View {
776806 public var span : Span < UTF8 . CodeUnit > {
777807 @lifetime ( borrow self)
778808 borrowing get {
779- #if _runtime(_ObjC)
780- // handle non-UTF8 Objective-C bridging cases here
781- if !_wholeGuts. isFastUTF8, _wholeGuts. _object. hasObjCBridgeableObject {
782- let base : String . UTF8View = self . _base
783- let first = base. _foreignDistance ( from: base. startIndex, to: startIndex)
784- let count = base. _foreignDistance ( from: startIndex, to: endIndex)
785- let span = unsafe base. span . _extracting ( first..< ( first &+ count) )
786- return unsafe _override Lifetime ( span, borrowing: self )
787- }
788- #endif
789- let first = _slice. _startIndex. _encodedOffset
790- let end = _slice. _endIndex. _encodedOffset
791- if _wholeGuts. isSmall {
792- let a = Builtin . addressOfBorrow ( self )
793- let offset = first &+ ( 2 &* MemoryLayout< String . Index> . stride)
794- let start = unsafe UnsafePointer< UTF8 . CodeUnit > ( a) . advanced ( by: offset)
795- let span = unsafe Span( _unsafeStart: start, count: end &- first)
796- return unsafe _override Lifetime ( span, borrowing: self )
809+ _underlyingSpan ( )
810+ }
811+ }
812+
813+ /// A span over the UTF8 code units that make up this substring.
814+ ///
815+ /// - Note: In the case of bridged UTF16 String instances (on Apple
816+ /// platforms,) this property needs to transcode the code units every time
817+ /// it is called.
818+ /// For example, if `string` has the bridged UTF16 representation,
819+ /// for word in string.split(separator: " ") {
820+ /// useSpan(word.span)
821+ /// }
822+ /// is accidentally quadratic because of this issue. A workaround is to
823+ /// explicitly convert the string into its native UTF8 representation:
824+ /// var nativeString = consume string
825+ /// nativeString.makeContiguousUTF8()
826+ /// for word in nativeString.split(separator: " ") {
827+ /// useSpan(word.span)
828+ /// }
829+ /// This second option has linear time complexity, as expected.
830+ ///
831+ /// Returns: a `Span` over the UTF8 code units of this Substring.
832+ ///
833+ /// Complexity: O(1) for native UTF8 Strings, O(n) for bridged UTF16 Strings.
834+ @available ( SwiftStdlib 6 . 2 , * )
835+ public var _span : Span < UTF8 . CodeUnit > ? {
836+ @_alwaysEmitIntoClient @inline ( __always)
837+ @lifetime ( borrow self)
838+ borrowing get {
839+ span
840+ }
841+ }
842+ #else // !(os(watchOS) && _pointerBitWidth(_32))
843+ @available ( watchOS, unavailable)
844+ public var span : Span < UTF8 . CodeUnit > {
845+ fatalError ( " \( #function) unavailable on 32-bit watchOS " )
846+ }
847+
848+ /// A span over the UTF8 code units that make up this substring.
849+ ///
850+ /// - Note: In the case of bridged UTF16 String instances (on Apple
851+ /// platforms,) this property needs to transcode the code units every time
852+ /// it is called.
853+ /// For example, if `string` has the bridged UTF16 representation,
854+ /// for word in string.split(separator: " ") {
855+ /// useSpan(word.span)
856+ /// }
857+ /// is accidentally quadratic because of this issue. A workaround is to
858+ /// explicitly convert the string into its native UTF8 representation:
859+ /// var nativeString = consume string
860+ /// nativeString.makeContiguousUTF8()
861+ /// for word in nativeString.split(separator: " ") {
862+ /// useSpan(word.span)
863+ /// }
864+ /// This second option has linear time complexity, as expected.
865+ ///
866+ /// Returns: a `Span` over the UTF8 code units of this Substring, or `nil`
867+ /// if the Substring does not have a contiguous representation.
868+ ///
869+ /// Complexity: O(1) for native UTF8 Strings, O(n) for bridged UTF16 Strings.
870+ @available ( SwiftStdlib 6 . 2 , * )
871+ public var _span : Span < UTF8 . CodeUnit > ? {
872+ @lifetime ( borrow self)
873+ borrowing get {
874+ if _wholeGuts. isSmall,
875+ _wholeGuts. count > _SmallString. contiguousCapacity ( ) {
876+ // substring is spannable only when the whole string is spannable.
877+ return nil
797878 }
798- let isFastUTF8 = _wholeGuts. isFastUTF8
799- _precondition ( isFastUTF8, " Substring must be contiguous UTF8 " )
800- var span = unsafe Span( _unsafeElements: _wholeGuts. _object. fastUTF8)
801- span = span. _extracting ( first..< end)
802- return unsafe _override Lifetime ( span, borrowing: self )
879+ return _underlyingSpan ( )
803880 }
804881 }
882+ #endif // !(os(watchOS) && _pointerBitWidth(_32))
805883}
806884
807885extension Substring {
0 commit comments