diff --git a/Sources/Spezi/SharedRepository/Builtin/HeapRepository.swift b/Sources/Spezi/SharedRepository/Builtin/HeapRepository.swift index 12c5741e..07ef2020 100644 --- a/Sources/Spezi/SharedRepository/Builtin/HeapRepository.swift +++ b/Sources/Spezi/SharedRepository/Builtin/HeapRepository.swift @@ -32,3 +32,25 @@ public final class HeapRepository: SharedRepository, BuiltinRepository { collect0(allOf: type) } } + + +extension HeapRepository: Collection { + public typealias Index = Dictionary.Index + + public var startIndex: Index { + storage.values.startIndex + } + + public var endIndex: Index { + storage.values.endIndex + } + + public func index(after index: Index) -> Index { + storage.values.index(after: index) + } + + + public subscript(position: Index) -> AnyRepositoryValue { + storage.values[position] + } +} diff --git a/Sources/Spezi/SharedRepository/Builtin/ValueRepository.swift b/Sources/Spezi/SharedRepository/Builtin/ValueRepository.swift index 3804103f..b6658e01 100644 --- a/Sources/Spezi/SharedRepository/Builtin/ValueRepository.swift +++ b/Sources/Spezi/SharedRepository/Builtin/ValueRepository.swift @@ -34,5 +34,26 @@ public struct ValueRepository: SharedRepository, BuiltinRepository { } } +extension ValueRepository: Collection { + public typealias Index = Dictionary.Index + + public var startIndex: Index { + storage.values.startIndex + } + + public var endIndex: Index { + storage.values.endIndex + } + + public func index(after index: Index) -> Index { + storage.values.index(after: index) + } + + + public subscript(position: Index) -> AnyRepositoryValue { + storage.values[position] + } +} + extension ValueRepository: @unchecked Sendable where Anchor: Sendable {} diff --git a/Sources/Spezi/SharedRepository/RepositoryValue.swift b/Sources/Spezi/SharedRepository/RepositoryValue.swift index 33814c2c..e166d151 100644 --- a/Sources/Spezi/SharedRepository/RepositoryValue.swift +++ b/Sources/Spezi/SharedRepository/RepositoryValue.swift @@ -9,6 +9,8 @@ /// Represents type erased ``RepositoryValue``. public protocol AnyRepositoryValue { + /// This property gives access to a type-erased version of ``RepositoryValue/Source`` + var anySource: any KnowledgeSource.Type { get } /// This property gives access to a type-erased version of ``RepositoryValue/value``. var anyValue: Any { get } } @@ -31,6 +33,11 @@ public protocol RepositoryValue: AnyRepositoryValue { extension RepositoryValue { + /// The type erased ``RepositoryValue/Source``. + public var anySource: any KnowledgeSource.Type { + Source.self + } + /// The type erased ``RepositoryValue/value``. public var anyValue: Any { value diff --git a/Tests/SpeziTests/HelperTests/SharedRepositoryTests.swift b/Tests/SpeziTests/HelperTests/SharedRepositoryTests.swift index f7c1f9aa..fc40c48a 100644 --- a/Tests/SpeziTests/HelperTests/SharedRepositoryTests.swift +++ b/Tests/SpeziTests/HelperTests/SharedRepositoryTests.swift @@ -265,6 +265,27 @@ final class SharedRepositoryTests: XCTestCase { Self.optionalComputedValue = nil } + func testValueRepositoryIteration() { + var repository = ValueRepository() + repository[TestStruct.self] = TestStruct(value: 3) + iterationTest(repository) + } + + func testHeapRepositoryIteration() { + var repository = HeapRepository() + repository[TestStruct.self] = TestStruct(value: 3) + iterationTest(repository) + } + + func iterationTest>(_ repository: Repository) + where Repository: Collection, Repository.Element == AnyRepositoryValue { + for value in repository { + XCTAssertTrue(value.anySource is TestStruct.Type) + XCTAssertTrue(value.anyValue is TestStruct) + XCTAssertEqual(value.anyValue as? TestStruct, TestStruct(value: 3)) + } + } + func testSetAndGet() { repos.forEach { $0.testSetAndGet() } }