diff --git a/Package.resolved b/Package.resolved index f6293d52c9..3ed9a394fb 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "82f71c92629a240db65e931912dfb2240dd0b70609e84bc12a7b6ccab081b14b", + "originHash" : "ee3f350fd3d229f68927207ca24a9198872a51157f5ab77fc9f62d85458f30ed", "pins" : [ { "identity" : "rxswift", @@ -64,6 +64,15 @@ "version" : "600.0.1" } }, + { + "identity" : "typedidentifier", + "kind" : "remoteSourceControl", + "location" : "https://github.com/VergeGroup/TypedIdentifier", + "state" : { + "revision" : "297de87772cccec24f8f1a63376778d3227305d7", + "version" : "2.0.2" + } + }, { "identity" : "viewinspector", "kind" : "remoteSourceControl", diff --git a/Package.swift b/Package.swift index 68d2550c2e..cf64f7f337 100644 --- a/Package.swift +++ b/Package.swift @@ -24,6 +24,7 @@ let package = Package( .package(url: "https://github.com/apple/swift-atomics.git", from: "1.0.2"), .package(url: "https://github.com/apple/swift-collections", from: "1.1.0"), .package(url: "https://github.com/VergeGroup/swift-concurrency-task-manager", from: "1.1.0"), + .package(url: "https://github.com/VergeGroup/TypedIdentifier", from: "2.0.2"), /// for testing .package(url: "https://github.com/nalexn/ViewInspector.git", from: "0.10.0"), @@ -62,13 +63,12 @@ let package = Package( "VergeRx" ] ), - .target(name: "VergeTypedIdentifier"), .target( name: "VergeNormalization", dependencies: [ "VergeMacros", "VergeComparator", - "VergeTypedIdentifier", + .product(name: "TypedIdentifier", package: "TypedIdentifier"), .product(name: "HashTreeCollections", package: "swift-collections"), ] ), diff --git a/Sources/VergeNormalization/EntityType.swift b/Sources/VergeNormalization/EntityType.swift new file mode 100644 index 0000000000..a3e02f10ce --- /dev/null +++ b/Sources/VergeNormalization/EntityType.swift @@ -0,0 +1,10 @@ +@_exported import TypedIdentifier + +public protocol EntityType: TypedIdentifiable, Equatable, Sendable { +} + +extension EntityType { + public var entityID: TypedID { + return typedID + } +} diff --git a/Sources/VergeNormalization/Indexes/Indexes.swift b/Sources/VergeNormalization/Indexes/Indexes.swift index 7c4af0afa8..39484ca791 100644 --- a/Sources/VergeNormalization/Indexes/Indexes.swift +++ b/Sources/VergeNormalization/Indexes/Indexes.swift @@ -32,9 +32,9 @@ public enum Indexes { ] ``` */ - public typealias Hash = HashTreeCollections.TreeDictionary + public typealias Hash = HashTreeCollections.TreeDictionary - public typealias Ordered = Array + public typealias Ordered = Array public typealias Set = Never diff --git a/Sources/VergeNormalization/NormalizedStorageComparators.swift b/Sources/VergeNormalization/NormalizedStorageComparators.swift index 5eee323d22..4adeb6b857 100644 --- a/Sources/VergeNormalization/NormalizedStorageComparators.swift +++ b/Sources/VergeNormalization/NormalizedStorageComparators.swift @@ -34,9 +34,9 @@ public enum NormalizedStorageComparators { // // public typealias Input = Storage // -// public let entityID: Entity.EntityID +// public let entityID: Entity.TypedID // -// public init(entityID: Entity.EntityID) { +// public init(entityID: Entity.TypedID) { // self.entityID = entityID // } // diff --git a/Sources/VergeNormalization/Tables/TableType.swift b/Sources/VergeNormalization/Tables/TableType.swift index 175404032b..013e7a43ef 100644 --- a/Sources/VergeNormalization/Tables/TableType.swift +++ b/Sources/VergeNormalization/Tables/TableType.swift @@ -1,4 +1,4 @@ -import VergeTypedIdentifier +import TypedIdentifier /// a storage of the entity public protocol TableType: Equatable, Sendable { @@ -12,17 +12,17 @@ public protocol TableType: Equatable, Sendable { var count: Int { get } var isEmpty: Bool { get } - borrowing func find(by id: consuming Entity.EntityID) -> Entity? + borrowing func find(by id: consuming Entity.TypedID) -> Entity? - borrowing func find(in ids: consuming some Sequence) -> [Entity] + borrowing func find(in ids: consuming some Sequence) -> [Entity] mutating func updateExists( - id: consuming Entity.EntityID, + id: consuming Entity.TypedID, update: (inout Entity) throws -> Void ) throws -> Entity mutating func updateIfExists( - id: consuming Entity.EntityID, + id: consuming Entity.TypedID, update: (inout Entity) throws -> Void ) rethrows -> Entity? @@ -32,7 +32,7 @@ public protocol TableType: Equatable, Sendable { @discardableResult mutating func insert(_ addingEntities: consuming some Sequence) -> [InsertionResult] - mutating func remove(_ id: Entity.EntityID) + mutating func remove(_ id: Entity.TypedID) mutating func removeAll() } @@ -40,9 +40,11 @@ public protocol TableType: Equatable, Sendable { /// An object indicates result of insertion /// It can be used to create a getter object. public struct InsertionResult { - public var entityID: Entity.EntityID { - entity.entityID + + public var entityID: Entity.TypedID { + entity.typedID } + public let entity: Entity init(entity: consuming Entity) { diff --git a/Sources/VergeNormalization/Tables/Tables.Hash.swift b/Sources/VergeNormalization/Tables/Tables.Hash.swift index 07b6efd817..b3af533fa9 100644 --- a/Sources/VergeNormalization/Tables/Tables.Hash.swift +++ b/Sources/VergeNormalization/Tables/Tables.Hash.swift @@ -9,7 +9,7 @@ extension Tables { public typealias Entity = Entity - private var storage: TreeDictionary + private var storage: TreeDictionary public private(set) var updatedMarker = NonAtomicCounter() /// The number of entities in table @@ -22,12 +22,12 @@ extension Tables { _read { yield storage.isEmpty } } - public init(entities: TreeDictionary = .init()) { + public init(entities: TreeDictionary = .init()) { self.storage = entities } /// Returns all entity ids that stored. - public borrowing func allIDs() -> TreeDictionary.Keys { + public borrowing func allIDs() -> TreeDictionary.Keys { return storage.keys } @@ -40,7 +40,7 @@ extension Tables { Finds an entity by the identifier of the entity. - Returns: An entity that found by identifier. Nil if the table does not have that entity. */ - public borrowing func find(by id: consuming Entity.EntityID) -> Entity? { + public borrowing func find(by id: consuming Entity.TypedID) -> Entity? { return storage[id] } @@ -49,7 +49,7 @@ extension Tables { /// /// if ids contains same id, result also contains same element. /// - Parameter ids: sequence of Entity.ID - public borrowing func find(in ids: consuming some Sequence) -> [Entity] { + public borrowing func find(in ids: consuming some Sequence) -> [Entity] { return ids.reduce(into: [Entity]()) { (buf, id) in guard let entity = storage[id] else { return } @@ -60,12 +60,12 @@ extension Tables { /** Updates the entity that already exsisting in the table. - - Attention: Please don't change `EntityType.entityID` value. if we changed, the crash happens (precondition) + - Attention: Please don't change `EntityType.TypedID` value. if we changed, the crash happens (precondition) */ @discardableResult @inline(__always) public mutating func updateExists( - id: consuming Entity.EntityID, + id: consuming Entity.TypedID, update: (inout Entity) throws -> Void ) throws -> Entity { @@ -74,7 +74,7 @@ extension Tables { } try update(¤t) - precondition(current.entityID == id) + precondition(current.typedID == id) storage[id] = current updatedMarker.increment() @@ -85,11 +85,11 @@ extension Tables { /** Updates the entity that already exsisting in the table. - - Attention: Please don't change `EntityType.entityID` value. if we changed, the crash happens (precondition) + - Attention: Please don't change `EntityType.TypedID` value. if we changed, the crash happens (precondition) */ @discardableResult public mutating func updateIfExists( - id: consuming Entity.EntityID, + id: consuming Entity.TypedID, update: (inout Entity) throws -> Void ) rethrows -> Entity? { try? updateExists(id: id, update: update) @@ -101,7 +101,7 @@ extension Tables { @discardableResult public mutating func insert(_ entity: Entity) -> Self.InsertionResult { - storage[entity.entityID] = entity + storage[entity.typedID] = entity updatedMarker.increment() @@ -115,7 +115,7 @@ extension Tables { public mutating func insert(_ addingEntities: consuming some Sequence) -> [Self.InsertionResult] { let results = addingEntities.map { entity -> Self.InsertionResult in - storage[entity.entityID] = entity + storage[entity.typedID] = entity return .init(entity: entity) } @@ -127,7 +127,7 @@ extension Tables { /** Removes the entity by the identifier. */ - public mutating func remove(_ id: Entity.EntityID) { + public mutating func remove(_ id: Entity.TypedID) { storage.removeValue(forKey: id) updatedMarker.increment() } @@ -140,7 +140,7 @@ extension Tables { updatedMarker.increment() } - public var values: TreeDictionary.Values { + public var values: TreeDictionary.Values { storage.values } diff --git a/Sources/VergeNormalization/VergeNormalization+Macros.swift b/Sources/VergeNormalization/VergeNormalization+Macros.swift index 6bf3cf5dd9..3ae9512d83 100644 --- a/Sources/VergeNormalization/VergeNormalization+Macros.swift +++ b/Sources/VergeNormalization/VergeNormalization+Macros.swift @@ -13,8 +13,8 @@ public macro Index() = #externalMacro(module: "VergeMacrosPlugin", type: "IndexM #if DEBUG struct A: EntityType { - typealias EntityIDRawType = String - var entityID: EntityID { + typealias TypedIdentifierRawValue = String + var typedID: TypedID { .init("") } } diff --git a/Sources/VergeNormalization/VergeNormalization.swift b/Sources/VergeNormalization/VergeNormalization.swift index cf88f4b5b2..2b09ec9c10 100644 --- a/Sources/VergeNormalization/VergeNormalization.swift +++ b/Sources/VergeNormalization/VergeNormalization.swift @@ -1 +1 @@ -@_exported import VergeTypedIdentifier +@_exported import TypedIdentifier diff --git a/Sources/VergeNormalizationDerived/DerivedResult.swift b/Sources/VergeNormalizationDerived/DerivedResult.swift index 6b7623812d..3b246a720a 100644 --- a/Sources/VergeNormalizationDerived/DerivedResult.swift +++ b/Sources/VergeNormalizationDerived/DerivedResult.swift @@ -15,7 +15,7 @@ public struct DerivedResult { /// A dictionary of Derived that stored by id /// It's faster than filtering values array to use this dictionary to find missing id or created id. - public private(set) var storage: [Entity.EntityID : Derived] = [:] + public private(set) var storage: [Entity.TypedID : Derived] = [:] /// An array of Derived that orderd by specified the order of id. public private(set) var values: [Derived] @@ -25,7 +25,7 @@ public struct DerivedResult { self.values = [] } - public mutating func append(derived: Derived, id: Entity.EntityID) { + public mutating func append(derived: Derived, id: Entity.TypedID) { storage[id] = derived values.append(derived) } diff --git a/Sources/VergeNormalizationDerived/DispatcherType+.swift b/Sources/VergeNormalizationDerived/DispatcherType+.swift index da534f38a7..ba8a60fb49 100644 --- a/Sources/VergeNormalizationDerived/DispatcherType+.swift +++ b/Sources/VergeNormalizationDerived/DispatcherType+.swift @@ -84,7 +84,7 @@ public struct NormalizedStorageTablePath< let tableSelector: _TableSelector public func derived( - from entityID: consuming Entity.EntityID + from entityID: consuming Entity.TypedID ) -> Derived> { return store.derivedEntity( @@ -95,7 +95,7 @@ public struct NormalizedStorageTablePath< } public func derived( - entityIDs: some Sequence + entityIDs: some Sequence ) -> DerivedResult>> { var result = DerivedResult>>() @@ -151,7 +151,7 @@ public struct NormalizedStorageTablePath< /// A pointer of the result derived object will be different from each other, but the backing source will be shared. /// public func derivedNonNull( - entityID: consuming Entity.EntityID + entityID: consuming Entity.TypedID ) throws -> Derived> { let _initialValue = storageSelector @@ -179,7 +179,7 @@ public struct NormalizedStorageTablePath< for entity in entities { result.append( derived: self.derivedNonNull(entity: entity), - id: entity.entityID + id: entity.typedID ) } @@ -196,7 +196,7 @@ public struct NormalizedStorageTablePath< /// A pointer of the result derived object will be different from each other, but the backing source will be shared. /// public func derivedNonNull( - entityIDs: consuming some Sequence + entityIDs: consuming some Sequence ) -> NonNullDerivedResult { var result = NonNullDerivedResult() @@ -224,7 +224,7 @@ public struct NormalizedStorageTablePath< /// A pointer of the result derived object will be different from each other, but the backing source will be shared. /// public func derivedNonNull( - entityIDs: consuming Set + entityIDs: consuming Set ) -> NonNullDerivedResult { var result = NonNullDerivedResult() @@ -280,7 +280,7 @@ extension DerivedMaking { _TableSelector: TableSelector >( selector: AbsoluteTableSelector<_StorageSelector, _TableSelector>, - entityID: consuming _TableSelector.Table.Entity.EntityID + entityID: consuming _TableSelector.Table.Entity.TypedID ) -> Derived> where _StorageSelector.Storage == _TableSelector.Storage, @@ -332,10 +332,10 @@ where _StorageSelector.Storage == _TableSelector.Storage { typealias Output = EntityWrapper private let selector: AbsoluteTableSelector<_StorageSelector, _TableSelector> - private let entityID: Entity.EntityID + private let entityID: Entity.TypedID init( - targetIdentifier: Entity.EntityID, + targetIdentifier: Entity.TypedID, selector: consuming AbsoluteTableSelector<_StorageSelector, _TableSelector> ) { self.entityID = targetIdentifier @@ -383,7 +383,7 @@ where _StorageSelector.Storage == _TableSelector.Storage { typealias Output = NonNullEntityWrapper private let selector: AbsoluteTableSelector<_StorageSelector, _TableSelector> - private let entityID: Entity.EntityID + private let entityID: Entity.TypedID private let latestValue: Entity private let lock: NSLock = .init() @@ -393,7 +393,7 @@ where _StorageSelector.Storage == _TableSelector.Storage { selector: consuming AbsoluteTableSelector<_StorageSelector, _TableSelector> ) { - self.entityID = initialEntity.entityID + self.entityID = initialEntity.typedID self.latestValue = initialEntity self.selector = selector diff --git a/Sources/VergeNormalizationDerived/EntityWrapper.swift b/Sources/VergeNormalizationDerived/EntityWrapper.swift index 4d6474ee32..2288677327 100644 --- a/Sources/VergeNormalizationDerived/EntityWrapper.swift +++ b/Sources/VergeNormalizationDerived/EntityWrapper.swift @@ -4,9 +4,9 @@ import VergeNormalization public struct EntityWrapper: Sendable { public private(set) var wrapped: Entity? - public let id: Entity.EntityID + public let id: Entity.TypedID - public init(id: Entity.EntityID, entity: Entity?) { + public init(id: Entity.TypedID, entity: Entity?) { self.id = id self.wrapped = entity } diff --git a/Sources/VergeNormalizationDerived/NonNullEntityWrapper.swift b/Sources/VergeNormalizationDerived/NonNullEntityWrapper.swift index 3fbf4678e5..be6f92c5c1 100644 --- a/Sources/VergeNormalizationDerived/NonNullEntityWrapper.swift +++ b/Sources/VergeNormalizationDerived/NonNullEntityWrapper.swift @@ -8,7 +8,7 @@ public struct NonNullEntityWrapper { public private(set) var wrapped: Entity /// An identifier - public let id: Entity.EntityID + public let id: Entity.TypedID @available(*, deprecated, renamed: "isFallBack") public var isUsingFallback: Bool { diff --git a/Sources/VergeTypedIdentifier/EntityType.swift b/Sources/VergeTypedIdentifier/EntityType.swift deleted file mode 100644 index 84f49442c4..0000000000 --- a/Sources/VergeTypedIdentifier/EntityType.swift +++ /dev/null @@ -1,57 +0,0 @@ -// -// Copyright (c) 2019 muukii -// -// 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. - -public struct EntityIdentifier : Hashable, CustomStringConvertible, Sendable { - - public static func == (lhs: Self, rhs: Self) -> Bool { - lhs.raw == rhs.raw - } - - public func hash(into hasher: inout Hasher) { - raw.hash(into: &hasher) - } - - public let raw: Entity.EntityIDRawType - - public init(_ raw: consuming Entity.EntityIDRawType) { - self.raw = raw - } - - public var description: String { - "<\(String(reflecting: Entity.self))>(\(raw))" - } -} - -/// A protocol describes object is an Entity. -public protocol EntityType: Identifiable, Equatable, Sendable { - - associatedtype EntityIDRawType: Hashable, Sendable - - var entityID: EntityID { get } - - typealias EntityID = EntityIdentifier -} - -extension EntityType { - public var id: EntityID { - entityID - } -} diff --git a/Tests/VergeNormalizationDerivedTests/DemoState.swift b/Tests/VergeNormalizationDerivedTests/DemoState.swift index 9d836cbaf7..71a385c8d3 100644 --- a/Tests/VergeNormalizationDerivedTests/DemoState.swift +++ b/Tests/VergeNormalizationDerivedTests/DemoState.swift @@ -42,22 +42,22 @@ extension Database { struct Book: EntityType, Hashable { - typealias EntityIDRawType = String + typealias TypedIdentifierRawValue = String - var entityID: EntityID { + var typedID: TypedID { .init(rawID) } let rawID: String - let authorID: Author.EntityID + let authorID: Author.TypedID var name: String = "initial" } struct Author: EntityType { - typealias EntityIDRawType = String - - var entityID: EntityID { + typealias TypedIdentifierRawValue = String + + var typedID: TypedID { .init(rawID) } diff --git a/Tests/VergeNormalizationDerivedTests/VergeNormalizationDerivedTests.swift b/Tests/VergeNormalizationDerivedTests/VergeNormalizationDerivedTests.swift index d3e8c8f1e9..dd4fc46073 100644 --- a/Tests/VergeNormalizationDerivedTests/VergeNormalizationDerivedTests.swift +++ b/Tests/VergeNormalizationDerivedTests/VergeNormalizationDerivedTests.swift @@ -22,7 +22,7 @@ final class VergeNormalizationDerivedTests: XCTestCase { let derived = store .normalizedStorage(.keyPath(\.db)) .table(.keyPath(\.book)) - .derived(from: Book.EntityID.init("1")) + .derived(from: Book.TypedID.init("1")) var received: [Book?] = [] diff --git a/Tests/VergeNormalizationTests/Entities.swift b/Tests/VergeNormalizationTests/Entities.swift index b67110bf35..0ff516c72c 100644 --- a/Tests/VergeNormalizationTests/Entities.swift +++ b/Tests/VergeNormalizationTests/Entities.swift @@ -2,22 +2,22 @@ import VergeNormalization struct Book: EntityType, Hashable { - typealias EntityIDRawType = String + typealias TypedIdentifierRawValue = String - var entityID: EntityID { + var typedID: TypedID { .init(rawID) } let rawID: String - let authorID: Author.EntityID + let authorID: Author.TypedID var name: String = "initial" } struct Author: EntityType { - typealias EntityIDRawType = String + typealias TypedIdentifierRawValue = String - var entityID: EntityID { + var typedID: TypedID { .init(rawID) } diff --git a/Tests/VergeNormalizationTests/Source.swift b/Tests/VergeNormalizationTests/Source.swift index ae56bb5826..3d0f7563e4 100644 --- a/Tests/VergeNormalizationTests/Source.swift +++ b/Tests/VergeNormalizationTests/Source.swift @@ -27,7 +27,7 @@ final class Tests: XCTestCase { var transaction = state.beginBatchUpdates() - let book = Book(rawID: "some", authorID: Author.anonymous.entityID) + let book = Book(rawID: "some", authorID: Author.anonymous.typedID) transaction.modifying.book.insert(book) state.commitBatchUpdates(transaction: transaction) @@ -45,7 +45,7 @@ final class Tests: XCTestCase { state.performBatchUpdates { (context) in - let book = Book(rawID: "some", authorID: Author.anonymous.entityID) + let book = Book(rawID: "some", authorID: Author.anonymous.typedID) context.modifying.book.insert(book) } @@ -62,7 +62,7 @@ final class Tests: XCTestCase { state.performBatchUpdates { (context) in - let book = Book(rawID: "some", authorID: Author.anonymous.entityID) + let book = Book(rawID: "some", authorID: Author.anonymous.typedID) context.modifying.book.insert(book) } @@ -76,9 +76,9 @@ final class Tests: XCTestCase { state.performBatchUpdates { (context) in - let book = Book(rawID: "some", authorID: Author.anonymous.entityID) + let book = Book(rawID: "some", authorID: Author.anonymous.typedID) context.modifying.book.insert(book) - context.modifying.bookIndex.append(book.entityID) + context.modifying.bookIndex.append(book.typedID) } XCTAssertEqual(state.book.count, 1) @@ -87,7 +87,7 @@ final class Tests: XCTestCase { print(state.bookIndex) state.performBatchUpdates { (context) -> Void in - context.modifying.book.remove(Book.EntityID.init("some")) + context.modifying.book.remove(Book.TypedID.init("some")) } XCTAssertEqual(state.book.count, 0) @@ -101,11 +101,11 @@ final class Tests: XCTestCase { var state = MyStorage() - let id = Book.EntityID.init("some") + let id = Book.TypedID.init("some") state.performBatchUpdates { (context) in - let book = Book(rawID: id.raw, authorID: Author.anonymous.entityID) + let book = Book(rawID: id.raw, authorID: Author.anonymous.typedID) context.modifying.book.insert(book) } @@ -195,7 +195,7 @@ final class Tests: XCTestCase { func testDescription() { - let authorID = Author.EntityID("author.id") + let authorID = Author.TypedID("author.id") XCTAssertEqual(authorID.description, "(author.id)") } @@ -210,7 +210,7 @@ final class Tests: XCTestCase { let a = Author(rawID: "\(i)", name: "\(i)") context.modifying.author.insert(a) - context.modifying.book.insert(Book(rawID: "\(i)", authorID: a.entityID)) + context.modifying.book.insert(Book(rawID: "\(i)", authorID: a.typedID)) }