mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-02-25 00:55:09 +01:00
check correct queue for managed object value access
This commit is contained in:
@@ -430,6 +430,10 @@
|
||||
B5A5F2681CAEC50F004AB9AF /* CSSelect.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A5F2651CAEC50F004AB9AF /* CSSelect.swift */; };
|
||||
B5A5F2691CAEC50F004AB9AF /* CSSelect.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A5F2651CAEC50F004AB9AF /* CSSelect.swift */; };
|
||||
B5A5F26A1CAEC50F004AB9AF /* CSSelect.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A5F2651CAEC50F004AB9AF /* CSSelect.swift */; };
|
||||
B5A991EC1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A991EB1E9DC2CE0091A2E3 /* VersionLock.swift */; };
|
||||
B5A991ED1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A991EB1E9DC2CE0091A2E3 /* VersionLock.swift */; };
|
||||
B5A991EE1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A991EB1E9DC2CE0091A2E3 /* VersionLock.swift */; };
|
||||
B5A991EF1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A991EB1E9DC2CE0091A2E3 /* VersionLock.swift */; };
|
||||
B5AEFAB51C9962AE00AD137F /* CoreStoreBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5AEFAB41C9962AE00AD137F /* CoreStoreBridge.swift */; };
|
||||
B5AEFAB61C9962AE00AD137F /* CoreStoreBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5AEFAB41C9962AE00AD137F /* CoreStoreBridge.swift */; };
|
||||
B5AEFAB71C9962AE00AD137F /* CoreStoreBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5AEFAB41C9962AE00AD137F /* CoreStoreBridge.swift */; };
|
||||
@@ -752,6 +756,7 @@
|
||||
B59FA0AD1CCBAC95007C9BCA /* ICloudStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ICloudStore.swift; sourceTree = "<group>"; };
|
||||
B5A261201B64BFDB006EB6D3 /* MigrationType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationType.swift; sourceTree = "<group>"; };
|
||||
B5A5F2651CAEC50F004AB9AF /* CSSelect.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSSelect.swift; sourceTree = "<group>"; };
|
||||
B5A991EB1E9DC2CE0091A2E3 /* VersionLock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VersionLock.swift; sourceTree = "<group>"; };
|
||||
B5AD60CD1C90141E00F2B2E8 /* Package.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = SOURCE_ROOT; };
|
||||
B5AEFAB41C9962AE00AD137F /* CoreStoreBridge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreBridge.swift; sourceTree = "<group>"; };
|
||||
B5BDC91A1C202269008147CD /* Cartfile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Cartfile; path = ../Cartfile; sourceTree = "<group>"; };
|
||||
@@ -1134,6 +1139,7 @@
|
||||
B5D339E61E9493A500C880DE /* Entity.swift */,
|
||||
B5D33A001E96012400C880DE /* Relationship.swift */,
|
||||
B5D339E11E948C3600C880DE /* Value.swift */,
|
||||
B5A991EB1E9DC2CE0091A2E3 /* VersionLock.swift */,
|
||||
);
|
||||
path = "Dynamic Models";
|
||||
sourceTree = "<group>";
|
||||
@@ -1785,6 +1791,7 @@
|
||||
B549F65E1E569C7400FBAB2D /* QueryableAttributeType.swift in Sources */,
|
||||
B5E84F211AFF84860064E85B /* CoreStore+Observing.swift in Sources */,
|
||||
B559CD431CAA8B6300E4D58B /* CSSetupResult.swift in Sources */,
|
||||
B5A991EC1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */,
|
||||
B5FE4DA71C84FB4400FA6A91 /* InMemoryStore.swift in Sources */,
|
||||
B52F743D1E9B8724005F3DAC /* DynamicSchema.swift in Sources */,
|
||||
B5ECDBEC1CA6BF2000C7F112 /* CSFrom.swift in Sources */,
|
||||
@@ -1956,6 +1963,7 @@
|
||||
B549F65F1E569C7400FBAB2D /* QueryableAttributeType.swift in Sources */,
|
||||
B559CD451CAA8B6300E4D58B /* CSSetupResult.swift in Sources */,
|
||||
82BA18B81C4BBD4200A0916E /* ClauseTypes.swift in Sources */,
|
||||
B5A991ED1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */,
|
||||
B5ECDBEE1CA6BF2000C7F112 /* CSFrom.swift in Sources */,
|
||||
B52F743E1E9B8724005F3DAC /* DynamicSchema.swift in Sources */,
|
||||
82BA18D61C4BBD7100A0916E /* NSManagedObjectContext+Transaction.swift in Sources */,
|
||||
@@ -2127,6 +2135,7 @@
|
||||
B549F6611E569C7400FBAB2D /* QueryableAttributeType.swift in Sources */,
|
||||
B52DD19B1BE1F92800949AFE /* CoreStoreLogger.swift in Sources */,
|
||||
B52DD1991BE1F92800949AFE /* DefaultLogger.swift in Sources */,
|
||||
B5A991EF1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */,
|
||||
B5220E201D130813009BC71E /* CSObjectMonitor.swift in Sources */,
|
||||
B52F74401E9B8724005F3DAC /* DynamicSchema.swift in Sources */,
|
||||
B5220E171D1306DF009BC71E /* UnsafeDataTransaction+Observing.swift in Sources */,
|
||||
@@ -2298,6 +2307,7 @@
|
||||
B549F6601E569C7400FBAB2D /* QueryableAttributeType.swift in Sources */,
|
||||
B559CD461CAA8B6300E4D58B /* CSSetupResult.swift in Sources */,
|
||||
B56321A61BD65216006C9394 /* MigrationType.swift in Sources */,
|
||||
B5A991EE1E9DC2CE0091A2E3 /* VersionLock.swift in Sources */,
|
||||
B5ECDBEF1CA6BF2000C7F112 /* CSFrom.swift in Sources */,
|
||||
B52F743F1E9B8724005F3DAC /* DynamicSchema.swift in Sources */,
|
||||
B56321B41BD6521C006C9394 /* NSManagedObjectContext+Transaction.swift in Sources */,
|
||||
|
||||
@@ -39,7 +39,7 @@ class Dog: Animal {
|
||||
|
||||
let nickname = Value.Optional<String>("nickname")
|
||||
let age = Value.Required<Int>("age", default: 1)
|
||||
let friends = Relationship.ToManyUnordered<Dog>("friends")
|
||||
let friends = Relationship.ToManyOrdered<Dog>("friends")
|
||||
let friends2 = Relationship.ToManyUnordered<Dog>("friends2", inverse: { $0.friends })
|
||||
}
|
||||
|
||||
@@ -63,6 +63,11 @@ class DynamicModelTests: BaseTestDataTestCase {
|
||||
Entity<Animal>("Animal"),
|
||||
Entity<Dog>("Dog"),
|
||||
Entity<Person>("Person")
|
||||
],
|
||||
versionLock: [
|
||||
"Animal": [0x2698c812ebbc3b97, 0x751e3fa3f04cf9, 0x51fd460d3babc82, 0x92b4ba735b5a3053],
|
||||
"Dog": [0x5285f8e3aff69199, 0x62c3291b59f2ec7c, 0xbe5a571397a4117b, 0x97fb40f5b79ffbdc],
|
||||
"Person": [0xae4060a59f990ef0, 0x8ac83a6e1411c130, 0xa29fea58e2e38ab6, 0x2071bb7e33d77887]
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
@@ -31,12 +31,29 @@ import CoreData
|
||||
|
||||
internal extension NSManagedObject {
|
||||
|
||||
@nonobjc
|
||||
internal func isRunningInAllowedQueue() -> Bool? {
|
||||
|
||||
guard let context = self.managedObjectContext else {
|
||||
|
||||
return nil
|
||||
}
|
||||
if context.isTransactionContext {
|
||||
|
||||
return context.parentTransaction?.isRunningInAllowedQueue()
|
||||
}
|
||||
if context.isDataStackContext {
|
||||
|
||||
return Thread.isMainThread
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// TODO: test before release (rolled back)
|
||||
// @nonobjc
|
||||
// internal static func cs_swizzleMethodsForLogging() {
|
||||
//
|
||||
//
|
||||
// struct Static {
|
||||
//
|
||||
//
|
||||
// static let isSwizzled = Static.swizzle()
|
||||
//
|
||||
// private static func swizzle() -> Bool {
|
||||
|
||||
@@ -997,6 +997,54 @@ extension Where: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||
}
|
||||
|
||||
|
||||
// MARK: - VersionLock
|
||||
|
||||
extension VersionLock: CustomStringConvertible, CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||
|
||||
// MARK: CustomStringConvertible
|
||||
|
||||
public var description: String {
|
||||
|
||||
var string = "["
|
||||
if self.hashesByEntityName.isEmpty {
|
||||
|
||||
string.append(":]")
|
||||
return string
|
||||
}
|
||||
for (index, keyValue) in self.hashesByEntityName.enumerated() {
|
||||
|
||||
let data = keyValue.value
|
||||
let count = data.count
|
||||
let bytes = data.withUnsafeBytes { (pointer: UnsafePointer<HashElement>) in
|
||||
|
||||
return (0 ..< (count / MemoryLayout<HashElement>.size))
|
||||
.map({ "\("0x\(String(pointer[$0], radix: 16, uppercase: false))")" })
|
||||
}
|
||||
string.append("\(index == 0 ? "\n" : ",\n")\"\(keyValue.key)\": [\(bytes.joined(separator: ", "))]")
|
||||
}
|
||||
string.indent(1)
|
||||
string.append("\n]")
|
||||
return string
|
||||
}
|
||||
|
||||
|
||||
// MARK: CustomDebugStringConvertible
|
||||
|
||||
public var debugDescription: String {
|
||||
|
||||
return formattedDebugDescription(self)
|
||||
}
|
||||
|
||||
|
||||
// MARK: CoreStoreDebugStringConvertible
|
||||
|
||||
public var coreStoreDumpString: String {
|
||||
|
||||
return self.description
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - XcodeDataModel
|
||||
|
||||
extension XcodeDataModel: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
|
||||
|
||||
@@ -31,23 +31,16 @@ import Foundation
|
||||
|
||||
public final class CoreStoreSchema: DynamicSchema {
|
||||
|
||||
public convenience init(modelVersion: String, _ entity: DynamicEntity, _ entities: DynamicEntity...) {
|
||||
public convenience init(modelVersion: String, entities: [DynamicEntity], versionLock: VersionLock? = nil) {
|
||||
|
||||
self.init(
|
||||
modelVersion: modelVersion,
|
||||
entities: [entity] + entities
|
||||
entitiesByConfiguration: [DataStack.defaultConfigurationName: entities],
|
||||
versionLock: versionLock
|
||||
)
|
||||
}
|
||||
|
||||
public convenience init(modelVersion: String, entities: [DynamicEntity]) {
|
||||
|
||||
self.init(
|
||||
modelVersion: modelVersion,
|
||||
entitiesByConfiguration: [DataStack.defaultConfigurationName: entities]
|
||||
)
|
||||
}
|
||||
|
||||
public required init(modelVersion: String, entitiesByConfiguration: [String: [DynamicEntity]]) {
|
||||
public required init(modelVersion: String, entitiesByConfiguration: [String: [DynamicEntity]], versionLock: VersionLock? = nil) {
|
||||
|
||||
var actualEntitiesByConfiguration: [String: Set<AnyEntity>] = [:]
|
||||
for (configuration, entities) in entitiesByConfiguration {
|
||||
@@ -58,7 +51,7 @@ public final class CoreStoreSchema: DynamicSchema {
|
||||
actualEntitiesByConfiguration[DataStack.defaultConfigurationName] = allEntities
|
||||
|
||||
CoreStore.assert(
|
||||
autoreleasepool {
|
||||
cs_lazy {
|
||||
|
||||
let expectedCount = allEntities.count
|
||||
return Set(allEntities.map({ ObjectIdentifier($0.type) })).count == expectedCount
|
||||
@@ -70,6 +63,23 @@ public final class CoreStoreSchema: DynamicSchema {
|
||||
self.modelVersion = modelVersion
|
||||
self.entitiesByConfiguration = actualEntitiesByConfiguration
|
||||
self.allEntities = allEntities
|
||||
|
||||
if let versionLock = versionLock {
|
||||
|
||||
CoreStore.assert(
|
||||
versionLock == VersionLock(entityVersionHashesByName: self.rawModel().entityVersionHashesByName),
|
||||
"A \(cs_typeName(VersionLock.self)) was provided for the \(cs_typeName(CoreStoreSchema.self)) with version \"\(modelVersion)\", but the actual hashes do not match. This may result in unwanted migrations or unusable persistent stores.\nExpected lock values: \(versionLock)\nActual lock values: \(VersionLock(entityVersionHashesByName: self.rawModel().entityVersionHashesByName))"
|
||||
)
|
||||
}
|
||||
else {
|
||||
|
||||
#if DEBUG
|
||||
CoreStore.log(
|
||||
.notice,
|
||||
message: "These are hashes for the \(cs_typeName(CoreStoreSchema.self)) with version name \"\(modelVersion)\". Copy the dictionary below and pass it to the \(cs_typeName(CoreStoreSchema.self)) initializer's \"versionLock\" argument:\n\(VersionLock(entityVersionHashesByName: self.rawModel().entityVersionHashesByName))"
|
||||
)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -43,8 +43,7 @@ public struct Entity<O: CoreStoreObject>: DynamicEntity, Hashable {
|
||||
|
||||
public init(_ entityName: String) {
|
||||
|
||||
self.type = O.self
|
||||
self.entityName = entityName
|
||||
self.init(O.self, entityName)
|
||||
}
|
||||
|
||||
public init(_ type: O.Type, _ entityName: String) {
|
||||
@@ -54,29 +53,6 @@ public struct Entity<O: CoreStoreObject>: DynamicEntity, Hashable {
|
||||
}
|
||||
|
||||
|
||||
// MARK: - VersionHash
|
||||
|
||||
public struct VersionHash: ExpressibleByArrayLiteral {
|
||||
|
||||
let hash: Data
|
||||
|
||||
public init(_ hash: Data) {
|
||||
|
||||
self.hash = hash
|
||||
}
|
||||
|
||||
|
||||
// MARK: ExpressibleByArrayLiteral
|
||||
|
||||
public typealias Element = UInt8
|
||||
|
||||
public init(arrayLiteral elements: UInt8...) {
|
||||
|
||||
self.hash = Data(bytes: elements)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: DynamicEntity
|
||||
|
||||
public let type: CoreStoreObject.Type
|
||||
|
||||
@@ -84,6 +84,10 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
|
||||
get {
|
||||
|
||||
CoreStore.assert(
|
||||
self.accessRawObject().isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
return self.accessRawObject()
|
||||
.getValue(
|
||||
forKvcKey: self.keyPath,
|
||||
@@ -92,6 +96,10 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
}
|
||||
set {
|
||||
|
||||
CoreStore.assert(
|
||||
self.accessRawObject().isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
self.accessRawObject()
|
||||
.setValue(
|
||||
newValue,
|
||||
@@ -175,6 +183,10 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
|
||||
get {
|
||||
|
||||
CoreStore.assert(
|
||||
self.accessRawObject().isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
return self.accessRawObject()
|
||||
.getValue(
|
||||
forKvcKey: self.keyPath,
|
||||
@@ -190,6 +202,10 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
}
|
||||
set {
|
||||
|
||||
CoreStore.assert(
|
||||
self.accessRawObject().isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
self.accessRawObject()
|
||||
.setValue(
|
||||
newValue,
|
||||
@@ -279,6 +295,10 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
|
||||
get {
|
||||
|
||||
CoreStore.assert(
|
||||
self.accessRawObject().isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
return self.accessRawObject()
|
||||
.getValue(
|
||||
forKvcKey: self.keyPath,
|
||||
@@ -294,6 +314,10 @@ public enum RelationshipContainer<O: CoreStoreObject> {
|
||||
}
|
||||
set {
|
||||
|
||||
CoreStore.assert(
|
||||
self.accessRawObject().isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
self.accessRawObject()
|
||||
.setValue(
|
||||
newValue,
|
||||
|
||||
@@ -31,6 +31,9 @@ import Foundation
|
||||
|
||||
public final class SchemaHistory: ExpressibleByArrayLiteral {
|
||||
|
||||
|
||||
// MARK: -
|
||||
|
||||
public let currentModelVersion: ModelVersion
|
||||
public let migrationChain: MigrationChain
|
||||
|
||||
@@ -157,6 +160,7 @@ public final class SchemaHistory: ExpressibleByArrayLiteral {
|
||||
CoreStore.abort("Could not resolve the \(cs_typeName(SchemaHistory.self)) current model version because the \(cs_typeName(MigrationChain.self)) have ambiguous leaf versions: \(candidateVersions)")
|
||||
}
|
||||
}
|
||||
|
||||
self.schemaByVersion = schemaByVersion
|
||||
self.migrationChain = migrationChain
|
||||
self.currentModelVersion = currentModelVersion
|
||||
|
||||
@@ -70,6 +70,10 @@ public enum ValueContainer<O: CoreStoreObject> {
|
||||
|
||||
get {
|
||||
|
||||
CoreStore.assert(
|
||||
self.accessRawObject().isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
return self.accessRawObject()
|
||||
.getValue(
|
||||
forKvcKey: self.keyPath,
|
||||
@@ -78,6 +82,10 @@ public enum ValueContainer<O: CoreStoreObject> {
|
||||
}
|
||||
set {
|
||||
|
||||
CoreStore.assert(
|
||||
self.accessRawObject().isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
self.accessRawObject()
|
||||
.setValue(
|
||||
newValue,
|
||||
@@ -139,6 +147,10 @@ public enum ValueContainer<O: CoreStoreObject> {
|
||||
|
||||
get {
|
||||
|
||||
CoreStore.assert(
|
||||
self.accessRawObject().isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
return self.accessRawObject()
|
||||
.getValue(
|
||||
forKvcKey: self.keyPath,
|
||||
@@ -147,6 +159,10 @@ public enum ValueContainer<O: CoreStoreObject> {
|
||||
}
|
||||
set {
|
||||
|
||||
CoreStore.assert(
|
||||
self.accessRawObject().isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(cs_typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
self.accessRawObject()
|
||||
.setValue(
|
||||
newValue,
|
||||
|
||||
89
Sources/Setup/Dynamic Models/VersionLock.swift
Normal file
89
Sources/Setup/Dynamic Models/VersionLock.swift
Normal file
@@ -0,0 +1,89 @@
|
||||
//
|
||||
// VersionLock.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2017 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
// MARK: - VersionLock
|
||||
|
||||
public struct VersionLock: ExpressibleByDictionaryLiteral, Equatable {
|
||||
|
||||
public typealias HashElement = UInt64
|
||||
|
||||
public let hashesByEntityName: [EntityName: Data]
|
||||
|
||||
public init(_ intArrayByEntityName: [EntityName: [HashElement]]) {
|
||||
|
||||
self.init(keyValues: intArrayByEntityName.map({ $0 }))
|
||||
}
|
||||
|
||||
|
||||
// MARK: ExpressibleByDictionaryLiteral
|
||||
|
||||
public typealias Key = EntityName
|
||||
public typealias Value = [HashElement]
|
||||
|
||||
public init(dictionaryLiteral elements: (EntityName, [HashElement])...) {
|
||||
|
||||
self.init(keyValues: elements)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Equatable
|
||||
|
||||
public static func == (lhs: VersionLock, rhs: VersionLock) -> Bool {
|
||||
|
||||
return lhs.hashesByEntityName == rhs.hashesByEntityName
|
||||
}
|
||||
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal init(entityVersionHashesByName: [String: Data]) {
|
||||
|
||||
self.hashesByEntityName = entityVersionHashesByName
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private init(keyValues: [(EntityName, [HashElement])]) {
|
||||
|
||||
var hashesByEntityName: [EntityName: Data] = [:]
|
||||
for (entityName, intArray) in keyValues {
|
||||
|
||||
hashesByEntityName[entityName] = Data(
|
||||
buffer: UnsafeBufferPointer(
|
||||
start: intArray,
|
||||
count: intArray.count
|
||||
)
|
||||
)
|
||||
}
|
||||
self.hashesByEntityName = hashesByEntityName
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user