diff --git a/Sources/OpenSwiftUI/DataAndStorage/Preferences/Internal/AnyPreferenceKey.swift b/Sources/OpenSwiftUI/DataAndStorage/Preferences/Internal/AnyPreferenceKey.swift new file mode 100644 index 0000000..257149a --- /dev/null +++ b/Sources/OpenSwiftUI/DataAndStorage/Preferences/Internal/AnyPreferenceKey.swift @@ -0,0 +1,20 @@ +// +// AnyPreferenceKey.swift +// OpenSwiftUI +// +// Created by Kyle on 2024/1/5. +// Lastest Version: iOS 15.5 +// Status: Complete + +protocol AnyPreferenceKey { + static var valueType: Any.Type { get } + static func visitKey(_ visitor: inout Visitor) +} + +struct _AnyPreferenceKey: AnyPreferenceKey { + static var valueType: Any.Type { Key.self } + + static func visitKey(_ visitor: inout Visitor) where Visitor : PreferenceKeyVisitor { + visitor.visit(key: Key.self) + } +} diff --git a/Sources/OpenSwiftUI/DataAndStorage/Preferences/Internal/HostPreferenceKey.swift b/Sources/OpenSwiftUI/DataAndStorage/Preferences/Internal/HostPreferenceKey.swift new file mode 100644 index 0000000..d8d88e1 --- /dev/null +++ b/Sources/OpenSwiftUI/DataAndStorage/Preferences/Internal/HostPreferenceKey.swift @@ -0,0 +1,9 @@ +// +// HostPreferenceKey.swift +// OpenSwiftUI +// +// Created by Kyle on 2023/1/5. +// Lastest Version: iOS 15.5 +// Status: Complete + +protocol HostPreferenceKey: PreferenceKey {} diff --git a/Sources/OpenSwiftUI/DataAndStorage/Preferences/Internal/PreferenceKeyVisitor.swift b/Sources/OpenSwiftUI/DataAndStorage/Preferences/Internal/PreferenceKeyVisitor.swift new file mode 100644 index 0000000..56e7dea --- /dev/null +++ b/Sources/OpenSwiftUI/DataAndStorage/Preferences/Internal/PreferenceKeyVisitor.swift @@ -0,0 +1,11 @@ +// +// PreferenceKeyVisitor.swift +// OpenSwiftUI +// +// Created by Kyle on 2023/1/5. +// Lastest Version: iOS 15.5 +// Status: Complete + +protocol PreferenceKeyVisitor { + mutating func visit(key: Key.Type) +} diff --git a/Sources/OpenSwiftUI/DataAndStorage/Preferences/Internal/PreferenceList.swift b/Sources/OpenSwiftUI/DataAndStorage/Preferences/Internal/PreferenceList.swift new file mode 100644 index 0000000..916b463 --- /dev/null +++ b/Sources/OpenSwiftUI/DataAndStorage/Preferences/Internal/PreferenceList.swift @@ -0,0 +1,34 @@ +// +// PreferenceList.swift +// OpenSwiftUI +// +// Created by Kyle on 2023/1/5. +// Lastest Version: iOS 15.5 +// Status: WIP + +struct PreferenceList { + private var first: PreferenceNode? + + subscript(_ keyType: Key.Type) -> Value { + get { fatalError("TODO") } + set { fatalError("TODO") } + } +} + +extension PreferenceList { + struct Value { + var value: V + var seed: VersionSeed + } +} + +private class PreferenceNode { + let keyType: Any.Type + let seed: VersionSeed + let mergedSeed: VersionSeed + let next: PreferenceNode? + + init(keyType: Any.Type, seed: VersionSeed, next: PreferenceNode?) { + fatalError("TODO") + } +} diff --git a/Sources/OpenSwiftUI/Internal/Graph/VersionSeed.swift b/Sources/OpenSwiftUI/Internal/Graph/VersionSeed.swift new file mode 100644 index 0000000..0859e31 --- /dev/null +++ b/Sources/OpenSwiftUI/Internal/Graph/VersionSeed.swift @@ -0,0 +1,77 @@ +// +// VersionSeed.swift +// OpenSwiftUI +// +// Created by Kyle on 2024/1/5. +// Lastest Version: iOS 15.5 +// Status: Complete +// ID: 1B00D77CE2C80F9C0F5A59FDEA30ED6B + +struct VersionSeed: CustomStringConvertible { + var value: UInt32 + + var description: String { + switch value { + case VersionSeed.zero.value: "empty" + case VersionSeed.invalid.value: "invalid" + default: value.description + } + } + + static var zero: VersionSeed { VersionSeed(value: .zero) } + static var invalid: VersionSeed { VersionSeed(value: .max) } + + var isValid: Bool { value != VersionSeed.invalid.value } +} + +struct VersionSeedTracker { + var seed: VersionSeed +} + +struct VersionSeedSetTracker { + private var values: [Value] + + mutating func addPreference(_: Key.Type) { + values.append(Value(key: _AnyPreferenceKey.self, seed: .invalid)) + } + + mutating func updateSeeds(to preferences: PreferenceList) { + for index in values.indices { + var visitor = UpdateSeedVisitor(preferences: preferences, seed: nil) + values[index].key.visitKey(&visitor) + guard let seed = visitor.seed else { + continue + } + values[index].seed = seed + } + } +} + +extension VersionSeedSetTracker { + private struct Value { + var key: AnyPreferenceKey.Type + var seed: VersionSeed + } +} + +extension VersionSeedSetTracker { + private struct HasChangesVisitor: PreferenceKeyVisitor { + let preferences: PreferenceList + var seed: VersionSeed + var matches: Bool? + + mutating func visit(key: (some PreferenceKey).Type) { + let valueSeed = preferences[key].seed + matches = seed.isValid && valueSeed.isValid && seed.value == valueSeed.value + } + } + + private struct UpdateSeedVisitor: PreferenceKeyVisitor { + let preferences: PreferenceList + var seed: VersionSeed? + + mutating func visit(key: (some PreferenceKey).Type) { + seed = preferences[key].seed + } + } +} diff --git a/Tests/OpenSwiftUITests/Internal/VersionSeed/VersionSeedTests.swift b/Tests/OpenSwiftUITests/Internal/VersionSeed/VersionSeedTests.swift new file mode 100644 index 0000000..c6d34ef --- /dev/null +++ b/Tests/OpenSwiftUITests/Internal/VersionSeed/VersionSeedTests.swift @@ -0,0 +1,21 @@ +// +// VersionSeedTests.swift +// +// +// Created by Kyle on 2024/1/5. +// + +@testable import OpenSwiftUI +import Testing + +struct VersionSeedTests { + @Test(arguments: [ + (0, "empty"), + (UInt32.max, "invalid"), + (2, "2"), + ]) + func description(value: UInt32, expectedDescription: String) { + let seed = VersionSeed(value: value) + #expect(seed.description == expectedDescription) + } +}