Skip to content

Commit a6e23cf

Browse files
drodriguezmillenomi
authored andcommitted
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 42b387c commit a6e23cf

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
@@ -443,6 +443,7 @@ if(ENABLE_TESTING)
443443
TestFoundation/TestAffineTransform.swift
444444
TestFoundation/TestBundle.swift
445445
TestFoundation/TestByteCountFormatter.swift
446+
TestFoundation/TestCachedURLResponse.swift
446447
TestFoundation/TestCalendar.swift
447448
TestFoundation/TestCharacterSet.swift
448449
TestFoundation/TestCodable.swift

Foundation/URLCache.swift

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

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

5678
open func encode(with aCoder: NSCoder) {
57-
NSUnimplemented()
79+
guard aCoder.allowsKeyedCoding else {
80+
fatalError("We do not support saving to a non-keyed coder.")
81+
}
82+
83+
aCoder.encode(data as NSData, forKey: "Data")
84+
aCoder.encode(response, forKey: "URLResponse")
85+
aCoder.encode(NSNumber(value: storagePolicy.rawValue), forKey: "StoragePolicy")
86+
if let userInfo = userInfo {
87+
aCoder.encode(userInfo._nsObject, forKey: "UserInfo")
88+
}
5889
}
5990

6091
static public var supportsSecureCoding: Bool {
@@ -66,7 +97,7 @@ open class CachedURLResponse : NSObject, NSSecureCoding, NSCopying {
6697
}
6798

6899
open func copy(with zone: NSZone? = nil) -> Any {
69-
NSUnimplemented()
100+
return self
70101
}
71102

72103
/*!
@@ -81,7 +112,12 @@ open class CachedURLResponse : NSObject, NSSecureCoding, NSCopying {
81112
corresponding to the given response.
82113
@result an initialized CachedURLResponse.
83114
*/
84-
public init(response: URLResponse, data: Data) { NSUnimplemented() }
115+
public init(response: URLResponse, data: Data) {
116+
self.response = response.copy() as! URLResponse
117+
self.data = data
118+
self.userInfo = nil
119+
self.storagePolicy = .allowed
120+
}
85121

86122
/*!
87123
@method initWithResponse:data:userInfo:storagePolicy:
@@ -95,35 +131,69 @@ open class CachedURLResponse : NSObject, NSSecureCoding, NSCopying {
95131
@param storagePolicy an URLCache.StoragePolicy constant.
96132
@result an initialized CachedURLResponse.
97133
*/
98-
public init(response: URLResponse, data: Data, userInfo: [AnyHashable : Any]? = [:], storagePolicy: URLCache.StoragePolicy) { NSUnimplemented() }
134+
public init(response: URLResponse, data: Data, userInfo: [AnyHashable : Any]? = nil, storagePolicy: URLCache.StoragePolicy) {
135+
self.response = response.copy() as! URLResponse
136+
self.data = data
137+
self.userInfo = userInfo
138+
self.storagePolicy = storagePolicy
139+
}
99140

100141
/*!
101142
@method response
102143
@abstract Returns the response wrapped by this instance.
103144
@result The response wrapped by this instance.
104145
*/
105-
/*@NSCopying*/ open var response: URLResponse { NSUnimplemented() }
146+
/*@NSCopying*/ open private(set) var response: URLResponse
106147

107148
/*!
108149
@method data
109150
@abstract Returns the data of the receiver.
110151
@result The data of the receiver.
111152
*/
112-
/*@NSCopying*/ open var data: Data { NSUnimplemented() }
153+
/*@NSCopying*/ open private(set) var data: Data
113154

114155
/*!
115156
@method userInfo
116157
@abstract Returns the userInfo dictionary of the receiver.
117158
@result The userInfo dictionary of the receiver.
118159
*/
119-
open var userInfo: [AnyHashable : Any]? { NSUnimplemented() }
160+
open private(set) var userInfo: [AnyHashable : Any]?
120161

121162
/*!
122163
@method storagePolicy
123164
@abstract Returns the URLCache.StoragePolicy constant of the receiver.
124165
@result The URLCache.StoragePolicy constant of the receiver.
125166
*/
126-
open var storagePolicy: URLCache.StoragePolicy { NSUnimplemented() }
167+
open private(set) var storagePolicy: URLCache.StoragePolicy
168+
169+
open override func isEqual(_ value: Any?) -> Bool {
170+
switch value {
171+
case let other as CachedURLResponse:
172+
return self.isEqual(to: other)
173+
default:
174+
return false
175+
}
176+
}
177+
178+
private func isEqual(to other: CachedURLResponse) -> Bool {
179+
if self === other {
180+
return true
181+
}
182+
183+
// We cannot compare userInfo because of the values are Any, which
184+
// doesn't conform to Equatable.
185+
return self.response == other.response &&
186+
self.data == other.data &&
187+
self.storagePolicy == other.storagePolicy
188+
}
189+
190+
open override var hash: Int {
191+
var hasher = Hasher()
192+
hasher.combine(response)
193+
hasher.combine(data)
194+
hasher.combine(storagePolicy)
195+
return hasher.finalize()
196+
}
127197
}
128198

129199
open class URLCache : NSObject {

Foundation/URLResponse.swift

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

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

0 commit comments

Comments
 (0)