Skip to content
This repository was archived by the owner on Jan 5, 2024. It is now read-only.

Commit 6cf1d47

Browse files
Merge pull request #56 from Andrea-Scuderi/master
Conform MockHTTPRoute to Codable
2 parents 6986eee + c8afb90 commit 6cf1d47

File tree

4 files changed

+688
-2
lines changed

4 files changed

+688
-2
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ profile
1818
DerivedData
1919
*.hmap
2020
*.ipa
21+
.build
2122

2223
# Bundler
2324
.bundle
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,310 @@
1+
// MockHTTPRoute+Codable.swift
2+
3+
import Foundation
4+
5+
extension MockHTTPMethod: Codable { }
6+
7+
extension MockHTTPRoute: Codable {
8+
9+
enum CodingKeys: String, CodingKey {
10+
case type
11+
case method
12+
case urlPath
13+
case code
14+
case filename
15+
case query
16+
case requestHeaders
17+
case responseHeaders
18+
case templateInfo
19+
case destination
20+
case routes
21+
case timeoutInSeconds
22+
}
23+
24+
enum MockHTTPRouteType: String, CodingKey, Codable {
25+
case simple
26+
case custom
27+
case template
28+
case redirect
29+
case collection
30+
case timeout
31+
}
32+
33+
public init(from decoder: Decoder) throws {
34+
let container = try decoder.container(keyedBy: CodingKeys.self)
35+
let type = try container.decode(MockHTTPRouteType.self, forKey: .type)
36+
switch type {
37+
case .simple:
38+
let method = try container.decode(MockHTTPMethod.self, forKey: .method)
39+
let urlPath = try container.decode(String.self, forKey: .urlPath)
40+
let code = try container.decode(Int.self, forKey: .code)
41+
let filename = try? container.decode(String.self, forKey: .filename)
42+
self = .simple(method: method, urlPath: urlPath, code: code, filename: filename)
43+
case .custom:
44+
let method = try container.decode(MockHTTPMethod.self, forKey: .method)
45+
let urlPath = try container.decode(String.self, forKey: .urlPath)
46+
let query = try container.decode([String: String].self, forKey: .query)
47+
let requestHeaders = try container.decode([String: String].self, forKey: .requestHeaders)
48+
let responseHeaders = try container.decode([String: String].self, forKey: .responseHeaders)
49+
let code = try container.decode(Int.self, forKey: .code)
50+
let filename = try? container.decode(String.self, forKey: .filename)
51+
self = .custom(method: method,
52+
urlPath: urlPath,
53+
query: query,
54+
requestHeaders: requestHeaders,
55+
responseHeaders: responseHeaders,
56+
code: code,
57+
filename: filename)
58+
case .template:
59+
let method = try container.decode(MockHTTPMethod.self, forKey: .method)
60+
let urlPath = try container.decode(String.self, forKey: .urlPath)
61+
let code = try container.decode(Int.self, forKey: .code)
62+
let filename = try? container.decode(String.self, forKey: .filename)
63+
let templateInfo = try container.decode([String: TemplateParameter].self, forKey: .templateInfo)
64+
self = .template(method: method,
65+
urlPath: urlPath,
66+
code: code,
67+
filename: filename,
68+
templateInfo: templateInfo)
69+
case .redirect:
70+
let urlPath = try container.decode(String.self, forKey: .urlPath)
71+
let destination = try container.decode(String.self, forKey: .destination)
72+
self = .redirect(urlPath: urlPath, destination: destination)
73+
case .timeout:
74+
let method = try container.decode(MockHTTPMethod.self, forKey: .method)
75+
let urlPath = try container.decode(String.self, forKey: .urlPath)
76+
let timeoutInSeconds = try container.decode(Int.self, forKey: .timeoutInSeconds)
77+
self = .timeout(method: method, urlPath: urlPath, timeoutInSeconds: timeoutInSeconds)
78+
case .collection:
79+
let routes = try container.decode([MockHTTPRoute].self, forKey: .routes)
80+
self = .collection(routes: routes)
81+
}
82+
}
83+
84+
public func encode(to encoder: Encoder) throws {
85+
var container = encoder.container(keyedBy: CodingKeys.self)
86+
switch self {
87+
case .simple(method: let method, urlPath: let urlPath, code: let code, filename: let filename):
88+
try container.encode(MockHTTPRouteType.simple.rawValue, forKey: .type)
89+
try container.encode(method, forKey: .method)
90+
try container.encode(urlPath, forKey: .urlPath)
91+
try container.encode(code, forKey: .code)
92+
try container.encode(filename, forKey: .filename)
93+
case .custom(method: let method,
94+
urlPath: let urlPath,
95+
query: let query,
96+
requestHeaders: let requestHeaders,
97+
responseHeaders: let responseHeaders,
98+
code: let code,
99+
filename: let filename):
100+
try container.encode(MockHTTPRouteType.custom.rawValue, forKey: .type)
101+
try container.encode(method, forKey: .method)
102+
try container.encode(urlPath, forKey: .urlPath)
103+
try container.encode(query, forKey: .query)
104+
try container.encode(requestHeaders, forKey: .requestHeaders)
105+
try container.encode(responseHeaders, forKey: .responseHeaders)
106+
try container.encode(code, forKey: .code)
107+
try container.encode(filename, forKey: .filename)
108+
case .template(method: let method,
109+
urlPath: let urlPath,
110+
code: let code,
111+
filename: let filename,
112+
templateInfo: let templateInfo):
113+
try container.encode(MockHTTPRouteType.template.rawValue, forKey: .type)
114+
try container.encode(method, forKey: .method)
115+
try container.encode(urlPath, forKey: .urlPath)
116+
try container.encode(code, forKey: .code)
117+
try container.encode(filename, forKey: .filename)
118+
try container.encode(TemplateParameter(with: templateInfo), forKey: .templateInfo)
119+
case .redirect(urlPath: let urlPath, destination: let destination):
120+
try container.encode(MockHTTPRouteType.redirect.rawValue, forKey: .type)
121+
try container.encode(urlPath, forKey: .urlPath)
122+
try container.encode(destination, forKey: .destination)
123+
case .collection(routes: let routes):
124+
try container.encode(MockHTTPRouteType.collection.rawValue, forKey: .type)
125+
try container.encode(routes, forKey: .routes)
126+
case .timeout(method: let method, urlPath: let urlPath, timeoutInSeconds: let timeoutInSeconds):
127+
try container.encode(MockHTTPRouteType.timeout.rawValue, forKey: .type)
128+
try container.encode(method, forKey: .method)
129+
try container.encode(urlPath, forKey: .urlPath)
130+
try container.encode(timeoutInSeconds, forKey: .timeoutInSeconds)
131+
}
132+
}
133+
}
134+
135+
enum TemplateParameter: Hashable {
136+
case `nil`
137+
case bool(Bool)
138+
case int(Int)
139+
case double(Double)
140+
case string(String)
141+
case array([TemplateParameter])
142+
case dictionary([String: TemplateParameter])
143+
144+
var value: AnyHashable? {
145+
switch self {
146+
case .nil:
147+
return nil
148+
case .bool(let bool):
149+
return bool
150+
case .int(let int):
151+
return int
152+
case .double(let double):
153+
return double
154+
case .string(let string):
155+
return string
156+
case .array(let array):
157+
return array
158+
case .dictionary(let dictionary):
159+
return dictionary
160+
}
161+
}
162+
163+
var string: String? {
164+
switch self {
165+
case .string(let value):
166+
return value
167+
default:
168+
return nil
169+
}
170+
}
171+
172+
var int: Int? {
173+
switch self {
174+
case .int(let value):
175+
return value
176+
default:
177+
return nil
178+
}
179+
}
180+
181+
var double: Double? {
182+
switch self {
183+
case .double(let value):
184+
return value
185+
default:
186+
return nil
187+
}
188+
}
189+
190+
var bool: Bool? {
191+
switch self {
192+
case .bool(let value):
193+
return value
194+
default:
195+
return nil
196+
}
197+
}
198+
199+
var array: [TemplateParameter]? {
200+
switch self {
201+
case .array(let value):
202+
return value
203+
default:
204+
return nil
205+
}
206+
}
207+
208+
var dictionary: [String: TemplateParameter]? {
209+
switch self {
210+
case .dictionary(let value):
211+
return value
212+
default:
213+
return nil
214+
}
215+
}
216+
217+
init(with value: AnyHashable) throws {
218+
if let string = value as? String {
219+
self = .string(string)
220+
return
221+
}
222+
if let bool = value as? Bool {
223+
self = .bool(bool)
224+
return
225+
}
226+
if let int = value as? Int {
227+
self = .int(int)
228+
return
229+
}
230+
if let double = value as? Double {
231+
self = .double(double)
232+
return
233+
}
234+
if let array = value as? [AnyHashable] {
235+
let list = try array.compactMap { try TemplateParameter(with: $0) }
236+
self = .array(list)
237+
return
238+
}
239+
if let dictionary = value as? [String: AnyHashable] {
240+
let dict = try dictionary.mapValues { try TemplateParameter(with: $0) }
241+
self = .dictionary(dict)
242+
return
243+
}
244+
if let _ = value as? NSNull {
245+
self = .nil
246+
return
247+
}
248+
throw CustomCodableError.unableToEncode
249+
}
250+
}
251+
252+
extension TemplateParameter: Codable {
253+
init(from decoder: Decoder) throws {
254+
let container = try decoder.singleValueContainer()
255+
guard !container.decodeNil() else {
256+
self = .nil
257+
return
258+
}
259+
if let value = try? container.decode(String.self) {
260+
self = .string(value)
261+
return
262+
}
263+
if let value = try? container.decode(Int.self) {
264+
self = .int(value)
265+
return
266+
}
267+
if let value = try? container.decode(Double.self) {
268+
self = .double(value)
269+
return
270+
}
271+
if let value = try? container.decode(Bool.self) {
272+
self = .bool(value)
273+
return
274+
}
275+
if let value = try? container.decode([String: TemplateParameter].self) {
276+
self = .dictionary(value)
277+
return
278+
}
279+
if let value = try? container.decode([TemplateParameter].self) {
280+
self = .array(value)
281+
return
282+
}
283+
throw CustomCodableError.unableToDecode
284+
}
285+
286+
func encode(to encoder: Encoder) throws {
287+
var container = encoder.singleValueContainer()
288+
switch self {
289+
case .nil:
290+
try container.encodeNil()
291+
case .bool(let bool):
292+
try container.encode(bool)
293+
case .int(let int):
294+
try container.encode(int)
295+
case .double(let double):
296+
try container.encode(double)
297+
case .string(let string):
298+
try container.encode(string)
299+
case .array(let array):
300+
try container.encode(array)
301+
case .dictionary(let dictionary):
302+
try container.encode(dictionary)
303+
}
304+
}
305+
}
306+
307+
private enum CustomCodableError: Error {
308+
case unableToDecode
309+
case unableToEncode
310+
}

0 commit comments

Comments
 (0)