mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-07 16:28:38 +09:00
149 lines
4.9 KiB
Swift
149 lines
4.9 KiB
Swift
/* 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 SwiftyJSON
|
|
|
|
// Our engine choices need to persist across server changes.
|
|
// Note that EngineConfiguration is not enough to evolve an existing meta/global:
|
|
// a meta/global generated from this will have different syncIDs and will
|
|
// always use this device's engine versions.
|
|
open class EngineConfiguration: Equatable {
|
|
let enabled: [String]
|
|
let declined: [String]
|
|
public init(enabled: [String], declined: [String]) {
|
|
self.enabled = enabled
|
|
self.declined = declined
|
|
}
|
|
|
|
open class func fromJSON(_ json: JSON) -> EngineConfiguration? {
|
|
if json.isError() {
|
|
return nil
|
|
}
|
|
if let enabled = jsonsToStrings(json["enabled"].array) {
|
|
if let declined = jsonsToStrings(json["declined"].array) {
|
|
return EngineConfiguration(enabled: enabled, declined: declined)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
open func toJSON() -> JSON {
|
|
let json: [String: AnyObject] = ["enabled": self.enabled as AnyObject, "declined": self.declined as AnyObject]
|
|
return JSON(json)
|
|
}
|
|
}
|
|
|
|
public func ==(lhs: EngineConfiguration, rhs: EngineConfiguration) -> Bool {
|
|
return Set(lhs.enabled) == Set(rhs.enabled)
|
|
}
|
|
|
|
extension EngineConfiguration: CustomStringConvertible {
|
|
public var description: String {
|
|
return "EngineConfiguration(enabled: \(self.enabled.sorted()), declined: \(self.declined.sorted()))"
|
|
}
|
|
}
|
|
|
|
// Equivalent to Android Sync's EngineSettings, but here
|
|
// we use them for meta/global itself.
|
|
public struct EngineMeta: Equatable {
|
|
let version: Int
|
|
let syncID: String
|
|
|
|
public static func fromJSON(_ json: JSON) -> EngineMeta? {
|
|
if let syncID = json["syncID"].string {
|
|
if let version = json["version"].int {
|
|
return EngineMeta(version: version, syncID: syncID)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
public static func mapFromJSON(_ map: [String: JSON]?) -> [String: EngineMeta]? {
|
|
if let map = map {
|
|
return optFilter(mapValues(map, f: EngineMeta.fromJSON))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
public func toJSON() -> JSON {
|
|
let json: [String: AnyObject] = ["version": self.version as AnyObject, "syncID": self.syncID as AnyObject]
|
|
return JSON(json)
|
|
}
|
|
}
|
|
|
|
public func ==(lhs: EngineMeta, rhs: EngineMeta) -> Bool {
|
|
return (lhs.version == rhs.version) && (lhs.syncID == rhs.syncID)
|
|
}
|
|
|
|
public struct MetaGlobal: Equatable {
|
|
let syncID: String
|
|
let storageVersion: Int
|
|
let engines: [String: EngineMeta]
|
|
let declined: [String]
|
|
|
|
// TODO: is it more useful to support partial globals?
|
|
// TODO: how do we return error states here?
|
|
public static func fromJSON(_ json: JSON) -> MetaGlobal? {
|
|
if json.isError() {
|
|
return nil
|
|
}
|
|
if let syncID = json["syncID"].string {
|
|
if let storageVersion = json["storageVersion"].int {
|
|
let engines = EngineMeta.mapFromJSON(json["engines"].dictionary) ?? [:]
|
|
let declined = json["declined"].array ?? []
|
|
return MetaGlobal(syncID: syncID,
|
|
storageVersion: storageVersion,
|
|
engines: engines,
|
|
declined: jsonsToStrings(declined) ?? [])
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
public func enginesPayload() -> JSON {
|
|
return JSON(mapValues(engines, f: { $0.toJSON() }))
|
|
}
|
|
|
|
// TODO: make a whole record JSON for this.
|
|
public func asPayload() -> CleartextPayloadJSON {
|
|
let json: JSON = JSON([
|
|
"syncID": self.syncID,
|
|
"storageVersion": self.storageVersion,
|
|
"engines": enginesPayload().dictionaryObject as Any,
|
|
"declined": self.declined
|
|
])
|
|
return CleartextPayloadJSON(json)
|
|
}
|
|
|
|
public func withSyncID(_ syncID: String) -> MetaGlobal {
|
|
return MetaGlobal(syncID: syncID, storageVersion: self.storageVersion, engines: self.engines, declined: self.declined)
|
|
}
|
|
|
|
public func engineConfiguration() -> EngineConfiguration {
|
|
return EngineConfiguration(enabled: Array(engines.keys), declined: declined)
|
|
}
|
|
}
|
|
|
|
public func ==(lhs: MetaGlobal, rhs: MetaGlobal) -> Bool {
|
|
return (lhs.syncID == rhs.syncID) &&
|
|
(lhs.storageVersion == rhs.storageVersion) &&
|
|
optArrayEqual(lhs.declined, rhs: rhs.declined) &&
|
|
optDictionaryEqual(lhs.engines, rhs: rhs.engines)
|
|
}
|
|
|
|
/**
|
|
* Encapsulates a meta/global, identity-derived keys, and keys.
|
|
*/
|
|
open class SyncMeta {
|
|
let syncKey: KeyBundle
|
|
|
|
var keys: Keys?
|
|
var global: MetaGlobal?
|
|
|
|
public init(syncKey: KeyBundle) {
|
|
self.syncKey = syncKey
|
|
}
|
|
}
|