Skip to content

Instantly share code, notes, and snippets.

@timvermeulen
Created July 25, 2019 17:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timvermeulen/476030d11c02c6f0686017d7743f7e0e to your computer and use it in GitHub Desktop.
Save timvermeulen/476030d11c02c6f0686017d7743f7e0e to your computer and use it in GitHub Desktop.
struct RotatedCollection<Base: Collection> {
let base: Base
let index: Base.Index
init(base: Base, shiftingToStart index: Base.Index) {
self.base = base
self.index = index
}
}
extension RotatedCollection: Collection {
struct Index {
let base: Base.Index
let isWrapped: Bool
}
var startIndex: Index {
Index(base: index, isWrapped: false)
}
var endIndex: Index {
Index(base: index, isWrapped: true)
}
subscript(index: Index) -> Base.SubSequence.Element {
base[index.base]
}
func index(after index: Index) -> Index {
let next = base.index(after: index.base)
if !index.isWrapped && next == base.endIndex {
return Index(base: base.startIndex, isWrapped: true)
} else {
return Index(base: next, isWrapped: index.isWrapped)
}
}
}
extension RotatedCollection.Index: Comparable {
static func == (lhs: RotatedCollection.Index, rhs: RotatedCollection.Index) -> Bool {
lhs.isWrapped == rhs.isWrapped && lhs.base == rhs.base
}
static func < (lhs: RotatedCollection.Index, rhs: RotatedCollection.Index) -> Bool {
if lhs.isWrapped == rhs.isWrapped {
return lhs.base < rhs.base
} else {
return rhs.isWrapped
}
}
}
extension Collection {
func rotated(shiftingToStart index: Index) -> RotatedCollection<Self> {
RotatedCollection(base: self, shiftingToStart: index)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment