Skip to content

Instantly share code, notes, and snippets.

@dabrahams
Last active July 17, 2020 09:33
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 dabrahams/c6368b58cd3d3ef9659d84ebe24d299c to your computer and use it in GitHub Desktop.
Save dabrahams/c6368b58cd3d3ef9659d84ebe24d299c to your computer and use it in GitHub Desktop.
Motivation for non-public conformances providing public API
/// A collection formed by adapting some `Base` collection, typically
/// displaying some altered form of the base collection's behavior.
///
/// Default implementations of all requirements are provided, forwarding their
/// implementations to the `Base` collection instance.
public protocol CollectionAdapter: Collection {
/// The type of the underlying collection being adapted.
associatedtype Base: Collection
/// The instance of the underlying collection being adapted.
var base: Base { get }
// Redeclarations of associated types allow us to attach defaults.
associatedtype Index = Base.Index
associatedtype Element = Base.Element
}
/// Default implementations depending on the `Index` type.
extension CollectionAdapter where Index == Base.Index {
public var startIndex: Index { base.startIndex }
public var endIndex: Index { base.endIndex }
public func index(after i: Index) -> Index { base.index(after: i) }
}
/// Default implementations depending on the `Index` and `Element` types.
extension CollectionAdapter where Index == Base.Index, Element == Base.Element {
public subscript(i: Index) -> Element { base[i] }
}
extension BidirectionalCollection
where Self: CollectionAdapter,
Base: BidirectionalCollection, Index == Base.Index
{
public func index(before i: Index) -> Index { base.index(before: i) }
}
public struct FilterCollection<Base: Collection>: CollectionAdapter {
public typealias Index = Base.Index // https://bugs.swift.org/browse/SR-12923
public var base: Base
var isIncluded: (Base.Element)->Bool // https://bugs.swift.org/browse/SR-12923
private func advancedTillValid(_ i: Index) -> Index {
var j = i
while j != endIndex && !isIncluded(base[j]) {
j = base.index(after: j)
}
return j
}
public var startIndex: Index {
return advancedTillValid(base.startIndex)
}
public func index(after i: Index) -> Index {
return advancedTillValid(base.index(after: i))
}
}
extension FilterCollection: BidirectionalCollection
where Base: BidirectionalCollection
{
public func index(before i: Index) -> Index {
var j = base.index(before: i)
while !isIncluded(base[j]) {
if j == base.startIndex { return i }
j = base.index(before: j)
}
return j
}
}
public struct MapCollection<Base: Collection, Element>: CollectionAdapter, Collection {
public typealias Index = Base.Index // https://bugs.swift.org/browse/SR-12923
public typealias Element = Element
public var base: Base
var mapping: (Base.Element)->Element
public subscript(_ i: Index) -> Element { mapping(base[i]) }
}
extension MapCollection: BidirectionalCollection
where Base: BidirectionalCollection {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment