Files
swift-mirror/stdlib/public/core/StringGutsSlice.swift
T
Doug Gregor 453277eb74 Mark the various with* functions as @safe
Functions like withUnsafeBufferPointer are, by themselves, safe to
call. It's only the operations on the unsafe pointers passed into the
closure that are the safety issue.

This was the intent spelled out in SE-0458 but was not fully realized
in the library.

Fixes rdar://174519372.
2026-04-16 22:37:54 -07:00

99 lines
2.9 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2026 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
// TODO(String performance): Unfortunately, this slice struct seems to add
// overhead. We may want to wean ourselves off of this and have all users just
// also store a range.
// A sliced _StringGuts, convenient for unifying String/Substring comparison,
// hashing, and RRC.
internal struct _StringGutsSlice {
internal var _guts: _StringGuts
internal var _offsetRange: Range<Int>
@inline(__always)
internal init(_ guts: _StringGuts) {
self._guts = guts
self._offsetRange = unsafe Range(_uncheckedBounds: (0, guts.count))
}
@inline(__always)
internal init(_ guts: _StringGuts, _ offsetRange: Range<Int>) {
_internalInvariant(
offsetRange.lowerBound >= 0 && offsetRange.upperBound <= guts.count)
self._guts = guts
self._offsetRange = offsetRange
}
internal var start: Int {
@inline(__always) get { return _offsetRange.lowerBound }
}
internal var end: Int {
@inline(__always) get { return _offsetRange.upperBound }
}
internal var count: Int {
@inline(__always) get { return _offsetRange.count }
}
internal var isNFCFastUTF8: Bool {
@inline(__always) get { return _guts.isNFCFastUTF8 }
}
internal var isASCII: Bool {
@inline(__always) get { return _guts.isASCII }
}
internal var isFastUTF8: Bool {
@inline(__always) get { return _guts.isFastUTF8 }
}
internal var utf8Count: Int {
@inline(__always) get {
if _fastPath(self.isFastUTF8) {
return _offsetRange.count
}
return Substring(self).utf8.count
}
}
internal var range: Range<String.Index> {
@inline(__always) get {
let lower = String.Index(_encodedOffset: _offsetRange.lowerBound)
._scalarAligned
let higher = String.Index(_encodedOffset: _offsetRange.upperBound)
._scalarAligned
return unsafe Range(_uncheckedBounds: (lower, higher))
}
}
@inline(__always)
internal func withFastUTF8<R, E: Error>(
_ f: (UnsafeBufferPointer<UInt8>) throws(E) -> R
) throws(E) -> R {
return try _guts.withFastUTF8(range: _offsetRange, f)
}
@_effects(releasenone)
internal func foreignErrorCorrectedScalar(
startingAt idx: String.Index
) -> (Unicode.Scalar, scalarLength: Int) {
let (scalar, len) = _guts.foreignErrorCorrectedScalar(startingAt: idx)
if _slowPath(idx.encoded(offsetBy: len) > range.upperBound) {
return (Unicode.Scalar._replacementCharacter, 1)
}
return (scalar, len)
}
}