Skip to content

Commit 7eff965

Browse files
committed
Implement CachedURLResponse.
Simple implementation for CachedURLResponse. The type seems to mostly be a data container with little behaviour. Implement the missing equality and hashing for URLResponse, which is used by CachedURLResponse. Implement tests for CachedURLResponse and the missing tests for equality and hashing in URLResponse.
1 parent 120f749 commit 7eff965

File tree

6 files changed

+427
-9
lines changed

6 files changed

+427
-9
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,7 @@ if(ENABLE_TESTING)
432432
TestFoundation/TestAffineTransform.swift
433433
TestFoundation/TestBundle.swift
434434
TestFoundation/TestByteCountFormatter.swift
435+
TestFoundation/TestCachedURLResponse.swift
435436
TestFoundation/TestCalendar.swift
436437
TestFoundation/TestCharacterSet.swift
437438
TestFoundation/TestCodable.swift

Foundation/URLCache.swift

Lines changed: 79 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,42 @@ extension URLCache {
4545
open class CachedURLResponse : NSObject, NSSecureCoding, NSCopying {
4646

4747
public required init?(coder aDecoder: NSCoder) {
48-
NSUnimplemented()
48+
guard aDecoder.allowsKeyedCoding else {
49+
/* Unkeyed unarchiving is not supported. */
50+
return nil
51+
}
52+
53+
guard let data = aDecoder.decodeObject(of: NSData.self, forKey: "Data") else {
54+
return nil
55+
}
56+
guard let response = aDecoder.decodeObject(of: URLResponse.self, forKey: "URLResponse") else {
57+
return nil
58+
}
59+
guard let storagePolicyValue = aDecoder.decodeObject(of: NSNumber.self, forKey: "StoragePolicy") else {
60+
return nil
61+
}
62+
guard let storagePolicy = URLCache.StoragePolicy(rawValue: storagePolicyValue.uintValue) else {
63+
return nil
64+
}
65+
let userInfo = aDecoder.decodeObject(of: NSDictionary.self, forKey: "UserInfo")
66+
67+
self.data = data as Data
68+
self.response = response
69+
self.storagePolicy = storagePolicy
70+
self.userInfo = userInfo?._swiftObject
4971
}
5072

5173
open func encode(with aCoder: NSCoder) {
52-
NSUnimplemented()
74+
guard aCoder.allowsKeyedCoding else {
75+
fatalError("We do not support saving to a non-keyed coder.")
76+
}
77+
78+
aCoder.encode(data as NSData, forKey: "Data")
79+
aCoder.encode(response, forKey: "URLResponse")
80+
aCoder.encode(NSNumber(value: storagePolicy.rawValue), forKey: "StoragePolicy")
81+
if let userInfo = userInfo {
82+
aCoder.encode(userInfo._nsObject, forKey: "UserInfo")
83+
}
5384
}
5485

5586
static public var supportsSecureCoding: Bool {
@@ -61,7 +92,7 @@ open class CachedURLResponse : NSObject, NSSecureCoding, NSCopying {
6192
}
6293

6394
open func copy(with zone: NSZone? = nil) -> Any {
64-
NSUnimplemented()
95+
return self
6596
}
6697

6798
/*!
@@ -76,7 +107,12 @@ open class CachedURLResponse : NSObject, NSSecureCoding, NSCopying {
76107
corresponding to the given response.
77108
@result an initialized CachedURLResponse.
78109
*/
79-
public init(response: URLResponse, data: Data) { NSUnimplemented() }
110+
public init(response: URLResponse, data: Data) {
111+
self.response = response.copy() as! URLResponse
112+
self.data = data
113+
self.userInfo = nil
114+
self.storagePolicy = .allowed
115+
}
80116

81117
/*!
82118
@method initWithResponse:data:userInfo:storagePolicy:
@@ -90,35 +126,69 @@ open class CachedURLResponse : NSObject, NSSecureCoding, NSCopying {
90126
@param storagePolicy an URLCache.StoragePolicy constant.
91127
@result an initialized CachedURLResponse.
92128
*/
93-
public init(response: URLResponse, data: Data, userInfo: [AnyHashable : Any]? = [:], storagePolicy: URLCache.StoragePolicy) { NSUnimplemented() }
129+
public init(response: URLResponse, data: Data, userInfo: [AnyHashable : Any]? = nil, storagePolicy: URLCache.StoragePolicy) {
130+
self.response = response.copy() as! URLResponse
131+
self.data = data
132+
self.userInfo = userInfo
133+
self.storagePolicy = storagePolicy
134+
}
94135

95136
/*!
96137
@method response
97138
@abstract Returns the response wrapped by this instance.
98139
@result The response wrapped by this instance.
99140
*/
100-
/*@NSCopying*/ open var response: URLResponse { NSUnimplemented() }
141+
/*@NSCopying*/ open private(set) var response: URLResponse
101142

102143
/*!
103144
@method data
104145
@abstract Returns the data of the receiver.
105146
@result The data of the receiver.
106147
*/
107-
/*@NSCopying*/ open var data: Data { NSUnimplemented() }
148+
/*@NSCopying*/ open private(set) var data: Data
108149

109150
/*!
110151
@method userInfo
111152
@abstract Returns the userInfo dictionary of the receiver.
112153
@result The userInfo dictionary of the receiver.
113154
*/
114-
open var userInfo: [AnyHashable : Any]? { NSUnimplemented() }
155+
open private(set) var userInfo: [AnyHashable : Any]?
115156

116157
/*!
117158
@method storagePolicy
118159
@abstract Returns the URLCache.StoragePolicy constant of the receiver.
119160
@result The URLCache.StoragePolicy constant of the receiver.
120161
*/
121-
open var storagePolicy: URLCache.StoragePolicy { NSUnimplemented() }
162+
open private(set) var storagePolicy: URLCache.StoragePolicy
163+
164+
open override func isEqual(_ value: Any?) -> Bool {
165+
switch value {
166+
case let other as CachedURLResponse:
167+
return self.isEqual(to: other)
168+
default:
169+
return false
170+
}
171+
}
172+
173+
private func isEqual(to other: CachedURLResponse) -> Bool {
174+
if self === other {
175+
return true
176+
}
177+
178+
// We cannot compare userInfo because of the values are Any, which
179+
// doesn't conform to Equatable.
180+
return self.response == other.response &&
181+
self.data == other.data &&
182+
self.storagePolicy == other.storagePolicy
183+
}
184+
185+
open override var hash: Int {
186+
var hasher = Hasher()
187+
hasher.combine(response)
188+
hasher.combine(data)
189+
hasher.combine(storagePolicy)
190+
return hasher.finalize()
191+
}
122192
}
123193

124194
open class URLCache : NSObject {

Foundation/URLResponse.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,35 @@ open class URLResponse : NSObject, NSSecureCoding, NSCopying {
133133
///
134134
/// This method always returns a valid filename.
135135
open fileprivate(set) var suggestedFilename: String?
136+
137+
open override func isEqual(_ value: Any?) -> Bool {
138+
switch value {
139+
case let other as URLResponse:
140+
return self.isEqual(to: other)
141+
default:
142+
return false
143+
}
144+
}
145+
146+
private func isEqual(to other: URLResponse) -> Bool {
147+
if self === other {
148+
return true
149+
}
150+
151+
return self.url == other.url &&
152+
self.expectedContentLength == other.expectedContentLength &&
153+
self.mimeType == other.mimeType &&
154+
self.textEncodingName == other.textEncodingName
155+
}
156+
157+
open override var hash: Int {
158+
var hasher = Hasher()
159+
hasher.combine(url)
160+
hasher.combine(expectedContentLength)
161+
hasher.combine(mimeType)
162+
hasher.combine(textEncodingName)
163+
return hasher.finalize()
164+
}
136165
}
137166

138167
/// A Response to an HTTP URL load.

0 commit comments

Comments
 (0)