Created
December 29, 2021 21:57
-
-
Save daltonclaybrook/bc537e8be6f5903d3a90377a9128b403 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
protocol Placeholding { | |
static func placeholder() -> Self | |
} | |
struct PlaceholderArray<Element: Placeholding>: RandomAccessCollection { | |
typealias SubSequence = Slice<Self> | |
var startIndex: Int { indices.lowerBound } | |
var endIndex: Int { indices.upperBound } | |
private(set) var indices: Range<Int> | |
private var storage: [Index: Element] = [:] | |
init(_ elements: [Element]) { | |
self.init(count: elements.count) | |
self.insert(elements: elements, in: 0..<elements.count) | |
} | |
init(count: Int = 0) { | |
self.indices = 0..<count | |
} | |
subscript(index: Int) -> Element { | |
get { | |
precondition(indices.contains(index), "Index out of bounds: \(index)") | |
return storage[index] ?? .placeholder() | |
} | |
set { | |
storage[index] = newValue | |
updateIndicesIfNecessary(index: index) | |
} | |
} | |
mutating func insert(elements: [Element], in range: Range<Int>) { | |
Swift.zip(range, elements).forEach { index, element in | |
storage[index] = element | |
} | |
updateIndicesIfNecessary(index: range.upperBound) | |
} | |
// MARK: - Helpers | |
private mutating func updateIndicesIfNecessary(index: Int) { | |
guard index > indices.upperBound else { return } | |
indices = 0..<index | |
} | |
} | |
extension PlaceholderArray: ExpressibleByArrayLiteral { | |
init(arrayLiteral elements: Element...) { | |
self.init(elements) | |
} | |
} | |
extension PlaceholderArray: Equatable where Element: Equatable {} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment