Skip to content

Instantly share code, notes, and snippets.

@daltonclaybrook
Created December 29, 2021 21:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save daltonclaybrook/bc537e8be6f5903d3a90377a9128b403 to your computer and use it in GitHub Desktop.
Save daltonclaybrook/bc537e8be6f5903d3a90377a9128b403 to your computer and use it in GitHub Desktop.
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