ApiResult.swift 4.25 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
//
//  Result.swift
//  Pods
//
//  Created by Mauro Bender on 14/8/16.
//
//

import Alamofire

public enum ApiResult<Value> {
12
13
	case success(Value)
	case failure(ApiError)
14
15
16
17
	
	/// Returns `true` if the result is a success, `false` otherwise.
	public var isSuccess: Bool {
		switch self {
18
		case .success:
19
			return true
20
		case .failure:
21
22
23
24
25
26
27
28
29
30
31
32
			return false
		}
	}
	
	/// Returns `true` if the result is a failure, `false` otherwise.
	public var isFailure: Bool {
		return !isSuccess
	}
	
	/// Returns the associated value if the result is a success, `nil` otherwise.
	public var value: Value? {
		switch self {
33
		case .success(let value):
34
			return value
35
		case .failure:
36
37
38
39
40
41
42
			return nil
		}
	}
	
	/// Returns the associated error value if the result is a failure, `nil` otherwise.
	public var error: ApiError? {
		switch self {
43
		case .success:
44
			return nil
45
		case .failure(let error):
46
47
48
49
50
51
			return error
		}
	}
}

public enum EmptyResult {
52
53
	case success
	case failure(ApiError)
54
55
56
57
	
	/// Returns `true` if the result is a success, `false` otherwise.
	public var isSuccess: Bool {
		switch self {
58
		case .success:
59
			return true
60
		case .failure:
61
62
63
64
65
66
67
68
69
70
71
72
			return false
		}
	}
	
	/// Returns `true` if the result is a failure, `false` otherwise.
	public var isFailure: Bool {
		return !isSuccess
	}
	
	/// Returns the associated error value if the result is a failure, `nil` otherwise.
	public var error: ApiError? {
		switch self {
73
		case .success:
74
			return nil
75
		case .failure(let error):
76
77
78
79
80
81
82
83
84
85
86
87
			return error
		}
	}
}

// MARK: - CustomStringConvertible

extension ApiResult: CustomStringConvertible {
	/// The textual representation used when written to an output stream, which includes whether the result was a
	/// success or failure.
	public var description: String {
		switch self {
88
		case .success:
89
			return "SUCCESS"
90
		case .failure:
91
92
93
94
95
96
97
98
99
100
			return "FAILURE"
		}
	}
}

extension ApiResult: CustomDebugStringConvertible {
	/// The debug textual representation used when written to an output stream, which includes whether the result was a
	/// success or failure in addition to the value or error.
	public var debugDescription: String {
		switch self {
101
		case .success(let value):
102
			return "SUCCESS: \(value)"
103
		case .failure(let error):
104
105
106
107
108
109
110
111
			return "FAILURE: \(error)"
		}
	}
}

// MARK: Factories

// FIXME: Encapsulate
112
113
114
115
116
117
118
119
func resultJSON (_ responseData: Any?, keyPath: String?) -> Any? {
	guard let keyPath = keyPath else { return responseData }
	guard let responseData = responseData as? [String: Any] else { return nil }
	
	return responseData[ keyPath ];
}

public func itemResult<T: JSONSerializable>( _ response: DataResponse<Any>,
120
121
122
                       keyPath: String? ) -> ApiResult< T? >
{
	switch(response.result) {
123
124
125
	case .success(let JSON):
		if let itemJSON = resultJSON(JSON, keyPath: keyPath) as? [String : AnyObject] {
			return .success( T( fromJSON: itemJSON ) )
126
		} else {
127
			return .success( nil )
128
		}
129
130
	case .failure(_):
		return .failure( ApiError( response: response ) )
131
132
133
134
	}
}


135
public func emptyResult( _ response: DataResponse<Any> ) -> EmptyResult {
136
	switch(response.result) {
137
138
139
140
	case .success:
		return .success
	case .failure(_):
		return .failure( ApiError( response: response ) )
141
142
143
	}
}

144
public func listResult<T: JSONSerializable>( _ response: DataResponse<Any>,
145
146
147
                       keyPath: String? ) -> ApiResult< [T]? >
{
	switch(response.result) {
148
149
	case .success(let JSON):
		if let listJSON = resultJSON(JSON, keyPath: keyPath) as? [[String : AnyObject]] {
150
			let list = listJSON.map { T( fromJSON: $0 ) }
151
			return .success( list )
152
		} else {
153
			return .success( nil )
154
		}
155
156
	case .failure(_):
		return .failure( ApiError( response: response ) )
157
158
159
160
	}
}


161
public func paginatedListResult<T: JSONSerializable>( _ response: DataResponse<Any>,
162
163
164
								  keyPath: String?, paginationKeyPath: String? ) -> ApiResult< ([T], Pagination)? >
{
	switch(response.result) {
165
166
167
	case .success(let JSON):
		if let listJSON = resultJSON(JSON, keyPath: keyPath) as? [[String : AnyObject]],
			let paginationJSON = resultJSON(JSON, keyPath: paginationKeyPath) as? [String : AnyObject]
168
169
170
		{
			let list       = listJSON.map { T( fromJSON: $0 ) }
			let pagination = Pagination( fromJSON: paginationJSON )
171
			return .success( (list, pagination) )
172
		} else {
173
			return .success( nil )
174
		}
175
176
	case .failure(_):
		return .failure( ApiError( response: response ) )
177
178
	}
}