Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions stdlib/public/core/StringGuts.swift
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,13 @@ extension _StringGuts {
}
}

extension _StringGuts {
@inline(__always) // Performance
internal func isTriviallyIdentical(to other: Self) -> Bool {
self.rawBits == other.rawBits
}
}

#if _runtime(_ObjC)
extension _StringGuts {

Expand Down
11 changes: 11 additions & 0 deletions stdlib/public/core/StringUTF16View.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1056,3 +1056,14 @@ extension String.UTF16View {
}
}
}

extension String.UTF16View {
/// Returns a boolean value indicating whether this UTF16 view
/// is trivially identical to `other`.
///
/// - Complexity: O(1)
@available(SwiftStdlib 6.3, *)
public func isTriviallyIdentical(to other: Self) -> Bool {
self._guts.isTriviallyIdentical(to: other._guts)
}
}
11 changes: 11 additions & 0 deletions stdlib/public/core/StringUTF8View.swift
Original file line number Diff line number Diff line change
Expand Up @@ -684,3 +684,14 @@ extension String.UTF8View {
return unsafe try _guts.withFastUTF8(body)
}
}

extension String.UTF8View {
/// Returns a boolean value indicating whether this UTF8 view
/// is trivially identical to `other`.
///
/// - Complexity: O(1)
@available(SwiftStdlib 6.3, *)
public func isTriviallyIdentical(to other: Self) -> Bool {
self._guts.isTriviallyIdentical(to: other._guts)
}
}
11 changes: 11 additions & 0 deletions stdlib/public/core/StringUnicodeScalarView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -527,3 +527,14 @@ extension String.UnicodeScalarView {
return r._knownUTF16
}
}

extension String.UnicodeScalarView {
/// Returns a boolean value indicating whether this unicode scalar view
/// is trivially identical to `other`.
///
/// - Complexity: O(1)
@available(SwiftStdlib 6.3, *)
public func isTriviallyIdentical(to other: Self) -> Bool {
self._guts.isTriviallyIdentical(to: other._guts)
}
}
36 changes: 36 additions & 0 deletions stdlib/public/core/Substring.swift
Original file line number Diff line number Diff line change
Expand Up @@ -882,6 +882,18 @@ extension Substring.UTF8View {
#endif // !(os(watchOS) && _pointerBitWidth(_32))
}

extension Substring.UTF8View {
/// Returns a boolean value indicating whether this UTF8 view
/// is trivially identical to `other`.
///
/// - Complexity: O(1)
@available(SwiftStdlib 6.3, *)
public func isTriviallyIdentical(to other: Self) -> Bool {
self._base.isTriviallyIdentical(to: other._base)
&& self._bounds == other._bounds
}
}

extension Substring {
@inlinable
public var utf8: UTF8View {
Expand Down Expand Up @@ -1037,6 +1049,18 @@ extension Substring.UTF16View: BidirectionalCollection {
}
}

extension Substring.UTF16View {
/// Returns a boolean value indicating whether this UTF16 view
/// is trivially identical to `other`.
///
/// - Complexity: O(1)
@available(SwiftStdlib 6.3, *)
public func isTriviallyIdentical(to other: Self) -> Bool {
self._base.isTriviallyIdentical(to: other._base)
&& self._bounds == other._bounds
}
}

extension Substring {
@inlinable
public var utf16: UTF16View {
Expand Down Expand Up @@ -1281,6 +1305,18 @@ extension Substring.UnicodeScalarView: RangeReplaceableCollection {
}
}

extension Substring.UnicodeScalarView {
/// Returns a boolean value indicating whether this unicode scalar view
/// is trivially identical to `other`.
///
/// - Complexity: O(1)
@available(SwiftStdlib 6.3, *)
public func isTriviallyIdentical(to other: Self) -> Bool {
self._slice._base.isTriviallyIdentical(to: other._slice._base)
&& self._bounds == other._bounds
}
}

extension Substring: RangeReplaceableCollection {
@_specialize(where S == String)
@_specialize(where S == Substring)
Expand Down
124 changes: 124 additions & 0 deletions test/stdlib/StringAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,130 @@ StringTests.test("_isIdentical(to:)") {
expectTrue(g._isIdentical(to: g))
}

StringTests.test("String.UnicodeScalarView.isTriviallyIdentical(to:)")
.skip(.custom({
if #available(SwiftStdlib 6.3, *) { false } else { true }
}, reason: "Requires Swift stdlib 6.3"))
.code {
guard #available(SwiftStdlib 6.3, *) else { return }

let a = "Hello".unicodeScalars
let b = "Hello".unicodeScalars
expectTrue(a.isTriviallyIdentical(to: a))
expectTrue(b.isTriviallyIdentical(to: b))
expectTrue(a.isTriviallyIdentical(to: b))
expectTrue(b.isTriviallyIdentical(to: a))

let c = "Abcde".unicodeScalars
expectFalse(a.isTriviallyIdentical(to: c))
expectFalse(c.isTriviallyIdentical(to: a))
}
StringTests.test("String.UTF8View.isTriviallyIdentical(to:)")
.skip(.custom({
if #available(SwiftStdlib 6.3, *) { false } else { true }
}, reason: "Requires Swift stdlib 6.3"))
.code {
guard #available(SwiftStdlib 6.3, *) else { return }

let a = "Hello".utf8
let b = "Hello".utf8
expectTrue(a.isTriviallyIdentical(to: a))
expectTrue(b.isTriviallyIdentical(to: b))
expectTrue(a.isTriviallyIdentical(to: b))
expectTrue(b.isTriviallyIdentical(to: a))


let c = "Abcde".utf8
expectFalse(a.isTriviallyIdentical(to: c))
expectFalse(c.isTriviallyIdentical(to: a))
}
StringTests.test("String.UTF16View.isTriviallyIdentical(to:)")
.skip(.custom({
if #available(SwiftStdlib 6.3, *) { false } else { true }
}, reason: "Requires Swift stdlib 6.3"))
.code {
guard #available(SwiftStdlib 6.3, *) else { return }

let a = "Hello".utf16
let b = "Hello".utf16
expectTrue(a.isTriviallyIdentical(to: a))
expectTrue(b.isTriviallyIdentical(to: b))
expectTrue(a.isTriviallyIdentical(to: b))
expectTrue(b.isTriviallyIdentical(to: a))


let c = "Abcde".utf16
expectFalse(a.isTriviallyIdentical(to: c))
expectFalse(c.isTriviallyIdentical(to: a))
}

StringTests.test("Substring.UnicodeScalarView.isTriviallyIdentical(to:)")
.skip(.custom({
if #available(SwiftStdlib 6.3, *) { false } else { true }
}, reason: "Requires Swift stdlib 6.3"))
.code {
guard #available(SwiftStdlib 6.3, *) else { return }

let base1 = "Test String"
let a = base1[base1.index(base1.startIndex, offsetBy: 5)..<base1.endIndex]
.unicodeScalars
let b = base1[base1.index(base1.startIndex, offsetBy: 5)..<base1.endIndex]
.unicodeScalars
expectTrue(a.isTriviallyIdentical(to: a))
expectTrue(b.isTriviallyIdentical(to: b))
expectTrue(a.isTriviallyIdentical(to: b))
expectTrue(b.isTriviallyIdentical(to: a))

let c = base1[base1.startIndex..<base1.index(base1.startIndex, offsetBy: 5)]
.unicodeScalars
expectFalse(a.isTriviallyIdentical(to: c))
expectFalse(c.isTriviallyIdentical(to: a))
}
StringTests.test("Substring.UTF8View.isTriviallyIdentical(to:)")
.skip(.custom({
if #available(SwiftStdlib 6.3, *) { false } else { true }
}, reason: "Requires Swift stdlib 6.3"))
.code {
guard #available(SwiftStdlib 6.3, *) else { return }

let base1 = "Test String"
let a = base1[base1.index(base1.startIndex, offsetBy: 5)..<base1.endIndex]
.utf8
let b = base1[base1.index(base1.startIndex, offsetBy: 5)..<base1.endIndex]
.utf8
expectTrue(a.isTriviallyIdentical(to: a))
expectTrue(b.isTriviallyIdentical(to: b))
expectTrue(a.isTriviallyIdentical(to: b))
expectTrue(b.isTriviallyIdentical(to: a))

let c = base1[base1.startIndex..<base1.index(base1.startIndex, offsetBy: 5)]
.utf8
expectFalse(a.isTriviallyIdentical(to: c))
expectFalse(c.isTriviallyIdentical(to: a))
}
StringTests.test("Substring.UTF16View.isTriviallyIdentical(to:)")
.skip(.custom({
if #available(SwiftStdlib 6.3, *) { false } else { true }
}, reason: "Requires Swift stdlib 6.3"))
.code {
guard #available(SwiftStdlib 6.3, *) else { return }

let base1 = "Test String"
let a = base1[base1.index(base1.startIndex, offsetBy: 5)..<base1.endIndex]
.utf16
let b = base1[base1.index(base1.startIndex, offsetBy: 5)..<base1.endIndex]
.utf16
expectTrue(a.isTriviallyIdentical(to: a))
expectTrue(b.isTriviallyIdentical(to: b))
expectTrue(a.isTriviallyIdentical(to: b))
expectTrue(b.isTriviallyIdentical(to: a))

let c = base1[base1.startIndex..<base1.index(base1.startIndex, offsetBy: 5)]
.utf16
expectFalse(a.isTriviallyIdentical(to: c))
expectFalse(c.isTriviallyIdentical(to: a))
}

StringTests.test("hasPrefix/hasSuffix vs Character boundaries") {
// https://github.com/apple/swift/issues/67427
let s1 = "\r\n"
Expand Down