@@ -1740,6 +1740,10 @@ public protocol UnkeyedDecodingContainer {
1740
1740
/// A container that can support the storage and direct encoding of a single
1741
1741
/// non-keyed value.
1742
1742
public protocol SingleValueEncodingContainer {
1743
+ /// The path of coding keys taken to get to this point in encoding.
1744
+ /// A `nil` value indicates an unkeyed container.
1745
+ var codingPath : [ CodingKey ? ] { get }
1746
+
1743
1747
/// Encodes a null value.
1744
1748
///
1745
1749
/// - throws: `EncodingError.invalidValue` if a null value is invalid in the current context for this format.
@@ -1854,6 +1858,10 @@ public protocol SingleValueEncodingContainer {
1854
1858
1855
1859
/// A `SingleValueDecodingContainer` is a container which can support the storage and direct decoding of a single non-keyed value.
1856
1860
public protocol SingleValueDecodingContainer {
1861
+ /// The path of coding keys taken to get to this point in encoding.
1862
+ /// A `nil` value indicates an unkeyed container.
1863
+ var codingPath : [ CodingKey ? ] { get }
1864
+
1857
1865
/// Decodes a null value.
1858
1866
///
1859
1867
/// - returns: Whether the encountered value was null.
@@ -2026,20 +2034,63 @@ public enum EncodingError : Error {
2026
2034
/// A description of what went wrong, for debugging purposes.
2027
2035
public let debugDescription : String
2028
2036
2037
+ /// The underlying error which caused this error, if any.
2038
+ public let underlyingError : Error ?
2039
+
2029
2040
/// Initializes `self` with the given path of `CodingKey`s and a description of what went wrong.
2030
2041
///
2031
2042
/// - parameter codingPath: The path of `CodingKey`s taken to get to the point of the failing encode call.
2032
2043
/// - parameter debugDescription: A description of what went wrong, for debugging purposes.
2033
- public init ( codingPath: [ CodingKey ? ] , debugDescription: String ) {
2044
+ /// - parameter underlyingError: The underlying error which caused this error, if any.
2045
+ public init ( codingPath: [ CodingKey ? ] , debugDescription: String , underlyingError: Error ? = nil ) {
2034
2046
self . codingPath = codingPath
2035
2047
self . debugDescription = debugDescription
2048
+ self . underlyingError = underlyingError
2036
2049
}
2037
2050
}
2038
2051
2039
2052
/// `.invalidValue` indicates that an `Encoder` or its containers could not encode the given value.
2040
2053
///
2041
2054
/// Contains the attempted value, along with context for debugging.
2042
2055
case invalidValue( Any , Context )
2056
+
2057
+ // MARK: - NSError Bridging
2058
+
2059
+ // CustomNSError bridging applies only when the CustomNSError conformance is applied in the same module as the declared error type.
2060
+ // Since we cannot access CustomNSError (which is defined in Foundation) from here, we can use the "hidden" entry points.
2061
+
2062
+ public var _domain : String {
2063
+ return " NSCocoaErrorDomain "
2064
+ }
2065
+
2066
+ public var _code : Int {
2067
+ switch self {
2068
+ case . invalidValue( _, _) : return 4866
2069
+ }
2070
+ }
2071
+
2072
+ public var _userInfo : AnyObject ? {
2073
+ // The error dictionary must be returned as an AnyObject. We can do this only on platforms with bridging, unfortunately.
2074
+ #if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
2075
+ let context : Context
2076
+ switch self {
2077
+ case . invalidValue( _, let c) : context = c
2078
+ }
2079
+
2080
+ var userInfo : [ String : Any ] = [
2081
+ " NSCodingPath " : context. codingPath,
2082
+ " NSDebugDescription " : context. debugDescription
2083
+ ]
2084
+
2085
+ if let underlyingError = context. underlyingError {
2086
+ userInfo [ " NSUnderlyingError " ] = underlyingError
2087
+ }
2088
+
2089
+ return userInfo as AnyObject
2090
+ #else
2091
+ return nil
2092
+ #endif
2093
+ }
2043
2094
}
2044
2095
2045
2096
/// An error that occurs during the decoding of a value.
@@ -2052,13 +2103,18 @@ public enum DecodingError : Error {
2052
2103
/// A description of what went wrong, for debugging purposes.
2053
2104
public let debugDescription : String
2054
2105
2106
+ /// The underlying error which caused this error, if any.
2107
+ public let underlyingError : Error ?
2108
+
2055
2109
/// Initializes `self` with the given path of `CodingKey`s and a description of what went wrong.
2056
2110
///
2057
2111
/// - parameter codingPath: The path of `CodingKey`s taken to get to the point of the failing decode call.
2058
2112
/// - parameter debugDescription: A description of what went wrong, for debugging purposes.
2059
- public init ( codingPath: [ CodingKey ? ] , debugDescription: String ) {
2113
+ /// - parameter underlyingError: The underlying error which caused this error, if any.
2114
+ public init ( codingPath: [ CodingKey ? ] , debugDescription: String , underlyingError: Error ? = nil ) {
2060
2115
self . codingPath = codingPath
2061
2116
self . debugDescription = debugDescription
2117
+ self . underlyingError = underlyingError
2062
2118
}
2063
2119
}
2064
2120
@@ -2081,6 +2137,91 @@ public enum DecodingError : Error {
2081
2137
///
2082
2138
/// Contains context for debugging.
2083
2139
case dataCorrupted( Context )
2140
+
2141
+ // MARK: - NSError Bridging
2142
+
2143
+ // CustomNSError bridging applies only when the CustomNSError conformance is applied in the same module as the declared error type.
2144
+ // Since we cannot access CustomNSError (which is defined in Foundation) from here, we can use the "hidden" entry points.
2145
+
2146
+ public var _domain : String {
2147
+ return " NSCocoaErrorDomain "
2148
+ }
2149
+
2150
+ public var _code : Int {
2151
+ switch self {
2152
+ case . keyNotFound( _, _) : fallthrough
2153
+ case . valueNotFound( _, _) : return 4865
2154
+ case . typeMismatch( _, _) : fallthrough
2155
+ case . dataCorrupted( _) : return 4864
2156
+ }
2157
+ }
2158
+
2159
+ public var _userInfo : AnyObject ? {
2160
+ // The error dictionary must be returned as an AnyObject. We can do this only on platforms with bridging, unfortunately.
2161
+ #if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
2162
+ let context : Context
2163
+ switch self {
2164
+ case . keyNotFound( _, let c) : context = c
2165
+ case . valueNotFound( _, let c) : context = c
2166
+ case . typeMismatch( _, let c) : context = c
2167
+ case . dataCorrupted( let c) : context = c
2168
+ }
2169
+
2170
+ var userInfo : [ String : Any ] = [
2171
+ " NSCodingPath " : context. codingPath,
2172
+ " NSDebugDescription " : context. debugDescription
2173
+ ]
2174
+
2175
+ if let underlyingError = context. underlyingError {
2176
+ userInfo [ " NSUnderlyingError " ] = underlyingError
2177
+ }
2178
+
2179
+ return userInfo as AnyObject
2180
+ #else
2181
+ return nil
2182
+ #endif
2183
+ }
2184
+ }
2185
+
2186
+ // The following extensions allow for easier error construction.
2187
+
2188
+ public extension DecodingError {
2189
+ /// A convenience method which creates a new .dataCorrupted error using a constructed coding path and the given debug description.
2190
+ ///
2191
+ /// Constructs a coding path by appending the given key to the given container's coding path.
2192
+ ///
2193
+ /// - param key: The key which caused the failure.
2194
+ /// - param container: The container in which the corrupted data was accessed.
2195
+ /// - param debugDescription: A description of the error to aid in debugging.
2196
+ static func dataCorruptedError< C : KeyedDecodingContainerProtocol > ( forKey key: C . Key , in container: C , debugDescription: String ) -> DecodingError {
2197
+ let context = DecodingError . Context ( codingPath: container. codingPath + [ key] ,
2198
+ debugDescription: debugDescription)
2199
+ return . dataCorrupted( context)
2200
+ }
2201
+
2202
+ /// A convenience method which creates a new .dataCorrupted error using a constructed coding path and the given debug description.
2203
+ ///
2204
+ /// Constructs a coding path by appending a nil key to the given container's coding path.
2205
+ ///
2206
+ /// - param container: The container in which the corrupted data was accessed.
2207
+ /// - param debugDescription: A description of the error to aid in debugging.
2208
+ static func dataCorruptedError( in container: UnkeyedDecodingContainer , debugDescription: String ) -> DecodingError {
2209
+ let context = DecodingError . Context ( codingPath: container. codingPath + [ nil ] ,
2210
+ debugDescription: debugDescription)
2211
+ return . dataCorrupted( context)
2212
+ }
2213
+
2214
+ /// A convenience method which creates a new .dataCorrupted error using a constructed coding path and the given debug description.
2215
+ ///
2216
+ /// Uses the given container's coding path as the constructed path.
2217
+ ///
2218
+ /// - param container: The container in which the corrupted data was accessed.
2219
+ /// - param debugDescription: A description of the error to aid in debugging.
2220
+ static func dataCorruptedError( in container: SingleValueDecodingContainer , debugDescription: String ) -> DecodingError {
2221
+ let context = DecodingError . Context ( codingPath: container. codingPath,
2222
+ debugDescription: debugDescription)
2223
+ return . dataCorrupted( context)
2224
+ }
2084
2225
}
2085
2226
2086
2227
//===----------------------------------------------------------------------===//
0 commit comments