blob: 05fd53646df54c9c2439fbd2587fb8db8ea4a8cb [file] [log] [blame]
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
import CoreFoundation
public let NSCocoaErrorDomain: String = "NSCocoaErrorDomain"
public let NSPOSIXErrorDomain: String = "NSPOSIXErrorDomain"
public let NSOSStatusErrorDomain: String = "NSOSStatusErrorDomain"
public let NSMachErrorDomain: String = "NSMachErrorDomain"
public let NSUnderlyingErrorKey: String = "NSUnderlyingError"
public let NSLocalizedDescriptionKey: String = "NSLocalizedDescription"
public let NSLocalizedFailureReasonErrorKey: String = "NSLocalizedFailureReason"
public let NSLocalizedRecoverySuggestionErrorKey: String = "NSLocalizedRecoverySuggestion"
public let NSLocalizedRecoveryOptionsErrorKey: String = "NSLocalizedRecoveryOptions"
public let NSRecoveryAttempterErrorKey: String = "NSRecoveryAttempter"
public let NSHelpAnchorErrorKey: String = "NSHelpAnchor"
public let NSStringEncodingErrorKey: String = "NSStringEncodingErrorKey"
public let NSURLErrorKey: String = "NSURL"
public let NSFilePathErrorKey: String = "NSFilePathErrorKey"
public class NSError : NSObject, NSCopying, NSSecureCoding, NSCoding {
typealias CFType = CFError
internal var _cfObject: CFType {
return CFErrorCreate(kCFAllocatorSystemDefault, domain._cfObject, code, nil)
}
// ErrorType forbids this being internal
public var _domain: String
public var _code: Int
/// - Experiment: This is a draft API currently under consideration for official import into Foundation
/// - Note: This API differs from Darwin because it uses [String : Any] as a type instead of [String : AnyObject]. This allows the use of Swift value types.
private var _userInfo: [String : Any]?
/// - Experiment: This is a draft API currently under consideration for official import into Foundation
/// - Note: This API differs from Darwin because it uses [String : Any] as a type instead of [String : AnyObject]. This allows the use of Swift value types.
public init(domain: String, code: Int, userInfo dict: [String : Any]?) {
_domain = domain
_code = code
_userInfo = dict
}
public required init?(coder aDecoder: NSCoder) {
if aDecoder.allowsKeyedCoding {
_code = aDecoder.decodeIntegerForKey("NSCode")
_domain = aDecoder.decodeObjectOfClass(NSString.self, forKey: "NSDomain")!._swiftObject
if let info = aDecoder.decodeObjectOfClasses([NSSet.self, NSDictionary.self, NSArray.self, NSString.self, NSNumber.self, NSData.self, NSURL.self], forKey: "NSUserInfo") as? NSDictionary {
var filteredUserInfo = [String : Any]()
// user info must be filtered so that the keys are all strings
info.enumerateKeysAndObjectsUsingBlock() {
if let key = $0.0 as? NSString {
filteredUserInfo[key._swiftObject] = $0.1
}
}
_userInfo = filteredUserInfo
}
} else {
var codeValue: Int32 = 0
aDecoder.decodeValueOfObjCType("i", at: &codeValue)
_code = Int(codeValue)
_domain = (aDecoder.decodeObject() as? NSString)!._swiftObject
if let info = aDecoder.decodeObject() as? NSDictionary {
var filteredUserInfo = [String : Any]()
// user info must be filtered so that the keys are all strings
info.enumerateKeysAndObjectsUsingBlock() {
if let key = $0.0 as? NSString {
filteredUserInfo[key._swiftObject] = $0.1
}
}
_userInfo = filteredUserInfo
}
}
}
public static func supportsSecureCoding() -> Bool {
return true
}
public func encodeWithCoder(aCoder: NSCoder) {
if aCoder.allowsKeyedCoding {
aCoder.encodeObject(_domain.bridge(), forKey: "NSDomain")
aCoder.encodeInt(Int32(_code), forKey: "NSCode")
aCoder.encodeObject(_userInfo?.bridge(), forKey: "NSUserInfo")
} else {
var codeValue: Int32 = Int32(self._code)
aCoder.encodeValueOfObjCType("i", at: &codeValue)
aCoder.encodeObject(self._domain.bridge())
aCoder.encodeObject(self._userInfo?.bridge())
}
}
public override func copy() -> AnyObject {
return copyWithZone(nil)
}
public func copyWithZone(zone: NSZone) -> AnyObject {
return self
}
public var domain: String {
return _domain
}
public var code: Int {
return _code
}
/// - Experiment: This is a draft API currently under consideration for official import into Foundation
/// - Note: This API differs from Darwin because it uses [String : Any] as a type instead of [String : AnyObject]. This allows the use of Swift value types.
public var userInfo: [String : Any] {
if let info = _userInfo {
return info
} else {
return Dictionary<String, Any>()
}
}
public var localizedDescription: String {
let desc = userInfo[NSLocalizedDescriptionKey] as? String
return desc ?? "The operation could not be completed"
}
public var localizedFailureReason: String? {
return userInfo[NSLocalizedFailureReasonErrorKey] as? String
}
public var localizedRecoverySuggestion: String? {
return userInfo[NSLocalizedRecoverySuggestionErrorKey] as? String
}
public var localizedRecoveryOptions: [String]? {
return userInfo[NSLocalizedRecoveryOptionsErrorKey] as? [String]
}
public var recoveryAttempter: AnyObject? {
return userInfo[NSRecoveryAttempterErrorKey] as? AnyObject
}
public var helpAnchor: String? {
return userInfo[NSHelpAnchorErrorKey] as? String
}
internal typealias NSErrorProvider = (error: NSError, key: String) -> AnyObject?
internal static var userInfoProviders = [String: NSErrorProvider]()
public class func setUserInfoValueProviderForDomain(errorDomain: String, provider: ((NSError, String) -> AnyObject?)?) {
NSError.userInfoProviders[errorDomain] = provider
}
public class func userInfoValueProviderForDomain(errorDomain: String) -> ((NSError, String) -> AnyObject?)? {
return NSError.userInfoProviders[errorDomain]
}
}
extension NSError : ErrorProtocol { }
extension NSError : _CFBridgable { }
extension CFError : _NSBridgable {
typealias NSType = NSError
internal var _nsObject: NSType {
let userInfo = CFErrorCopyUserInfo(self)._swiftObject
var newUserInfo: [String: Any] = [:]
for (key, value) in userInfo {
if let key = key as? NSString {
newUserInfo[key._swiftObject] = value
}
}
return NSError(domain: CFErrorGetDomain(self)._swiftObject, code: CFErrorGetCode(self), userInfo: newUserInfo)
}
}
public protocol _ObjectTypeBridgeableErrorType : ErrorProtocol {
init?(_bridgedNSError: NSError)
}
public protocol __BridgedNSError : RawRepresentable, ErrorProtocol {
static var __NSErrorDomain: String { get }
}
@warn_unused_result
public func ==<T: __BridgedNSError where T.RawValue: SignedInteger>(lhs: T, rhs: T) -> Bool {
return lhs.rawValue.toIntMax() == rhs.rawValue.toIntMax()
}
public extension __BridgedNSError where RawValue: SignedInteger {
public final var _domain: String { return Self.__NSErrorDomain }
public final var _code: Int { return Int(rawValue.toIntMax()) }
public init?(rawValue: RawValue) {
self = unsafeBitCast(rawValue, to: Self.self)
}
public init?(_bridgedNSError: NSError) {
if _bridgedNSError.domain != Self.__NSErrorDomain {
return nil
}
self.init(rawValue: RawValue(IntMax(_bridgedNSError.code)))
}
public final var hashValue: Int { return _code }
}
@warn_unused_result
public func ==<T: __BridgedNSError where T.RawValue: UnsignedInteger>(lhs: T, rhs: T) -> Bool {
return lhs.rawValue.toUIntMax() == rhs.rawValue.toUIntMax()
}
public extension __BridgedNSError where RawValue: UnsignedInteger {
public final var _domain: String { return Self.__NSErrorDomain }
public final var _code: Int {
return Int(bitPattern: UInt(rawValue.toUIntMax()))
}
public init?(rawValue: RawValue) {
self = unsafeBitCast(rawValue, to: Self.self)
}
public init?(_bridgedNSError: NSError) {
if _bridgedNSError.domain != Self.__NSErrorDomain {
return nil
}
self.init(rawValue: RawValue(UIntMax(UInt(_bridgedNSError.code))))
}
public final var hashValue: Int { return _code }
}
public protocol _BridgedNSError : __BridgedNSError, Hashable {
// TODO: Was _NSErrorDomain, but that caused a module error.
static var __NSErrorDomain: String { get }
}