|
10 | 10 | // |
11 | 11 | //===----------------------------------------------------------------------===// |
12 | 12 |
|
13 | | -#if _runtime(_ObjC) |
14 | 13 | /// A Swift Array or Dictionary of types conforming to |
15 | 14 | /// `_ObjectiveCBridgeable` can be passed to Objective-C as an NSArray or |
16 | 15 | /// NSDictionary, respectively. The elements of the resulting NSArray |
@@ -83,6 +82,8 @@ public protocol _ObjectiveCBridgeable { |
83 | 82 | -> Self |
84 | 83 | } |
85 | 84 |
|
| 85 | +#if _runtime(_ObjC) |
| 86 | + |
86 | 87 | //===--- Bridging for metatypes -------------------------------------------===// |
87 | 88 |
|
88 | 89 | /// A stand-in for a value of metatype type. |
@@ -640,3 +641,182 @@ public func _getObjCTypeEncoding<T>(_ type: T.Type) -> UnsafePointer<Int8> { |
640 | 641 | } |
641 | 642 |
|
642 | 643 | #endif |
| 644 | + |
| 645 | +//===--- Bridging without the ObjC runtime --------------------------------===// |
| 646 | + |
| 647 | +#if !_runtime(_ObjC) |
| 648 | + |
| 649 | +/// Convert `x` from its Objective-C representation to its Swift |
| 650 | +/// representation. |
| 651 | +/// COMPILER_INTRINSIC |
| 652 | +@_inlineable // FIXME(sil-serialize-all) |
| 653 | +public func _forceBridgeFromObjectiveC_bridgeable<T:_ObjectiveCBridgeable> ( |
| 654 | + _ x: T._ObjectiveCType, |
| 655 | + _: T.Type |
| 656 | +) -> T { |
| 657 | + var result: T? |
| 658 | + T._forceBridgeFromObjectiveC(x, result: &result) |
| 659 | + return result! |
| 660 | +} |
| 661 | + |
| 662 | +/// Attempt to convert `x` from its Objective-C representation to its Swift |
| 663 | +/// representation. |
| 664 | +/// COMPILER_INTRINSIC |
| 665 | +@_inlineable // FIXME(sil-serialize-all) |
| 666 | +public func _conditionallyBridgeFromObjectiveC_bridgeable<T:_ObjectiveCBridgeable>( |
| 667 | + _ x: T._ObjectiveCType, |
| 668 | + _: T.Type |
| 669 | +) -> T? { |
| 670 | + var result: T? |
| 671 | + T._conditionallyBridgeFromObjectiveC (x, result: &result) |
| 672 | + return result |
| 673 | +} |
| 674 | + |
| 675 | +public // SPI(Foundation) |
| 676 | +protocol _NSSwiftValue: class { |
| 677 | + init(_ value: Any) |
| 678 | + var value: Any { get } |
| 679 | + static var null: AnyObject { get } |
| 680 | +} |
| 681 | + |
| 682 | +@usableFromInline |
| 683 | +internal class _SwiftValue { |
| 684 | + @usableFromInline |
| 685 | + let value: Any |
| 686 | + |
| 687 | + @usableFromInline |
| 688 | + init(_ value: Any) { |
| 689 | + self.value = value |
| 690 | + } |
| 691 | + |
| 692 | + @usableFromInline |
| 693 | + static let null = _SwiftValue(Optional<Any>.none as Any) |
| 694 | +} |
| 695 | + |
| 696 | +// Internal stdlib SPI |
| 697 | +@_silgen_name("swift_unboxFromSwiftValueWithType") |
| 698 | +public func swift_unboxFromSwiftValueWithType<T>( |
| 699 | + _ source: inout AnyObject, |
| 700 | + _ result: UnsafeMutablePointer<T> |
| 701 | + ) -> Bool { |
| 702 | + |
| 703 | + if source === _nullPlaceholder { |
| 704 | + if let unpacked = Optional<Any>.none as? T { |
| 705 | + result.initialize(to: unpacked) |
| 706 | + return true |
| 707 | + } |
| 708 | + } |
| 709 | + |
| 710 | + if let box = source as? _SwiftValue { |
| 711 | + if let value = box.value as? T { |
| 712 | + result.initialize(to: value) |
| 713 | + return true |
| 714 | + } |
| 715 | + } else if let box = source as? _NSSwiftValue { |
| 716 | + if let value = box.value as? T { |
| 717 | + result.initialize(to: value) |
| 718 | + return true |
| 719 | + } |
| 720 | + } |
| 721 | + |
| 722 | + return false |
| 723 | +} |
| 724 | + |
| 725 | +// Internal stdlib SPI |
| 726 | +@_silgen_name("swift_swiftValueConformsTo") |
| 727 | +public func _swiftValueConformsTo<T>(_ type: T.Type) -> Bool { |
| 728 | + if let foundationType = _foundationSwiftValueType { |
| 729 | + return foundationType is T.Type |
| 730 | + } else { |
| 731 | + return _SwiftValue.self is T.Type |
| 732 | + } |
| 733 | +} |
| 734 | + |
| 735 | +@_silgen_name("_swift_extractDynamicValue") |
| 736 | +public func _extractDynamicValue<T>(_ value: T) -> AnyObject? |
| 737 | + |
| 738 | +@_silgen_name("_swift_bridgeToObjectiveCUsingProtocolIfPossible") |
| 739 | +public func _bridgeToObjectiveCUsingProtocolIfPossible<T>(_ value: T) -> AnyObject? |
| 740 | + |
| 741 | +@usableFromInline |
| 742 | +protocol _Unwrappable { |
| 743 | + func unwrap() -> Any? |
| 744 | +} |
| 745 | + |
| 746 | +extension Optional: _Unwrappable { |
| 747 | + func unwrap() -> Any? { |
| 748 | + return self |
| 749 | + } |
| 750 | +} |
| 751 | + |
| 752 | +private let _foundationSwiftValueType = _typeByName("Foundation._SwiftValue") as? _NSSwiftValue.Type |
| 753 | + |
| 754 | +@usableFromInline |
| 755 | +internal var _nullPlaceholder: AnyObject { |
| 756 | + if let foundationType = _foundationSwiftValueType { |
| 757 | + return foundationType.null |
| 758 | + } else { |
| 759 | + return _SwiftValue.null |
| 760 | + } |
| 761 | +} |
| 762 | + |
| 763 | +@usableFromInline |
| 764 | +func _makeSwiftValue(_ value: Any) -> AnyObject { |
| 765 | + if let foundationType = _foundationSwiftValueType { |
| 766 | + return foundationType.init(value) |
| 767 | + } else { |
| 768 | + return _SwiftValue(value) |
| 769 | + } |
| 770 | +} |
| 771 | + |
| 772 | +/// Bridge an arbitrary value to an Objective-C object. |
| 773 | +/// |
| 774 | +/// - If `T` is a class type, it is always bridged verbatim, the function |
| 775 | +/// returns `x`; |
| 776 | +/// |
| 777 | +/// - otherwise, if `T` conforms to `_ObjectiveCBridgeable`, |
| 778 | +/// returns the result of `x._bridgeToObjectiveC()`; |
| 779 | +/// |
| 780 | +/// - otherwise, we use **boxing** to bring the value into Objective-C. |
| 781 | +/// The value is wrapped in an instance of a private Objective-C class |
| 782 | +/// that is `id`-compatible and dynamically castable back to the type of |
| 783 | +/// the boxed value, but is otherwise opaque. |
| 784 | +/// |
| 785 | +/// COMPILER_INTRINSIC |
| 786 | +@inlinable // FIXME(sil-serialize-all) |
| 787 | +public func _bridgeAnythingToObjectiveC<T>(_ x: T) -> AnyObject { |
| 788 | + var done = false |
| 789 | + var result: AnyObject! |
| 790 | + |
| 791 | + var source: Any = x |
| 792 | + |
| 793 | + if let dynamicSource = _extractDynamicValue(x) { |
| 794 | + result = dynamicSource as AnyObject |
| 795 | + done = true |
| 796 | + } |
| 797 | + |
| 798 | + if !done, let wrapper = source as? _Unwrappable { |
| 799 | + if let value = wrapper.unwrap() { |
| 800 | + result = value as AnyObject |
| 801 | + } else { |
| 802 | + result = _nullPlaceholder |
| 803 | + } |
| 804 | + |
| 805 | + done = true |
| 806 | + } |
| 807 | + |
| 808 | + if !done { |
| 809 | + if type(of: source) as? AnyClass != nil { |
| 810 | + result = unsafeBitCast(x, to: AnyObject.self) |
| 811 | + } else if let object = _bridgeToObjectiveCUsingProtocolIfPossible(source) { |
| 812 | + result = object |
| 813 | + } else { |
| 814 | + result = _makeSwiftValue(source) |
| 815 | + } |
| 816 | + } |
| 817 | + |
| 818 | + return result |
| 819 | +} |
| 820 | + |
| 821 | +#endif // !_runtime(_ObjC) |
| 822 | + |
0 commit comments