diff --git a/Package.swift b/Package.swift index 60624ba2ca..dd0a3c28ea 100644 --- a/Package.swift +++ b/Package.swift @@ -45,10 +45,12 @@ let package = Package( .target(name: "VergeMacros", dependencies: ["VergeMacrosPlugin"]), .target(name: "VergeTiny", dependencies: []), + .target(name: "VergeComparator"), .target( name: "Verge", dependencies: [ "VergeMacros", + "VergeComparator", .product(name: "Atomics", package: "swift-atomics"), .product(name: "DequeModule", package: "swift-collections"), .product(name: "ConcurrencyTaskManager", package: "swift-concurrency-task-manager"), @@ -64,6 +66,7 @@ let package = Package( name: "VergeNormalization", dependencies: [ "VergeMacros", + "VergeComparator", .product(name: "HashTreeCollections", package: "swift-collections"), ] ), diff --git a/Sources/Verge/Verge.swift b/Sources/Verge/Verge.swift index 975e1ffe0c..0c70f8cc2c 100644 --- a/Sources/Verge/Verge.swift +++ b/Sources/Verge/Verge.swift @@ -1,3 +1,4 @@ @_exported import ConcurrencyTaskManager @_exported import Combine +@_exported import VergeComparator diff --git a/Sources/Verge/Store/Comparer.swift b/Sources/VergeComparator/Comparator.swift similarity index 99% rename from Sources/Verge/Store/Comparer.swift rename to Sources/VergeComparator/Comparator.swift index 57903fe9a2..e351a0a783 100644 --- a/Sources/Verge/Store/Comparer.swift +++ b/Sources/VergeComparator/Comparator.swift @@ -22,6 +22,7 @@ import Foundation import os.log +// TODO: will rename as Comparator public protocol Comparison: Sendable { associatedtype Input diff --git a/Sources/VergeMacrosPlugin/DatabaseMacro.swift b/Sources/VergeMacrosPlugin/DatabaseMacro.swift index a7cb8f3a9e..f2348ebbae 100644 --- a/Sources/VergeMacrosPlugin/DatabaseMacro.swift +++ b/Sources/VergeMacrosPlugin/DatabaseMacro.swift @@ -216,6 +216,13 @@ public struct DatabaseTableMacro: Macro { } +extension DatabaseTableMacro: PeerMacro { + public static func expansion(of node: SwiftSyntax.AttributeSyntax, providingPeersOf declaration: some SwiftSyntax.DeclSyntaxProtocol, in context: some SwiftSyntaxMacros.MacroExpansionContext) throws -> [SwiftSyntax.DeclSyntax] { + return [] + } + +} + extension DatabaseTableMacro: AccessorMacro { public static func expansion( of node: SwiftSyntax.AttributeSyntax, @@ -230,16 +237,16 @@ extension DatabaseTableMacro: AccessorMacro { let id = identifier(from: declaration.cast(VariableDeclSyntax.self)) return [ - """ - get { - _$\(id) - } - """, - """ - set { - _$\(id) = newValue - } - """ , +// """ +// get { +// _$\(id) +// } +// """, +// """ +// set { +// _$\(id) = newValue +// } +// """ , ] } diff --git a/Sources/VergeNormalization/Comparison.swift b/Sources/VergeNormalization/Comparison.swift new file mode 100644 index 0000000000..81708d8a65 --- /dev/null +++ b/Sources/VergeNormalization/Comparison.swift @@ -0,0 +1,62 @@ +import VergeComparator + +public enum NormalizedStorageComparisons { + + /// True indicates database is not changed + public struct StorageComparison: Comparison { + public typealias Input = Storage + + public func callAsFunction(_ lhs: Storage, _ rhs: Storage) -> Bool { + + lhs == rhs + +// (lhs._backingStorage.entityUpdatedMarker, lhs._backingStorage.indexUpdatedMarker) == (rhs._backingStorage.entityUpdatedMarker, rhs._backingStorage.indexUpdatedMarker) + } + } + + /// Returns true if the table of the entity in database has no changes. + /// + /// - Complexity: O(1) + public struct TableComparison: Comparison { + + public typealias Input = Storage + + public func callAsFunction(_ lhs: Storage, _ rhs: Storage) -> Bool { +// lhs._backingStorage.entityBackingStorage.table(Entity.self).updatedMarker == rhs._backingStorage.entityBackingStorage.table(Entity.self).updatedMarker + fatalError() + } + + } + + /// Returns true if the updates result does not contain the entity. + public struct UpdateComparison: Comparison { + + public typealias Input = Storage + + + public let entityID: Entity.EntityID + + public init(entityID: Entity.EntityID) { + self.entityID = entityID + } + + public func callAsFunction(_ lhs: Storage, _ rhs: Storage) -> Bool { + + fatalError() + +// guard let result = rhs._backingStorage.lastUpdatesResult else { +// return false +// } +// guard !result.wasUpdated(entityID) else { +// return false +// } +// guard !result.wasDeleted(entityID) else { +// return false +// } +// return true + + } + } + +} + diff --git a/Sources/VergeNormalization/NormalizedStorageType.swift b/Sources/VergeNormalization/NormalizedStorageType.swift index 491d85f30c..86b591bd59 100644 --- a/Sources/VergeNormalization/NormalizedStorageType.swift +++ b/Sources/VergeNormalization/NormalizedStorageType.swift @@ -1,5 +1,5 @@ -public protocol NormalizedStorageType { +public protocol NormalizedStorageType: Equatable { func finalizeTransaction(transaction: inout ModifyingTransaction) diff --git a/Sources/VergeNormalization/VergeNormalization+Macros.swift b/Sources/VergeNormalization/VergeNormalization+Macros.swift index 859b624450..735744ec10 100644 --- a/Sources/VergeNormalization/VergeNormalization+Macros.swift +++ b/Sources/VergeNormalization/VergeNormalization+Macros.swift @@ -1,10 +1,10 @@ -@attached(member, names: arbitrary) +//@attached(member, names: arbitrary) //@attached(memberAttribute) @attached(extension, conformances: NormalizedStorageType, Equatable, names: named(Context), named(BBB), arbitrary) public macro NormalizedStorage() = #externalMacro(module: "VergeMacrosPlugin", type: "DatabaseMacro") -@attached(accessor) +@attached(peer) public macro TableAccessor() = #externalMacro(module: "VergeMacrosPlugin", type: "DatabaseTableMacro") @@ -25,7 +25,7 @@ struct MyDatabase { private func play() { - var db = MyDatabase.init() + var db = MyDatabase.init(user: .init()) db.performBatchUpdates { t in t.modifying.user.insert(.init()) diff --git a/Sources/VergeNormalizationDerived/DispatcherType+.swift b/Sources/VergeNormalizationDerived/DispatcherType+.swift index 47796b87f2..8481fe0112 100644 --- a/Sources/VergeNormalizationDerived/DispatcherType+.swift +++ b/Sources/VergeNormalizationDerived/DispatcherType+.swift @@ -4,17 +4,49 @@ extension DispatcherType { _StorageSelector: StorageSelector, _TableSelector: TableSelector >( - selector: consuming AbsoluteTableSelector<_StorageSelector, _TableSelector> + selector: consuming AbsoluteTableSelector<_StorageSelector, _TableSelector>, + entityID: _TableSelector.Entity.EntityID ) -> Derived> where _StorageSelector.Storage == _TableSelector.Storage, _StorageSelector.Source == Changes { - derived(SingleEntityPipeline(selector: selector), queue: .passthrough) + // TODO: caching + + return derived( + SingleEntityPipeline( + targetIdentifier: entityID, + selector: selector + ), + queue: .passthrough + ) } + public func derivedEntity2< + _StorageSelector: StorageSelector, + _TableSelector: TableSelector + >( + selector: consuming AbsoluteTableSelector<_StorageSelector, _TableSelector>, + entityID: _TableSelector.Entity.EntityID + ) -> Derived> + where + _StorageSelector.Storage == _TableSelector.Storage, + _StorageSelector.Source == Changes + { + + // TODO: caching + + return derived( + SingleEntityPipeline( + targetIdentifier: entityID, + selector: selector + ), + queue: .passthrough + ) + + } } private struct SingleEntityPipeline< @@ -48,6 +80,11 @@ where _StorageSelector.Storage == _TableSelector.Storage, _StorageSelector.Sourc } func yieldContinuously(_ input: Input) -> Verge.ContinuousResult> { + + guard let previous = input.previous else { + return .new(yield(input)) + } + fatalError() }