//===----------------------------------------------------------------------===// // // 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) } } }