| //===----------------------------------------------------------------------===// |
| // |
| // 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 |
| import CoreGraphics |
| |
| //===----------------------------------------------------------------------===// |
| // Numbers |
| //===----------------------------------------------------------------------===// |
| |
| @_silgen_name("_swift_Foundation_TypePreservingNSNumberGetKind") |
| internal func _swift_Foundation_TypePreservingNSNumberGetKind( |
| _ value: NSNumber |
| ) -> UInt8 |
| |
| // This enum has a matching counterpart in TypePreservingNSNumber.mm. Please |
| // update both copies when changing it. |
| internal enum _SwiftTypePreservingNSNumberTag : UInt8 { |
| case SwiftInt = 0 |
| case SwiftInt64 = 1 |
| case SwiftInt32 = 2 |
| case SwiftInt16 = 3 |
| case SwiftInt8 = 4 |
| case SwiftUInt = 5 |
| case SwiftUInt64 = 6 |
| case SwiftUInt32 = 7 |
| case SwiftUInt16 = 8 |
| case SwiftUInt8 = 9 |
| case SwiftFloat = 10 |
| case SwiftDouble = 11 |
| case SwiftCGFloat = 12 |
| case SwiftBool = 13 |
| } |
| |
| // Conversions between NSNumber and various numeric types. The |
| // conversion to NSNumber is automatic (auto-boxing), while conversion |
| // back to a specific numeric type requires a cast. |
| |
| %{ |
| # The set of types we bridge to NSNumber using a Swift-type-preserving |
| # subclass. Note that this doesn't include Bool or CGFloat, which require |
| # special handling. |
| bridgedNumberTypes = [ |
| ('Int', 'int'), |
| ('Int64', 'int64'), |
| ('Int32', 'int32'), |
| ('Int16', 'int16'), |
| ('Int8', 'int8'), |
| ('UInt', 'uint'), |
| ('UInt64', 'uint64'), |
| ('UInt32', 'uint32'), |
| ('UInt16', 'uint16'), |
| ('UInt8', 'uint8'), |
| ('Float', 'float'), |
| ('Double', 'double'), |
| ] |
| }% |
| |
| % for NumberType, accessorName in bridgedNumberTypes: |
| |
| @_silgen_name("_swift_Foundation_TypePreservingNSNumberWith${NumberType}") |
| internal func _swift_Foundation_TypePreservingNSNumberWith${NumberType}( |
| _ value: ${NumberType} |
| ) -> NSNumber |
| |
| @_silgen_name("_swift_Foundation_TypePreservingNSNumberGetAs${NumberType}") |
| internal func _swift_Foundation_TypePreservingNSNumberGetAs${NumberType}( |
| _ value: NSNumber |
| ) -> ${NumberType} |
| |
| extension ${NumberType} : _ObjectiveCBridgeable { |
| public init(_ number: NSNumber) { |
| self = number.${accessorName}Value |
| } |
| |
| @_semantics("convertToObjectiveC") |
| public func _bridgeToObjectiveC() -> NSNumber { |
| return _swift_Foundation_TypePreservingNSNumberWith${NumberType}(self) |
| } |
| |
| public static func _forceBridgeFromObjectiveC( |
| _ x: NSNumber, |
| result: inout ${NumberType}? |
| ) { |
| // If the NSNumber instance preserved its Swift type, we only want to allow |
| // the cast if the type matches. |
| if let tag = _SwiftTypePreservingNSNumberTag(rawValue: |
| _swift_Foundation_TypePreservingNSNumberGetKind(x)) { |
| precondition(tag == .Swift${NumberType}, |
| "NSNumber does not contain right type to be cast to ${NumberType}") |
| } |
| |
| result = x.${accessorName}Value |
| } |
| |
| public static func _conditionallyBridgeFromObjectiveC( |
| _ x: NSNumber, |
| result: inout ${NumberType}? |
| ) -> Bool { |
| // If the NSNumber instance preserved its Swift type, we only want to allow |
| // the cast if the type matches. |
| if let tag = _SwiftTypePreservingNSNumberTag(rawValue: |
| _swift_Foundation_TypePreservingNSNumberGetKind(x)), |
| tag != .Swift${NumberType} { |
| result = nil |
| return false |
| } |
| |
| result = x.${accessorName}Value |
| return true |
| } |
| |
| public static func _unconditionallyBridgeFromObjectiveC( |
| _ source: NSNumber? |
| ) -> ${NumberType} { |
| let unwrappedSource = source! |
| |
| // If the NSNumber instance preserved its Swift type, we only want to allow |
| // the cast if the type matches. |
| if let tag = _SwiftTypePreservingNSNumberTag(rawValue: |
| _swift_Foundation_TypePreservingNSNumberGetKind(unwrappedSource)) { |
| precondition(tag == .Swift${NumberType}, |
| "NSNumber does not contain right type to be cast to ${NumberType}") |
| } |
| |
| return unwrappedSource.${accessorName}Value |
| } |
| } |
| % end |
| |
| // Cocoa's implementation of NSNumber already preserves the type of Bool |
| // values by producing a CFBoolean instance instead of a CFNumber instance |
| // under the hood. Property list and JSON serialization in Foundation rely |
| // on -[NSNumber numberWithBool:] producing the correct implementation- |
| // internal subclass to know when to serialize as a boolean instead of a |
| // number, so implement Bool's bridging in terms of the standard NSNumber |
| // interfaces. |
| extension Bool: _ObjectiveCBridgeable { |
| public init(_ number: NSNumber) { |
| self = number.boolValue |
| } |
| |
| @_semantics("convertToObjectiveC") |
| public func _bridgeToObjectiveC() -> NSNumber { |
| return NSNumber(value: self) |
| } |
| |
| public static func _forceBridgeFromObjectiveC( |
| _ x: NSNumber, |
| result: inout Bool? |
| ) { |
| // If the NSNumber instance preserved its Swift type, we only want to allow |
| // the cast if the type matches. |
| if let tag = _SwiftTypePreservingNSNumberTag(rawValue: |
| _swift_Foundation_TypePreservingNSNumberGetKind(x)) { |
| precondition(tag == .SwiftBool, |
| "NSNumber does not contain right type to be cast to Bool") |
| } |
| |
| result = x.boolValue |
| } |
| |
| public static func _conditionallyBridgeFromObjectiveC( |
| _ x: NSNumber, |
| result: inout Bool? |
| ) -> Bool { |
| // If the NSNumber instance preserved its Swift type, we only want to allow |
| // the cast if the type matches. |
| if let tag = _SwiftTypePreservingNSNumberTag(rawValue: |
| _swift_Foundation_TypePreservingNSNumberGetKind(x)), |
| tag != .SwiftBool { |
| result = nil |
| return false |
| } |
| |
| result = x.boolValue |
| return true |
| } |
| |
| public static func _unconditionallyBridgeFromObjectiveC( |
| _ source: NSNumber? |
| ) -> Bool { |
| let unwrappedSource = source! |
| |
| // If the NSNumber instance preserved its Swift type, we only want to allow |
| // the cast if the type matches. |
| if let tag = _SwiftTypePreservingNSNumberTag(rawValue: |
| _swift_Foundation_TypePreservingNSNumberGetKind(unwrappedSource)) { |
| precondition(tag == .SwiftBool, |
| "NSNumber does not contain right type to be cast to Bool") |
| } |
| |
| return unwrappedSource.boolValue |
| } |
| } |
| |
| // CGFloat bridging. |
| |
| @_silgen_name("_swift_Foundation_TypePreservingNSNumberWithCGFloat") |
| internal func _swift_Foundation_TypePreservingNSNumberWithCGFloat( |
| _ value: CGFloat |
| ) -> NSNumber |
| |
| @_silgen_name("_swift_Foundation_TypePreservingNSNumberGetAsCGFloat") |
| internal func _swift_Foundation_TypePreservingNSNumberGetAsCGFloat( |
| _ value: NSNumber |
| ) -> CGFloat |
| |
| extension CGFloat : _ObjectiveCBridgeable { |
| public init(_ number: NSNumber) { |
| self.native = CGFloat.NativeType(number) |
| } |
| |
| @_semantics("convertToObjectiveC") |
| public func _bridgeToObjectiveC() -> NSNumber { |
| return _swift_Foundation_TypePreservingNSNumberWithCGFloat(self) |
| } |
| |
| public static func _forceBridgeFromObjectiveC( |
| _ x: NSNumber, |
| result: inout CGFloat? |
| ) { |
| // If the NSNumber instance preserved its Swift type, we only want to allow |
| // the cast if the type matches. |
| if let tag = _SwiftTypePreservingNSNumberTag(rawValue: |
| _swift_Foundation_TypePreservingNSNumberGetKind(x)) { |
| precondition(tag == .SwiftCGFloat, |
| "NSNumber does not contain right type to be cast to CGFloat") |
| } |
| |
| result = CGFloat(x) |
| } |
| |
| public static func _conditionallyBridgeFromObjectiveC( |
| _ x: NSNumber, |
| result: inout CGFloat? |
| ) -> Bool { |
| // If the NSNumber instance preserved its Swift type, we only want to allow |
| // the cast if the type matches. |
| if let tag = _SwiftTypePreservingNSNumberTag(rawValue: |
| _swift_Foundation_TypePreservingNSNumberGetKind(x)), |
| tag != .SwiftCGFloat { |
| result = nil |
| return false |
| } |
| |
| result = CGFloat(x) |
| return true |
| } |
| |
| public static func _unconditionallyBridgeFromObjectiveC( |
| _ source: NSNumber? |
| ) -> CGFloat { |
| let unwrappedSource = source! |
| |
| // If the NSNumber instance preserved its Swift type, we only want to allow |
| // the cast if the type matches. |
| if let tag = _SwiftTypePreservingNSNumberTag(rawValue: |
| _swift_Foundation_TypePreservingNSNumberGetKind(unwrappedSource)) { |
| precondition(tag == .SwiftCGFloat, |
| "NSNumber does not contain right type to be cast to CGFloat") |
| } |
| |
| return CGFloat(unwrappedSource) |
| } |
| } |
| |
| // Literal support for NSNumber |
| extension NSNumber |
| : ExpressibleByFloatLiteral, |
| ExpressibleByIntegerLiteral, |
| ExpressibleByBooleanLiteral |
| { |
| /// Create an instance initialized to `value`. |
| @nonobjc |
| public required convenience init(integerLiteral value: Int) { |
| self.init(value: value) |
| } |
| |
| /// Create an instance initialized to `value`. |
| @nonobjc |
| public required convenience init(floatLiteral value: Double) { |
| self.init(value: value) |
| } |
| |
| /// Create an instance initialized to `value`. |
| @nonobjc |
| public required convenience init(booleanLiteral value: Bool) { |
| self.init(value: value) |
| } |
| } |
| |
| extension NSNumber : _HasCustomAnyHashableRepresentation { |
| // Must be @nonobjc to prevent infinite recursion trying to bridge |
| // AnyHashable to NSObject. |
| @nonobjc |
| public func _toCustomAnyHashable() -> AnyHashable? { |
| guard let kind = _SwiftTypePreservingNSNumberTag( |
| rawValue: _swift_Foundation_TypePreservingNSNumberGetKind(self) |
| ) else { |
| if let nsDecimalNumber: NSDecimalNumber = self as? NSDecimalNumber { |
| return AnyHashable(nsDecimalNumber as Decimal) |
| } |
| return nil |
| } |
| switch kind { |
| % for NumberType, _ in bridgedNumberTypes: |
| case .Swift${NumberType}: |
| return AnyHashable(_swift_Foundation_TypePreservingNSNumberGetAs${NumberType}(self)) |
| % end |
| case .SwiftCGFloat: |
| return AnyHashable(_swift_Foundation_TypePreservingNSNumberGetAsCGFloat(self)) |
| case .SwiftBool: |
| return AnyHashable(self.boolValue) |
| } |
| } |
| } |