-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathEquatableTuple.swift
61 lines (55 loc) · 2.19 KB
/
EquatableTuple.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
//
// EquatableTuple.swift
//
//
// Created by Joel Saltzman on 5/24/21.
//
import Foundation
/// A helper struct for when you have the same types of inputs of a Context.
/// If your inputs of a Context have different types, you can use a CodableTuple.
/// We want Equatable inputs so that we can use the `wasCalled` helpers.
public struct EquatableTuple<Input: Equatable>: Equatable {
public let inputs: [Input]
public init(_ inputs: [Input]) {
self.inputs = inputs
}
}
extension EquatableTuple where Input == CodableInput {
public init<RawType: Codable>(encoding rawValues: [RawType]) throws {
self.inputs = try rawValues.map({ try CodableInput($0) })
}
}
/// When the inputs of a Context have different types, you can use CodableTuple to encode each input.
/// When the mock tries to call getValue() it can decode the Inputs and use their values.
/// We want Equatable inputs so that we can use the `wasCalled` helpers.
public struct CodableInput: Equatable, Codable {
/// The encoded data of the represented Value
public let data: Data
public let description: String
public init<Value: Codable>(_ rawValue: Value) throws {
self.data = try JSONEncoder().encode(rawValue)
if case Optional<Any>.none = rawValue as Any {
self.description = "nil"
} else if case Optional<Any>.some(let value) = rawValue as Any {
self.description = String(describing: value)
} else {
self.description = String(describing: rawValue)
}
}
public init<Value: Any>(anyValue rawValue: Value?) throws {
if let value = rawValue {
self.data = try JSONSerialization.data(withJSONObject: value as Any, options: [])
self.description = String(describing: value)
} else {
self.data = Data()
self.description = "nil"
}
}
public func decode<Value: Codable>() throws -> Value {
return try JSONDecoder().decode(Value.self, from: data)
}
public func decode<Value: Any>() throws -> Value? {
guard data.count > 0 else { return nil }
return try JSONSerialization.jsonObject(with: data, options: []) as? Value
}
}