-
Notifications
You must be signed in to change notification settings - Fork 3k
/
Copy pathRecord.swift
98 lines (82 loc) · 3.09 KB
/
Record.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
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import Foundation
import Shared
import XCGLogger
private let log = Logger.syncLogger
let ONE_YEAR_IN_SECONDS = 365 * 24 * 60 * 60
/**
* Immutable representation for Sync records.
*
* Envelopes consist of:
* Required: "id", "collection", "payload".
* Optional: "modified", "sortindex", "ttl".
*
* Deletedness is a property of the payload.
*/
open class Record<T: CleartextPayloadJSON> {
open let id: String
open let payload: T
open let modified: Timestamp
open let sortindex: Int
open let ttl: Int? // Seconds. Can be null, which means 'don't expire'.
// This is a hook for decryption.
// Right now it only parses the string. In subclasses, it'll parse the
// string, decrypt the contents, and return the data as a JSON object.
// From the docs:
//
// payload none string 256k
// A string containing a JSON structure encapsulating the data of the record.
// This structure is defined separately for each WBO type.
// Parts of the structure may be encrypted, in which case the structure
// should also specify a record for decryption.
//
// @seealso EncryptedRecord.
open class func payloadFromPayloadString(_ envelope: EnvelopeJSON, payload: String) -> T? {
return T(payload)
}
// TODO: consider using error tuples.
open class func fromEnvelope(_ envelope: EnvelopeJSON, payloadFactory: (String) -> T?) -> Record<T>? {
if !(envelope.isValid()) {
log.error("Invalid envelope.")
return nil
}
guard let payload = payloadFactory(envelope.payload) else {
log.error("Unable to parse payload.")
return nil
}
if !payload.isValid() {
log.error("Invalid payload \(envelope.payload).")
return nil
}
return Record<T>(envelope: envelope, payload: payload)
}
/**
* Accepts an envelope and a decrypted payload.
* Inputs are not validated. Use `fromEnvelope` above.
*/
convenience init(envelope: EnvelopeJSON, payload: T) {
// TODO: modified, sortindex, ttl
self.init(id: envelope.id, payload: payload, modified: envelope.modified, sortindex: envelope.sortindex)
}
init(id: GUID, payload: T, modified: Timestamp = Timestamp(time(nil)), sortindex: Int = 0, ttl: Int? = nil) {
self.id = id
self.payload = payload
self.modified = modified
self.sortindex = sortindex
self.ttl = ttl
}
func equalIdentifiers(_ rec: Record) -> Bool {
return rec.id == self.id
}
// Override me.
func equalPayloads(_ rec: Record) -> Bool {
return equalIdentifiers(rec) && rec.payload.deleted == self.payload.deleted
}
func equals(_ rec: Record) -> Bool {
return rec.sortindex == self.sortindex &&
rec.modified == self.modified &&
equalPayloads(rec)
}
}