@@ -749,8 +749,38 @@ extension Substring.UTF8View: BidirectionalCollection {
749
749
}
750
750
}
751
751
752
+ @available ( SwiftStdlib 6 . 2 , * )
752
753
extension Substring . UTF8View {
753
754
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))
754
784
/// A span over the UTF8 code units that make up this substring.
755
785
///
756
786
/// - Note: In the case of bridged UTF16 String instances (on Apple
@@ -776,32 +806,80 @@ extension Substring.UTF8View {
776
806
public var span : Span < UTF8 . CodeUnit > {
777
807
@lifetime ( borrow self)
778
808
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 = 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
797
878
}
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 ( )
803
880
}
804
881
}
882
+ #endif // !(os(watchOS) && _pointerBitWidth(_32))
805
883
}
806
884
807
885
extension Substring {
0 commit comments