| //===----------------------------------------------------------------------===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2017 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 |
| // |
| //===----------------------------------------------------------------------===// |
| |
| @_exported import Foundation // Clang module |
| |
| /// A class type which acts as a handle (pointer-to-pointer) to a Foundation reference type which has only a mutable class (e.g., NSURLComponents). |
| /// |
| /// Note: This assumes that the result of calling copy() is mutable. The documentation says that classes which do not have a mutable/immutable distinction should just adopt NSCopying instead of NSMutableCopying. |
| internal final class _MutableHandle<MutableType : NSObject> |
| where MutableType : NSCopying { |
| fileprivate var _pointer : MutableType |
| |
| init(reference : MutableType) { |
| _pointer = reference.copy() as! MutableType |
| } |
| |
| init(adoptingReference reference: MutableType) { |
| _pointer = reference |
| } |
| |
| /// Apply a closure to the reference type. |
| func map<ReturnType>(_ whatToDo : (MutableType) throws -> ReturnType) rethrows -> ReturnType { |
| return try whatToDo(_pointer) |
| } |
| |
| func _copiedReference() -> MutableType { |
| return _pointer.copy() as! MutableType |
| } |
| |
| func _uncopiedReference() -> MutableType { |
| return _pointer |
| } |
| } |
| |
| /// Describes common operations for Foundation struct types that are bridged to a mutable object (e.g. NSURLComponents). |
| internal protocol _MutableBoxing : ReferenceConvertible { |
| var _handle : _MutableHandle<ReferenceType> { get set } |
| |
| /// Apply a mutating closure to the reference type, regardless if it is mutable or immutable. |
| /// |
| /// This function performs the correct copy-on-write check for efficient mutation. |
| mutating func _applyMutation<ReturnType>(_ whatToDo : (ReferenceType) -> ReturnType) -> ReturnType |
| } |
| |
| extension _MutableBoxing { |
| @inline(__always) |
| mutating func _applyMutation<ReturnType>(_ whatToDo : (ReferenceType) -> ReturnType) -> ReturnType { |
| // Only create a new box if we are not uniquely referenced |
| if !isKnownUniquelyReferenced(&_handle) { |
| let ref = _handle._pointer |
| _handle = _MutableHandle(reference: ref) |
| } |
| return whatToDo(_handle._pointer) |
| } |
| } |
| |
| internal enum _MutableUnmanagedWrapper<ImmutableType : NSObject, MutableType : NSObject> |
| where MutableType : NSMutableCopying{ |
| case Immutable(Unmanaged<ImmutableType>) |
| case Mutable(Unmanaged<MutableType>) |
| } |