/
Response.swift
152 lines (114 loc) · 3.68 KB
/
Response.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
//
// Created by Vladimir Burdukov on 5/17/16.
// Copyright © 2016 NetcoSports. All rights reserved.
//
import Foundation
public protocol BaseModel {
static func model(with data: Data, atPath path: String?) throws -> Self
static func models(with data: Data, atPath path: String?) throws -> [Self]
static func optionalModels(with data: Data, atPath path: String?) throws -> [Self?]
}
public protocol Result {
associatedtype ModelType: BaseModel
init(data: Data, atPath path: String?) throws
}
public protocol NonOptionalResult: Result { }
public protocol OptionalResult: Result {
static func empty() -> Self
}
public protocol Single: Result { }
public protocol Multiple: Result { }
public struct SingleResult<T: BaseModel>: Single, NonOptionalResult {
public typealias ModelType = T
public let model: ModelType
public init(data: Data, atPath path: String?) throws {
self.model = try T.model(with: data, atPath: path)
}
}
public struct SingleOptionalResult<T: BaseModel>: Single, OptionalResult {
public typealias ModelType = T
public let model: ModelType?
public init(data: Data, atPath path: String?) {
do {
self.model = try T.model(with: data, atPath: path)
} catch {
self.model = nil
Gnomon.errorLog("\(error)")
}
}
private init() {
model = nil
}
public static func empty() -> SingleOptionalResult {
return SingleOptionalResult()
}
}
public struct MultipleResults<T: BaseModel>: Multiple, NonOptionalResult {
public typealias ModelType = T
public let models: [ModelType]
public init(data: Data, atPath path: String?) throws {
self.init(models: try T.models(with: data, atPath: path))
}
public init(models: [ModelType]) {
self.models = models
}
}
public struct MultipleOptionalResults<T: BaseModel>: Multiple, OptionalResult {
public typealias ModelType = T
public let models: [ModelType?]
public init(data: Data, atPath path: String?) {
do {
self.init(models: try T.optionalModels(with: data, atPath: path))
} catch {
Gnomon.errorLog("\(error)")
self.init(models: [])
}
}
public init(models: [ModelType?]) {
self.models = models
}
public static func empty() -> MultipleOptionalResults {
return MultipleOptionalResults(models: [])
}
}
public enum ResponseType {
case localCache, httpCache, regular
}
public struct Response<ResultType: Result> {
public let result: ResultType
public let responseType: ResponseType
public let headers: [String: String]
public let statusCode: Int
}
public extension Response where ResultType: OptionalResult {
public static func empty(with responseType: ResponseType) -> Response<ResultType> {
return Response(result: .empty(), responseType: responseType, headers: [:], statusCode: 200)
}
}
public protocol StringModel: BaseModel {
init(with string: String)
static var encoding: String.Encoding { get }
}
public extension StringModel {
static func model(with data: Data, atPath path: String?) throws -> Self {
if path != nil {
Gnomon.errorLog("StringModel doesn't support xpath")
}
guard let string = String(data: data, encoding: Self.encoding) else {
throw "can't parse String from received data"
}
return Self(with: string)
}
static func models(with data: Data, atPath path: String?) throws -> [Self] {
throw "StringModel doesn't support multiple models parsing"
}
static func optionalModels(with data: Data, atPath path: String?) throws -> [Self?] {
throw "StringModel doesn't support multiple models parsing"
}
}
extension String: StringModel {
public init(with string: String) {
self = string
}
public static var encoding: String.Encoding { return .utf8 }
}