Skip to content

Commit b481755

Browse files
authored
Merge pull request #25345 from lorentey/foundation-diff-apis
[Foundation] Bridge difference APIs between Foundation and swift stdlib
2 parents 5d59600 + 89b918a commit b481755

File tree

5 files changed

+113
-0
lines changed

5 files changed

+113
-0
lines changed

include/swift/AST/KnownIdentifiers.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ IDENTIFIER(Any)
3131
IDENTIFIER(ArrayLiteralElement)
3232
IDENTIFIER(atIndexedSubscript)
3333
IDENTIFIER_(bridgeToObjectiveC)
34+
IDENTIFIER(Change)
3435
IDENTIFIER_WITH_NAME(code_, "_code")
3536
IDENTIFIER(CodingKeys)
3637
IDENTIFIER(combine)

include/swift/AST/KnownStdlibTypes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ KNOWN_STDLIB_TYPE_DECL(Array, NominalTypeDecl, 1)
5454
KNOWN_STDLIB_TYPE_DECL(Set, NominalTypeDecl, 1)
5555
KNOWN_STDLIB_TYPE_DECL(Sequence, NominalTypeDecl, 1)
5656
KNOWN_STDLIB_TYPE_DECL(Dictionary, NominalTypeDecl, 2)
57+
KNOWN_STDLIB_TYPE_DECL(CollectionDifference, NominalTypeDecl, 1)
5758
KNOWN_STDLIB_TYPE_DECL(AnyHashable, NominalTypeDecl, 0)
5859
KNOWN_STDLIB_TYPE_DECL(MutableCollection, ProtocolDecl, 1)
5960
KNOWN_STDLIB_TYPE_DECL(Hasher, NominalTypeDecl, 0)

lib/AST/ASTContext.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4189,6 +4189,10 @@ bool ASTContext::isTypeBridgedInExternalModule(
41894189
nominal == getFloatDecl() ||
41904190
nominal == getDoubleDecl() ||
41914191
nominal == getArrayDecl() ||
4192+
nominal == getCollectionDifferenceDecl() ||
4193+
(nominal->getDeclContext()->getAsDecl() ==
4194+
getCollectionDifferenceDecl() &&
4195+
nominal->getBaseName() == Id_Change) ||
41924196
nominal == getDictionaryDecl() ||
41934197
nominal == getSetDecl() ||
41944198
nominal == getStringDecl() ||

stdlib/public/Darwin/Foundation/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ add_swift_target_library(swiftFoundation ${SWIFT_SDK_OVERLAY_LIBRARY_BUILD_TYPES
4141
NSItemProvider.swift
4242
NSNumber.swift
4343
NSObject.swift
44+
NSOrderedCollectionDifference.swift
4445
NSPredicate.swift
4546
NSRange.swift
4647
NSSet.swift
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
@_exported import Foundation // Clang module
14+
15+
// CollectionDifference<ChangeElement>.Change is conditionally bridged to NSOrderedCollectionChange
16+
@available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) // FIXME(availability-5.1)
17+
extension CollectionDifference.Change : _ObjectiveCBridgeable {
18+
@_semantics("convertToObjectiveC")
19+
public func _bridgeToObjectiveC() -> NSOrderedCollectionChange {
20+
switch self {
21+
case .insert(offset: let o, element: let e, associatedWith: let a):
22+
return NSOrderedCollectionChange(object: e, type: .insert, index: o, associatedIndex: a ?? NSNotFound)
23+
case .remove(offset: let o, element: let e, associatedWith: let a):
24+
return NSOrderedCollectionChange(object: e, type: .remove, index: o, associatedIndex: a ?? NSNotFound)
25+
}
26+
}
27+
28+
public static func _forceBridgeFromObjectiveC(_ input: NSOrderedCollectionChange, result: inout CollectionDifference.Change?) {
29+
let _ = input.object as! ChangeElement
30+
31+
if !_conditionallyBridgeFromObjectiveC(input, result: &result) {
32+
fatalError("Unable to bridge \(_ObjectiveCType.self) to \(self)")
33+
}
34+
}
35+
36+
public static func _conditionallyBridgeFromObjectiveC(
37+
_ x: NSOrderedCollectionChange, result: inout CollectionDifference.Change?
38+
) -> Bool {
39+
guard let element = x.object as? ChangeElement else { return false }
40+
41+
let a: Int?
42+
if x.associatedIndex == NSNotFound {
43+
a = nil
44+
} else {
45+
a = x.associatedIndex
46+
}
47+
48+
switch x.changeType {
49+
case .insert:
50+
result = .insert(offset: x.index, element: element, associatedWith: a)
51+
case .remove:
52+
result = .remove(offset: x.index, element: element, associatedWith: a)
53+
default:
54+
return false
55+
}
56+
57+
return true
58+
}
59+
60+
@_effects(readonly)
61+
public static func _unconditionallyBridgeFromObjectiveC(_ s: NSOrderedCollectionChange?) -> CollectionDifference.Change {
62+
var result: CollectionDifference<ChangeElement>.Change? = nil
63+
CollectionDifference<ChangeElement>.Change._forceBridgeFromObjectiveC(s!, result: &result)
64+
return result!
65+
}
66+
}
67+
68+
// CollectionDifference<ChangeElement> is conditionally bridged to NSOrderedCollectionDifference
69+
@available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) // FIXME(availability-5.1)
70+
extension CollectionDifference : _ObjectiveCBridgeable {
71+
@_semantics("convertToObjectiveC")
72+
public func _bridgeToObjectiveC() -> NSOrderedCollectionDifference {
73+
return NSOrderedCollectionDifference(changes: self.map({ $0 as NSOrderedCollectionChange }))
74+
}
75+
76+
public static func _forceBridgeFromObjectiveC(_ input: NSOrderedCollectionDifference, result: inout CollectionDifference?) {
77+
if !_conditionallyBridgeFromObjectiveC(input, result: &result) {
78+
fatalError("Unable to bridge \(_ObjectiveCType.self) to \(self)")
79+
}
80+
}
81+
82+
private static func _formDifference(
83+
from input: NSOrderedCollectionDifference,
84+
_ changeConverter: (Any) -> CollectionDifference<ChangeElement>.Change?
85+
) -> CollectionDifference<ChangeElement>? {
86+
var changes = Array<Change>()
87+
let iteratorSeq = IteratorSequence(NSFastEnumerationIterator(input))
88+
for objc_change in iteratorSeq {
89+
guard let swift_change = changeConverter(objc_change) else { return nil }
90+
changes.append(swift_change)
91+
}
92+
return CollectionDifference(changes)
93+
}
94+
95+
public static func _conditionallyBridgeFromObjectiveC(
96+
_ input: NSOrderedCollectionDifference, result: inout CollectionDifference?
97+
) -> Bool {
98+
result = _formDifference(from: input) { $0 as? Change }
99+
return result != nil
100+
}
101+
102+
@_effects(readonly)
103+
public static func _unconditionallyBridgeFromObjectiveC(_ s: NSOrderedCollectionDifference?) -> CollectionDifference {
104+
return _formDifference(from: s!) { $0 as! Change }!
105+
}
106+
}

0 commit comments

Comments
 (0)