mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
6217 lines
178 KiB
Swift
6217 lines
178 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
import StdlibUnittest
|
|
|
|
/// State shared by all generators of a MinimalSequence.
|
|
internal class _MinimalIteratorSharedState<T> {
|
|
internal init(_ data: [T]) {
|
|
self.data = data
|
|
}
|
|
|
|
internal let data: [T]
|
|
internal var i: Int = 0
|
|
internal var underestimatedCount: Int = 0
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// MinimalIterator
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// An IteratorProtocol that implements the protocol contract in the most
|
|
/// narrow way possible.
|
|
///
|
|
/// This generator will return `nil` only once.
|
|
public struct MinimalIterator<T> : IteratorProtocol {
|
|
public init<S : Sequence>(_ s: S) where S.Element == T {
|
|
self._sharedState = _MinimalIteratorSharedState(Array(s))
|
|
}
|
|
|
|
public init(_ data: [T]) {
|
|
self._sharedState = _MinimalIteratorSharedState(data)
|
|
}
|
|
|
|
internal init(_ _sharedState: _MinimalIteratorSharedState<T>) {
|
|
self._sharedState = _sharedState
|
|
}
|
|
|
|
public func next() -> T? {
|
|
if _sharedState.i == _sharedState.data.count {
|
|
return nil
|
|
}
|
|
defer { _sharedState.i += 1 }
|
|
return _sharedState.data[_sharedState.i]
|
|
}
|
|
|
|
internal let _sharedState: _MinimalIteratorSharedState<T>
|
|
}
|
|
|
|
// A protocol to identify MinimalIterator.
|
|
public protocol _MinimalIterator {}
|
|
extension MinimalIterator : _MinimalIterator {}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// MinimalSequence
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
public enum UnderestimatedCountBehavior {
|
|
/// Return the actual number of elements.
|
|
case precise
|
|
|
|
/// Return the actual number of elements divided by 2.
|
|
case half
|
|
|
|
/// Return an overestimated count. Useful to test how algorithms reserve
|
|
/// memory.
|
|
case overestimate
|
|
|
|
/// Return the provided value.
|
|
case value(Int)
|
|
}
|
|
|
|
/// A Sequence that implements the protocol contract in the most
|
|
/// narrow way possible.
|
|
///
|
|
/// This sequence is consumed when its generator is advanced.
|
|
public struct MinimalSequence<T> : Sequence, CustomDebugStringConvertible {
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == T {
|
|
let data = Array(elements)
|
|
self._sharedState = _MinimalIteratorSharedState(data)
|
|
|
|
switch underestimatedCount {
|
|
case .precise:
|
|
self._sharedState.underestimatedCount = data.count
|
|
|
|
case .half:
|
|
self._sharedState.underestimatedCount = data.count / 2
|
|
|
|
case .overestimate:
|
|
self._sharedState.underestimatedCount = data.count * 3 + 5
|
|
|
|
case .value(let count):
|
|
self._sharedState.underestimatedCount = count
|
|
}
|
|
}
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<T> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return MinimalIterator(_sharedState)
|
|
}
|
|
|
|
public var underestimatedCount: Int {
|
|
return Swift.max(0, self._sharedState.underestimatedCount - self._sharedState.i)
|
|
}
|
|
|
|
public var debugDescription: String {
|
|
return "MinimalSequence(\(_sharedState.data[_sharedState.i..<_sharedState.data.count]))"
|
|
}
|
|
|
|
internal let _sharedState: _MinimalIteratorSharedState<T>
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Index invalidation checking
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
internal enum _CollectionOperation : Equatable {
|
|
case reserveCapacity(capacity: Int)
|
|
case append
|
|
case appendContentsOf(count: Int)
|
|
case replaceRange(subRange: Range<Int>, replacementCount: Int)
|
|
case insert(atIndex: Int)
|
|
case insertContentsOf(atIndex: Int, count: Int)
|
|
case removeAtIndex(index: Int)
|
|
case removeLast
|
|
case removeRange(subRange: Range<Int>)
|
|
case removeAll(keepCapacity: Bool)
|
|
|
|
internal func _applyTo(
|
|
elementsLastMutatedStateIds: [Int],
|
|
endIndexLastMutatedStateId: Int,
|
|
nextStateId: Int
|
|
) -> ([Int], Int) {
|
|
var newElementsIds = elementsLastMutatedStateIds
|
|
var newEndIndexId = endIndexLastMutatedStateId
|
|
switch self {
|
|
case .reserveCapacity:
|
|
let invalidIndices = newElementsIds.indices
|
|
newElementsIds.replaceSubrange(
|
|
invalidIndices,
|
|
with: repeatElement(nextStateId, count: invalidIndices.count))
|
|
newEndIndexId = nextStateId
|
|
|
|
case .append:
|
|
newElementsIds.append(nextStateId)
|
|
newEndIndexId = nextStateId
|
|
|
|
case .appendContentsOf(let count):
|
|
newElementsIds.append(contentsOf:
|
|
repeatElement(nextStateId, count: count))
|
|
newEndIndexId = nextStateId
|
|
|
|
case .replaceRange(let subRange, let replacementCount):
|
|
newElementsIds.replaceSubrange(
|
|
subRange,
|
|
with: repeatElement(nextStateId, count: replacementCount))
|
|
|
|
let invalidIndices = subRange.lowerBound..<newElementsIds.endIndex
|
|
newElementsIds.replaceSubrange(
|
|
invalidIndices,
|
|
with: repeatElement(nextStateId, count: invalidIndices.count))
|
|
newEndIndexId = nextStateId
|
|
|
|
case .insert(let atIndex):
|
|
newElementsIds.insert(nextStateId, at: atIndex)
|
|
|
|
let invalidIndices = atIndex..<newElementsIds.endIndex
|
|
newElementsIds.replaceSubrange(
|
|
invalidIndices,
|
|
with: repeatElement(nextStateId, count: invalidIndices.count))
|
|
newEndIndexId = nextStateId
|
|
|
|
case .insertContentsOf(let atIndex, let count):
|
|
newElementsIds.insert(
|
|
contentsOf: repeatElement(nextStateId, count: count),
|
|
at: atIndex)
|
|
|
|
let invalidIndices = atIndex..<newElementsIds.endIndex
|
|
newElementsIds.replaceSubrange(
|
|
invalidIndices,
|
|
with: repeatElement(nextStateId, count: invalidIndices.count))
|
|
newEndIndexId = nextStateId
|
|
|
|
case .removeAtIndex(let index):
|
|
newElementsIds.remove(at: index)
|
|
|
|
let invalidIndices = index..<newElementsIds.endIndex
|
|
newElementsIds.replaceSubrange(
|
|
invalidIndices,
|
|
with: repeatElement(nextStateId, count: invalidIndices.count))
|
|
newEndIndexId = nextStateId
|
|
|
|
case .removeLast:
|
|
newElementsIds.removeLast()
|
|
newEndIndexId = nextStateId
|
|
|
|
case .removeRange(let subRange):
|
|
newElementsIds.removeSubrange(subRange)
|
|
|
|
let invalidIndices = subRange.lowerBound..<newElementsIds.endIndex
|
|
newElementsIds.replaceSubrange(
|
|
invalidIndices,
|
|
with: repeatElement(nextStateId, count: invalidIndices.count))
|
|
newEndIndexId = nextStateId
|
|
|
|
case .removeAll(let keepCapacity):
|
|
newElementsIds.removeAll(keepingCapacity: keepCapacity)
|
|
newEndIndexId = nextStateId
|
|
}
|
|
return (newElementsIds, newEndIndexId)
|
|
}
|
|
}
|
|
|
|
internal func == (
|
|
lhs: _CollectionOperation,
|
|
rhs: _CollectionOperation
|
|
) -> Bool {
|
|
switch (lhs, rhs) {
|
|
case (.reserveCapacity(let lhsCapacity), .reserveCapacity(let rhsCapacity)):
|
|
return lhsCapacity == rhsCapacity
|
|
|
|
case (.append, .append):
|
|
return true
|
|
|
|
case (.appendContentsOf(let lhsCount), .appendContentsOf(let rhsCount)):
|
|
return lhsCount == rhsCount
|
|
|
|
case (
|
|
.replaceRange(let lhsSubRange, let lhsReplacementCount),
|
|
.replaceRange(let rhsSubRange, let rhsReplacementCount)):
|
|
|
|
return lhsSubRange == rhsSubRange &&
|
|
lhsReplacementCount == rhsReplacementCount
|
|
|
|
case (.insert(let lhsAtIndex), .insert(let rhsAtIndex)):
|
|
return lhsAtIndex == rhsAtIndex
|
|
|
|
case (
|
|
.insertContentsOf(let lhsAtIndex, let lhsCount),
|
|
.insertContentsOf(let rhsAtIndex, let rhsCount)):
|
|
|
|
return lhsAtIndex == rhsAtIndex && lhsCount == rhsCount
|
|
|
|
case (.removeAtIndex(let lhsIndex), .removeAtIndex(let rhsIndex)):
|
|
return lhsIndex == rhsIndex
|
|
|
|
case (.removeLast, .removeLast):
|
|
return true
|
|
|
|
case (.removeRange(let lhsSubRange), .removeRange(let rhsSubRange)):
|
|
return lhsSubRange == rhsSubRange
|
|
|
|
case (.removeAll(let lhsKeepCapacity), .removeAll(let rhsKeepCapacity)):
|
|
return lhsKeepCapacity == rhsKeepCapacity
|
|
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
public struct _CollectionState : Equatable, Hashable {
|
|
internal static var _nextUnusedState: Int = 0
|
|
internal static var _namedStates: [String : _CollectionState] = [:]
|
|
|
|
internal let _id: Int
|
|
internal let _elementsLastMutatedStateIds: [Int]
|
|
internal let _endIndexLastMutatedStateId: Int
|
|
|
|
internal init(
|
|
id: Int,
|
|
elementsLastMutatedStateIds: [Int],
|
|
endIndexLastMutatedStateId: Int) {
|
|
self._id = id
|
|
self._elementsLastMutatedStateIds = elementsLastMutatedStateIds
|
|
self._endIndexLastMutatedStateId = endIndexLastMutatedStateId
|
|
}
|
|
|
|
public init(newRootStateForElementCount count: Int) {
|
|
self._id = _CollectionState._nextUnusedState
|
|
_CollectionState._nextUnusedState += 1
|
|
self._elementsLastMutatedStateIds =
|
|
Array(repeatElement(self._id, count: count))
|
|
self._endIndexLastMutatedStateId = self._id
|
|
}
|
|
|
|
internal init(name: String, elementCount: Int) {
|
|
if let result = _CollectionState._namedStates[name] {
|
|
self = result
|
|
} else {
|
|
self = _CollectionState(newRootStateForElementCount: elementCount)
|
|
_CollectionState._namedStates[name] = self
|
|
}
|
|
}
|
|
|
|
public func hash(into hasher: inout Hasher) {
|
|
hasher.combine(_id)
|
|
}
|
|
}
|
|
|
|
public func == (lhs: _CollectionState, rhs: _CollectionState) -> Bool {
|
|
return lhs._id == rhs._id
|
|
}
|
|
|
|
internal struct _CollectionStateTransition {
|
|
internal let _previousState: _CollectionState
|
|
internal let _operation: _CollectionOperation
|
|
internal let _nextState: _CollectionState
|
|
|
|
internal static var _allTransitions:
|
|
[_CollectionState : Box<[_CollectionStateTransition]>] = [:]
|
|
|
|
internal init(
|
|
previousState: _CollectionState,
|
|
operation: _CollectionOperation,
|
|
nextState: _CollectionState
|
|
) {
|
|
var transitions =
|
|
_CollectionStateTransition._allTransitions[previousState]
|
|
if transitions == nil {
|
|
transitions = Box<[_CollectionStateTransition]>([])
|
|
_CollectionStateTransition._allTransitions[previousState] = transitions
|
|
}
|
|
if let i = transitions!.value.firstIndex(where: { $0._operation == operation }) {
|
|
self = transitions!.value[i]
|
|
return
|
|
}
|
|
self._previousState = previousState
|
|
self._operation = operation
|
|
self._nextState = nextState
|
|
transitions!.value.append(self)
|
|
}
|
|
|
|
internal init(
|
|
previousState: _CollectionState,
|
|
operation: _CollectionOperation
|
|
) {
|
|
let nextStateId = _CollectionState._nextUnusedState
|
|
_CollectionState._nextUnusedState += 1
|
|
let (newElementStates, newEndIndexState) = operation._applyTo(
|
|
elementsLastMutatedStateIds: previousState._elementsLastMutatedStateIds,
|
|
endIndexLastMutatedStateId: previousState._endIndexLastMutatedStateId,
|
|
nextStateId: nextStateId)
|
|
let nextState = _CollectionState(
|
|
id: nextStateId,
|
|
elementsLastMutatedStateIds: newElementStates,
|
|
endIndexLastMutatedStateId: newEndIndexState)
|
|
self = _CollectionStateTransition(
|
|
previousState: previousState,
|
|
operation: operation,
|
|
nextState: nextState)
|
|
}
|
|
}
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// MinimalIndex
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// Asserts that the two indices are allowed to participate in a binary
|
|
/// operation.
|
|
internal func _expectCompatibleIndices(
|
|
_ first: MinimalIndex,
|
|
_ second: MinimalIndex,
|
|
|
|
_ message: @autoclosure () -> String = "",
|
|
stackTrace: SourceLocStack = SourceLocStack(),
|
|
showFrame: Bool = true,
|
|
file: String = #file, line: UInt = #line
|
|
) {
|
|
if first._collectionState._id == second._collectionState._id {
|
|
// Fast path: the indices are derived from the same state.
|
|
return
|
|
}
|
|
|
|
// The indices are derived from different states. Check that they point
|
|
// to a self-consistent view of the collection.
|
|
if first._collectionState._id > second._collectionState._id {
|
|
return _expectCompatibleIndices(second, first)
|
|
}
|
|
|
|
func lastMutatedStateId(
|
|
of i: MinimalIndex,
|
|
in state: _CollectionState
|
|
) -> Int {
|
|
let offset = i.position
|
|
if offset == state._elementsLastMutatedStateIds.endIndex {
|
|
return state._id
|
|
}
|
|
return state._elementsLastMutatedStateIds[offset]
|
|
}
|
|
|
|
let newestCollectionState = second._collectionState
|
|
let expectedFirstIndexLastMutatedStateId =
|
|
lastMutatedStateId(of: first, in: newestCollectionState)
|
|
|
|
expectEqual(
|
|
expectedFirstIndexLastMutatedStateId,
|
|
first._collectionState._id,
|
|
"Indices are not compatible:\n" +
|
|
"first: \(first)\n" +
|
|
"second: \(second)\n" +
|
|
"first element last mutated in state id: \(first._collectionState._id)\n" +
|
|
"expected state id: \(expectedFirstIndexLastMutatedStateId)\n" +
|
|
"newest collection state: \(newestCollectionState)",
|
|
stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
|
|
|
|
// To make writing assertions easier, perform a trap.
|
|
if expectedFirstIndexLastMutatedStateId != first._collectionState._id {
|
|
fatalError("Indices are not compatible")
|
|
}
|
|
}
|
|
|
|
public struct MinimalIndex : Comparable {
|
|
public init(
|
|
collectionState: _CollectionState,
|
|
position: Int,
|
|
startIndex: Int,
|
|
endIndex: Int
|
|
) {
|
|
expectTrapping(
|
|
position,
|
|
in: startIndex...endIndex)
|
|
self = MinimalIndex(
|
|
_collectionState: collectionState,
|
|
uncheckedPosition: position)
|
|
}
|
|
|
|
internal init(
|
|
_collectionState: _CollectionState,
|
|
uncheckedPosition: Int
|
|
) {
|
|
self._collectionState = _collectionState
|
|
self.position = uncheckedPosition
|
|
}
|
|
|
|
public let _collectionState: _CollectionState
|
|
public let position: Int
|
|
|
|
public static var trapOnRangeCheckFailure = ResettableValue(true)
|
|
|
|
}
|
|
|
|
public func == (lhs: MinimalIndex, rhs: MinimalIndex) -> Bool {
|
|
_expectCompatibleIndices(lhs, rhs)
|
|
return lhs.position == rhs.position
|
|
}
|
|
|
|
public func < (lhs: MinimalIndex, rhs: MinimalIndex) -> Bool {
|
|
_expectCompatibleIndices(lhs, rhs)
|
|
return lhs.position < rhs.position
|
|
}
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// MinimalStrideableIndex
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// Asserts that the two indices are allowed to participate in a binary
|
|
/// operation.
|
|
internal func _expectCompatibleIndices(
|
|
_ first: MinimalStrideableIndex,
|
|
_ second: MinimalStrideableIndex,
|
|
|
|
_ message: @autoclosure () -> String = "",
|
|
stackTrace: SourceLocStack = SourceLocStack(),
|
|
showFrame: Bool = true,
|
|
file: String = #file, line: UInt = #line
|
|
) {
|
|
if first._collectionState._id == second._collectionState._id {
|
|
// Fast path: the indices are derived from the same state.
|
|
return
|
|
}
|
|
|
|
// The indices are derived from different states. Check that they point
|
|
// to a self-consistent view of the collection.
|
|
if first._collectionState._id > second._collectionState._id {
|
|
return _expectCompatibleIndices(second, first)
|
|
}
|
|
|
|
func lastMutatedStateId(
|
|
of i: MinimalStrideableIndex,
|
|
in state: _CollectionState
|
|
) -> Int {
|
|
let offset = i.position
|
|
if offset == state._elementsLastMutatedStateIds.endIndex {
|
|
return state._id
|
|
}
|
|
return state._elementsLastMutatedStateIds[offset]
|
|
}
|
|
|
|
let newestCollectionState = second._collectionState
|
|
let expectedFirstIndexLastMutatedStateId =
|
|
lastMutatedStateId(of: first, in: newestCollectionState)
|
|
|
|
expectEqual(
|
|
expectedFirstIndexLastMutatedStateId,
|
|
first._collectionState._id,
|
|
"Indices are not compatible:\n" +
|
|
"first: \(first)\n" +
|
|
"second: \(second)\n" +
|
|
"first element last mutated in state id: \(first._collectionState._id)\n" +
|
|
"expected state id: \(expectedFirstIndexLastMutatedStateId)\n" +
|
|
"newest collection state: \(newestCollectionState)",
|
|
stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
|
|
|
|
// To make writing assertions easier, perform a trap.
|
|
if expectedFirstIndexLastMutatedStateId != first._collectionState._id {
|
|
fatalError("Indices are not compatible")
|
|
}
|
|
}
|
|
|
|
public struct MinimalStrideableIndex : Comparable {
|
|
public init(
|
|
collectionState: _CollectionState,
|
|
position: Int,
|
|
startIndex: Int,
|
|
endIndex: Int
|
|
) {
|
|
expectTrapping(
|
|
position,
|
|
in: startIndex...endIndex)
|
|
self = MinimalStrideableIndex(
|
|
_collectionState: collectionState,
|
|
uncheckedPosition: position)
|
|
}
|
|
|
|
internal init(
|
|
_collectionState: _CollectionState,
|
|
uncheckedPosition: Int
|
|
) {
|
|
self._collectionState = _collectionState
|
|
self.position = uncheckedPosition
|
|
}
|
|
|
|
public let _collectionState: _CollectionState
|
|
public let position: Int
|
|
|
|
public static var trapOnRangeCheckFailure = ResettableValue(true)
|
|
|
|
public var timesAdvancedCalled = ResettableValue(0)
|
|
public var timesDistanceCalled = ResettableValue(0)
|
|
}
|
|
|
|
public func == (lhs: MinimalStrideableIndex, rhs: MinimalStrideableIndex) -> Bool {
|
|
_expectCompatibleIndices(lhs, rhs)
|
|
return lhs.position == rhs.position
|
|
}
|
|
|
|
public func < (lhs: MinimalStrideableIndex, rhs: MinimalStrideableIndex) -> Bool {
|
|
_expectCompatibleIndices(lhs, rhs)
|
|
return lhs.position < rhs.position
|
|
}
|
|
|
|
|
|
extension MinimalStrideableIndex : Strideable {
|
|
public typealias Stride = Int
|
|
|
|
public func distance(to other: MinimalStrideableIndex) -> Int {
|
|
timesDistanceCalled.value += 1
|
|
_expectCompatibleIndices(self, other)
|
|
return other.position - position
|
|
}
|
|
|
|
public func advanced(by n: Int) -> MinimalStrideableIndex {
|
|
timesAdvancedCalled.value += 1
|
|
return MinimalStrideableIndex(
|
|
_collectionState: _collectionState,
|
|
uncheckedPosition: position + n)
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Minimal***[Mutable]?Collection
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
/// A minimal implementation of `Collection` with extra checks.
|
|
public struct MinimalCollection<T> : Collection {
|
|
/// Creates a collection with given contents, but a unique modification
|
|
/// history. No other instance has the same modification history.
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == T {
|
|
self._elements = Array(elements)
|
|
|
|
self._collectionState = _CollectionState(
|
|
newRootStateForElementCount: self._elements.count)
|
|
|
|
switch underestimatedCount {
|
|
case .precise:
|
|
self.underestimatedCount = _elements.count
|
|
|
|
case .half:
|
|
self.underestimatedCount = _elements.count / 2
|
|
|
|
case .overestimate:
|
|
self.underestimatedCount = _elements.count * 3 + 5
|
|
|
|
case .value(let count):
|
|
self.underestimatedCount = count
|
|
}
|
|
}
|
|
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<T> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return MinimalIterator(_elements)
|
|
}
|
|
|
|
public typealias Index = MinimalIndex
|
|
|
|
internal func _index(forPosition i: Int) -> MinimalIndex {
|
|
return MinimalIndex(
|
|
collectionState: _collectionState,
|
|
position: i,
|
|
startIndex: _elements.startIndex,
|
|
endIndex: _elements.endIndex)
|
|
}
|
|
|
|
internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
|
|
return MinimalIndex(
|
|
_collectionState: _collectionState,
|
|
uncheckedPosition: i)
|
|
}
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.startIndex)
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.endIndex)
|
|
}
|
|
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ index: MinimalIndex,
|
|
bounds: Range<MinimalIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: index.position),
|
|
index)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
index.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ range: Range<MinimalIndex>,
|
|
bounds: Range<MinimalIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.lowerBound.position),
|
|
range.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.upperBound.position),
|
|
range.upperBound)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
range.lowerBound.position..<range.upperBound.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func index(after i: MinimalIndex) -> MinimalIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _uncheckedIndex(forPosition: i.position + 1)
|
|
}
|
|
|
|
|
|
public func distance(from start: MinimalIndex, to end: MinimalIndex)
|
|
-> Int {
|
|
precondition(start <= end,
|
|
"Only BidirectionalCollections can have end come before start")
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if start != endIndex {
|
|
_failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
|
|
}
|
|
if end != endIndex {
|
|
_failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
|
|
}
|
|
return end.position - start.position
|
|
}
|
|
|
|
public func index(_ i: Index, offsetBy n: Int) -> Index {
|
|
precondition(n >= 0,
|
|
"Only BidirectionalCollections can be advanced by a negative amount")
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if i != endIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
}
|
|
return _index(forPosition: i.position + n)
|
|
}
|
|
|
|
public subscript(i: MinimalIndex) -> T {
|
|
get {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _elements[i.position]
|
|
}
|
|
}
|
|
|
|
public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalCollection<T>> {
|
|
get {
|
|
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
}
|
|
|
|
|
|
public var underestimatedCount: Int
|
|
|
|
internal var _elements: [T]
|
|
internal let _collectionState: _CollectionState
|
|
}
|
|
|
|
|
|
/// A minimal implementation of `Collection` with extra checks.
|
|
public struct MinimalRangeReplaceableCollection<T> : Collection, RangeReplaceableCollection {
|
|
/// Creates a collection with given contents, but a unique modification
|
|
/// history. No other instance has the same modification history.
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == T {
|
|
self._elements = Array(elements)
|
|
|
|
self._collectionState = _CollectionState(
|
|
newRootStateForElementCount: self._elements.count)
|
|
|
|
switch underestimatedCount {
|
|
case .precise:
|
|
self.underestimatedCount = _elements.count
|
|
|
|
case .half:
|
|
self.underestimatedCount = _elements.count / 2
|
|
|
|
case .overestimate:
|
|
self.underestimatedCount = _elements.count * 3 + 5
|
|
|
|
case .value(let count):
|
|
self.underestimatedCount = count
|
|
}
|
|
}
|
|
|
|
public init() {
|
|
self.underestimatedCount = 0
|
|
self._elements = []
|
|
self._collectionState =
|
|
_CollectionState(name: "\(type(of: self))", elementCount: 0)
|
|
}
|
|
|
|
public init<S : Sequence>(_ elements: S) where S.Element == T {
|
|
self.underestimatedCount = 0
|
|
self._elements = Array(elements)
|
|
self._collectionState =
|
|
_CollectionState(newRootStateForElementCount: self._elements.count)
|
|
}
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<T> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return MinimalIterator(_elements)
|
|
}
|
|
|
|
public typealias Index = MinimalIndex
|
|
|
|
internal func _index(forPosition i: Int) -> MinimalIndex {
|
|
return MinimalIndex(
|
|
collectionState: _collectionState,
|
|
position: i,
|
|
startIndex: _elements.startIndex,
|
|
endIndex: _elements.endIndex)
|
|
}
|
|
|
|
internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
|
|
return MinimalIndex(
|
|
_collectionState: _collectionState,
|
|
uncheckedPosition: i)
|
|
}
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.startIndex)
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.endIndex)
|
|
}
|
|
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ index: MinimalIndex,
|
|
bounds: Range<MinimalIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: index.position),
|
|
index)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
index.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ range: Range<MinimalIndex>,
|
|
bounds: Range<MinimalIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.lowerBound.position),
|
|
range.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.upperBound.position),
|
|
range.upperBound)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
range.lowerBound.position..<range.upperBound.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func index(after i: MinimalIndex) -> MinimalIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _uncheckedIndex(forPosition: i.position + 1)
|
|
}
|
|
|
|
|
|
public func distance(from start: MinimalIndex, to end: MinimalIndex)
|
|
-> Int {
|
|
precondition(start <= end,
|
|
"Only BidirectionalCollections can have end come before start")
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if start != endIndex {
|
|
_failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
|
|
}
|
|
if end != endIndex {
|
|
_failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
|
|
}
|
|
return end.position - start.position
|
|
}
|
|
|
|
public func index(_ i: Index, offsetBy n: Int) -> Index {
|
|
precondition(n >= 0,
|
|
"Only BidirectionalCollections can be advanced by a negative amount")
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if i != endIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
}
|
|
return _index(forPosition: i.position + n)
|
|
}
|
|
|
|
public subscript(i: MinimalIndex) -> T {
|
|
get {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _elements[i.position]
|
|
}
|
|
}
|
|
|
|
public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalRangeReplaceableCollection<T>> {
|
|
get {
|
|
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
}
|
|
|
|
public mutating func reserveCapacity(_ n: Int) {
|
|
_willMutate(.reserveCapacity(capacity: n))
|
|
_elements.reserveCapacity(n)
|
|
reservedCapacity = Swift.max(reservedCapacity, n)
|
|
}
|
|
|
|
public mutating func append(_ x: T) {
|
|
_willMutate(.append)
|
|
_elements.append(x)
|
|
}
|
|
|
|
public mutating func append<S : Sequence>(contentsOf newElements: S)
|
|
where S.Element == T {
|
|
let oldCount = count
|
|
_elements.append(contentsOf: newElements)
|
|
let newCount = count
|
|
_willMutate(.appendContentsOf(count: newCount - oldCount))
|
|
}
|
|
|
|
public mutating func replaceSubrange<C>(
|
|
_ subRange: Range<MinimalIndex>,
|
|
with newElements: C
|
|
) where C : Collection, C.Element == T {
|
|
let oldCount = count
|
|
_elements.replaceSubrange(
|
|
subRange.lowerBound.position..<subRange.upperBound.position,
|
|
with: newElements)
|
|
let newCount = count
|
|
_willMutate(.replaceRange(
|
|
subRange: subRange.lowerBound.position..<subRange.upperBound.position,
|
|
replacementCount:
|
|
subRange.upperBound.position - subRange.lowerBound.position
|
|
+ newCount - oldCount))
|
|
}
|
|
|
|
public mutating func insert(_ newElement: T, at i: MinimalIndex) {
|
|
_willMutate(.insert(atIndex: i.position))
|
|
_elements.insert(newElement, at: i.position)
|
|
}
|
|
|
|
public mutating func insert<S : Collection>(
|
|
contentsOf newElements: S, at i: MinimalIndex
|
|
) where S.Element == T {
|
|
let oldCount = count
|
|
_elements.insert(contentsOf: newElements, at: i.position)
|
|
let newCount = count
|
|
|
|
if newCount - oldCount != 0 {
|
|
_willMutate(.insertContentsOf(
|
|
atIndex: i.position,
|
|
count: newCount - oldCount))
|
|
}
|
|
}
|
|
|
|
@discardableResult
|
|
public mutating func remove(at i: MinimalIndex) -> T {
|
|
_willMutate(.removeAtIndex(index: i.position))
|
|
return _elements.remove(at: i.position)
|
|
}
|
|
|
|
@discardableResult
|
|
public mutating func removeLast() -> T {
|
|
_willMutate(.removeLast)
|
|
return _elements.removeLast()
|
|
}
|
|
|
|
public mutating func removeSubrange(_ subRange: Range<MinimalIndex>) {
|
|
if !subRange.isEmpty {
|
|
_willMutate(.removeRange(
|
|
subRange: subRange.lowerBound.position..<subRange.upperBound.position))
|
|
}
|
|
_elements.removeSubrange(
|
|
subRange.lowerBound.position..<subRange.upperBound.position
|
|
)
|
|
}
|
|
|
|
public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
|
|
_willMutate(.removeAll(keepCapacity: keepCapacity))
|
|
// Ignore the value of `keepCapacity`.
|
|
_elements.removeAll(keepingCapacity: false)
|
|
}
|
|
|
|
internal mutating func _willMutate(_ operation: _CollectionOperation) {
|
|
_collectionState = _CollectionStateTransition(
|
|
previousState: _collectionState,
|
|
operation: operation)._nextState
|
|
}
|
|
|
|
public var underestimatedCount: Int
|
|
public var reservedCapacity: Int = 0
|
|
|
|
internal var _elements: [T]
|
|
internal var _collectionState: _CollectionState
|
|
}
|
|
|
|
|
|
/// A minimal implementation of `Collection` with extra checks.
|
|
public struct MinimalMutableCollection<T> : Collection, MutableCollection {
|
|
/// Creates a collection with given contents, but a unique modification
|
|
/// history. No other instance has the same modification history.
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == T {
|
|
self._elements = Array(elements)
|
|
|
|
self._collectionState = _CollectionState(
|
|
newRootStateForElementCount: self._elements.count)
|
|
|
|
switch underestimatedCount {
|
|
case .precise:
|
|
self.underestimatedCount = _elements.count
|
|
|
|
case .half:
|
|
self.underestimatedCount = _elements.count / 2
|
|
|
|
case .overestimate:
|
|
self.underestimatedCount = _elements.count * 3 + 5
|
|
|
|
case .value(let count):
|
|
self.underestimatedCount = count
|
|
}
|
|
}
|
|
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<T> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return MinimalIterator(_elements)
|
|
}
|
|
|
|
public typealias Index = MinimalIndex
|
|
|
|
internal func _index(forPosition i: Int) -> MinimalIndex {
|
|
return MinimalIndex(
|
|
collectionState: _collectionState,
|
|
position: i,
|
|
startIndex: _elements.startIndex,
|
|
endIndex: _elements.endIndex)
|
|
}
|
|
|
|
internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
|
|
return MinimalIndex(
|
|
_collectionState: _collectionState,
|
|
uncheckedPosition: i)
|
|
}
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.startIndex)
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.endIndex)
|
|
}
|
|
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ index: MinimalIndex,
|
|
bounds: Range<MinimalIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: index.position),
|
|
index)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
index.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ range: Range<MinimalIndex>,
|
|
bounds: Range<MinimalIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.lowerBound.position),
|
|
range.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.upperBound.position),
|
|
range.upperBound)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
range.lowerBound.position..<range.upperBound.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func index(after i: MinimalIndex) -> MinimalIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _uncheckedIndex(forPosition: i.position + 1)
|
|
}
|
|
|
|
|
|
public func distance(from start: MinimalIndex, to end: MinimalIndex)
|
|
-> Int {
|
|
precondition(start <= end,
|
|
"Only BidirectionalCollections can have end come before start")
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if start != endIndex {
|
|
_failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
|
|
}
|
|
if end != endIndex {
|
|
_failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
|
|
}
|
|
return end.position - start.position
|
|
}
|
|
|
|
public func index(_ i: Index, offsetBy n: Int) -> Index {
|
|
precondition(n >= 0,
|
|
"Only BidirectionalCollections can be advanced by a negative amount")
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if i != endIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
}
|
|
return _index(forPosition: i.position + n)
|
|
}
|
|
|
|
public subscript(i: MinimalIndex) -> T {
|
|
get {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _elements[i.position]
|
|
}
|
|
set {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
_elements[i.position] = newValue
|
|
}
|
|
}
|
|
|
|
public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalMutableCollection<T>> {
|
|
get {
|
|
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
set {
|
|
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
|
|
_writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
|
|
}
|
|
}
|
|
|
|
|
|
public var underestimatedCount: Int
|
|
|
|
internal var _elements: [T]
|
|
internal let _collectionState: _CollectionState
|
|
}
|
|
|
|
|
|
/// A minimal implementation of `Collection` with extra checks.
|
|
public struct MinimalMutableRangeReplaceableCollection<T> : Collection, MutableCollection, RangeReplaceableCollection {
|
|
/// Creates a collection with given contents, but a unique modification
|
|
/// history. No other instance has the same modification history.
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == T {
|
|
self._elements = Array(elements)
|
|
|
|
self._collectionState = _CollectionState(
|
|
newRootStateForElementCount: self._elements.count)
|
|
|
|
switch underestimatedCount {
|
|
case .precise:
|
|
self.underestimatedCount = _elements.count
|
|
|
|
case .half:
|
|
self.underestimatedCount = _elements.count / 2
|
|
|
|
case .overestimate:
|
|
self.underestimatedCount = _elements.count * 3 + 5
|
|
|
|
case .value(let count):
|
|
self.underestimatedCount = count
|
|
}
|
|
}
|
|
|
|
public init() {
|
|
self.underestimatedCount = 0
|
|
self._elements = []
|
|
self._collectionState =
|
|
_CollectionState(name: "\(type(of: self))", elementCount: 0)
|
|
}
|
|
|
|
public init<S : Sequence>(_ elements: S) where S.Element == T {
|
|
self.underestimatedCount = 0
|
|
self._elements = Array(elements)
|
|
self._collectionState =
|
|
_CollectionState(newRootStateForElementCount: self._elements.count)
|
|
}
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<T> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return MinimalIterator(_elements)
|
|
}
|
|
|
|
public typealias Index = MinimalIndex
|
|
|
|
internal func _index(forPosition i: Int) -> MinimalIndex {
|
|
return MinimalIndex(
|
|
collectionState: _collectionState,
|
|
position: i,
|
|
startIndex: _elements.startIndex,
|
|
endIndex: _elements.endIndex)
|
|
}
|
|
|
|
internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
|
|
return MinimalIndex(
|
|
_collectionState: _collectionState,
|
|
uncheckedPosition: i)
|
|
}
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.startIndex)
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.endIndex)
|
|
}
|
|
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ index: MinimalIndex,
|
|
bounds: Range<MinimalIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: index.position),
|
|
index)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
index.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ range: Range<MinimalIndex>,
|
|
bounds: Range<MinimalIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.lowerBound.position),
|
|
range.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.upperBound.position),
|
|
range.upperBound)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
range.lowerBound.position..<range.upperBound.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func index(after i: MinimalIndex) -> MinimalIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _uncheckedIndex(forPosition: i.position + 1)
|
|
}
|
|
|
|
|
|
public func distance(from start: MinimalIndex, to end: MinimalIndex)
|
|
-> Int {
|
|
precondition(start <= end,
|
|
"Only BidirectionalCollections can have end come before start")
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if start != endIndex {
|
|
_failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
|
|
}
|
|
if end != endIndex {
|
|
_failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
|
|
}
|
|
return end.position - start.position
|
|
}
|
|
|
|
public func index(_ i: Index, offsetBy n: Int) -> Index {
|
|
precondition(n >= 0,
|
|
"Only BidirectionalCollections can be advanced by a negative amount")
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if i != endIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
}
|
|
return _index(forPosition: i.position + n)
|
|
}
|
|
|
|
public subscript(i: MinimalIndex) -> T {
|
|
get {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _elements[i.position]
|
|
}
|
|
set {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
_elements[i.position] = newValue
|
|
}
|
|
}
|
|
|
|
public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalMutableRangeReplaceableCollection<T>> {
|
|
get {
|
|
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
set {
|
|
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
|
|
_writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
|
|
}
|
|
}
|
|
|
|
public mutating func reserveCapacity(_ n: Int) {
|
|
_willMutate(.reserveCapacity(capacity: n))
|
|
_elements.reserveCapacity(n)
|
|
reservedCapacity = Swift.max(reservedCapacity, n)
|
|
}
|
|
|
|
public mutating func append(_ x: T) {
|
|
_willMutate(.append)
|
|
_elements.append(x)
|
|
}
|
|
|
|
public mutating func append<S : Sequence>(contentsOf newElements: S)
|
|
where S.Element == T {
|
|
let oldCount = count
|
|
_elements.append(contentsOf: newElements)
|
|
let newCount = count
|
|
_willMutate(.appendContentsOf(count: newCount - oldCount))
|
|
}
|
|
|
|
public mutating func replaceSubrange<C>(
|
|
_ subRange: Range<MinimalIndex>,
|
|
with newElements: C
|
|
) where C : Collection, C.Element == T {
|
|
let oldCount = count
|
|
_elements.replaceSubrange(
|
|
subRange.lowerBound.position..<subRange.upperBound.position,
|
|
with: newElements)
|
|
let newCount = count
|
|
_willMutate(.replaceRange(
|
|
subRange: subRange.lowerBound.position..<subRange.upperBound.position,
|
|
replacementCount:
|
|
subRange.upperBound.position - subRange.lowerBound.position
|
|
+ newCount - oldCount))
|
|
}
|
|
|
|
public mutating func insert(_ newElement: T, at i: MinimalIndex) {
|
|
_willMutate(.insert(atIndex: i.position))
|
|
_elements.insert(newElement, at: i.position)
|
|
}
|
|
|
|
public mutating func insert<S : Collection>(
|
|
contentsOf newElements: S, at i: MinimalIndex
|
|
) where S.Element == T {
|
|
let oldCount = count
|
|
_elements.insert(contentsOf: newElements, at: i.position)
|
|
let newCount = count
|
|
|
|
if newCount - oldCount != 0 {
|
|
_willMutate(.insertContentsOf(
|
|
atIndex: i.position,
|
|
count: newCount - oldCount))
|
|
}
|
|
}
|
|
|
|
@discardableResult
|
|
public mutating func remove(at i: MinimalIndex) -> T {
|
|
_willMutate(.removeAtIndex(index: i.position))
|
|
return _elements.remove(at: i.position)
|
|
}
|
|
|
|
@discardableResult
|
|
public mutating func removeLast() -> T {
|
|
_willMutate(.removeLast)
|
|
return _elements.removeLast()
|
|
}
|
|
|
|
public mutating func removeSubrange(_ subRange: Range<MinimalIndex>) {
|
|
if !subRange.isEmpty {
|
|
_willMutate(.removeRange(
|
|
subRange: subRange.lowerBound.position..<subRange.upperBound.position))
|
|
}
|
|
_elements.removeSubrange(
|
|
subRange.lowerBound.position..<subRange.upperBound.position
|
|
)
|
|
}
|
|
|
|
public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
|
|
_willMutate(.removeAll(keepCapacity: keepCapacity))
|
|
// Ignore the value of `keepCapacity`.
|
|
_elements.removeAll(keepingCapacity: false)
|
|
}
|
|
|
|
internal mutating func _willMutate(_ operation: _CollectionOperation) {
|
|
_collectionState = _CollectionStateTransition(
|
|
previousState: _collectionState,
|
|
operation: operation)._nextState
|
|
}
|
|
|
|
public var underestimatedCount: Int
|
|
public var reservedCapacity: Int = 0
|
|
|
|
internal var _elements: [T]
|
|
internal var _collectionState: _CollectionState
|
|
}
|
|
|
|
|
|
/// A minimal implementation of `Collection` with extra checks.
|
|
public struct MinimalBidirectionalCollection<T> : BidirectionalCollection {
|
|
/// Creates a collection with given contents, but a unique modification
|
|
/// history. No other instance has the same modification history.
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == T {
|
|
self._elements = Array(elements)
|
|
|
|
self._collectionState = _CollectionState(
|
|
newRootStateForElementCount: self._elements.count)
|
|
|
|
switch underestimatedCount {
|
|
case .precise:
|
|
self.underestimatedCount = _elements.count
|
|
|
|
case .half:
|
|
self.underestimatedCount = _elements.count / 2
|
|
|
|
case .overestimate:
|
|
self.underestimatedCount = _elements.count * 3 + 5
|
|
|
|
case .value(let count):
|
|
self.underestimatedCount = count
|
|
}
|
|
}
|
|
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<T> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return MinimalIterator(_elements)
|
|
}
|
|
|
|
public typealias Index = MinimalIndex
|
|
|
|
internal func _index(forPosition i: Int) -> MinimalIndex {
|
|
return MinimalIndex(
|
|
collectionState: _collectionState,
|
|
position: i,
|
|
startIndex: _elements.startIndex,
|
|
endIndex: _elements.endIndex)
|
|
}
|
|
|
|
internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
|
|
return MinimalIndex(
|
|
_collectionState: _collectionState,
|
|
uncheckedPosition: i)
|
|
}
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.startIndex)
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.endIndex)
|
|
}
|
|
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ index: MinimalIndex,
|
|
bounds: Range<MinimalIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: index.position),
|
|
index)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
index.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ range: Range<MinimalIndex>,
|
|
bounds: Range<MinimalIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.lowerBound.position),
|
|
range.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.upperBound.position),
|
|
range.upperBound)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
range.lowerBound.position..<range.upperBound.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func index(after i: MinimalIndex) -> MinimalIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _uncheckedIndex(forPosition: i.position + 1)
|
|
}
|
|
|
|
public func index(before i: MinimalIndex) -> MinimalIndex {
|
|
// FIXME: swift-3-indexing-model: perform a range check and use
|
|
// return _uncheckedIndex(forPosition: i.position - 1)
|
|
return _index(forPosition: i.position - 1)
|
|
}
|
|
|
|
public func distance(from start: MinimalIndex, to end: MinimalIndex)
|
|
-> Int {
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if start != endIndex {
|
|
_failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
|
|
}
|
|
if end != endIndex {
|
|
_failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
|
|
}
|
|
return end.position - start.position
|
|
}
|
|
|
|
public func index(_ i: Index, offsetBy n: Int) -> Index {
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if i != endIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
}
|
|
return _index(forPosition: i.position + n)
|
|
}
|
|
|
|
public subscript(i: MinimalIndex) -> T {
|
|
get {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _elements[i.position]
|
|
}
|
|
}
|
|
|
|
public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalBidirectionalCollection<T>> {
|
|
get {
|
|
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
}
|
|
|
|
|
|
public var underestimatedCount: Int
|
|
|
|
internal var _elements: [T]
|
|
internal let _collectionState: _CollectionState
|
|
}
|
|
|
|
/// A minimal implementation of `Collection` with extra checks.
|
|
public struct MinimalBidirectionalRandomAccessCollection<T> : BidirectionalCollection, RandomAccessCollection {
|
|
/// Creates a collection with given contents, but a unique modification
|
|
/// history. No other instance has the same modification history.
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == T {
|
|
self._elements = Array(elements)
|
|
|
|
self._collectionState = _CollectionState(
|
|
newRootStateForElementCount: self._elements.count)
|
|
|
|
switch underestimatedCount {
|
|
case .precise:
|
|
self.underestimatedCount = _elements.count
|
|
|
|
case .half:
|
|
self.underestimatedCount = _elements.count / 2
|
|
|
|
case .overestimate:
|
|
self.underestimatedCount = _elements.count * 3 + 5
|
|
|
|
case .value(let count):
|
|
self.underestimatedCount = count
|
|
}
|
|
}
|
|
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<T> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return MinimalIterator(_elements)
|
|
}
|
|
|
|
public typealias Index = MinimalIndex
|
|
|
|
internal func _index(forPosition i: Int) -> MinimalIndex {
|
|
return MinimalIndex(
|
|
collectionState: _collectionState,
|
|
position: i,
|
|
startIndex: _elements.startIndex,
|
|
endIndex: _elements.endIndex)
|
|
}
|
|
|
|
internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
|
|
return MinimalIndex(
|
|
_collectionState: _collectionState,
|
|
uncheckedPosition: i)
|
|
}
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.startIndex)
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.endIndex)
|
|
}
|
|
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ index: MinimalIndex,
|
|
bounds: Range<MinimalIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: index.position),
|
|
index)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
index.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ range: Range<MinimalIndex>,
|
|
bounds: Range<MinimalIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.lowerBound.position),
|
|
range.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.upperBound.position),
|
|
range.upperBound)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
range.lowerBound.position..<range.upperBound.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func index(after i: MinimalIndex) -> MinimalIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _uncheckedIndex(forPosition: i.position + 1)
|
|
}
|
|
|
|
public func index(before i: MinimalIndex) -> MinimalIndex {
|
|
// FIXME: swift-3-indexing-model: perform a range check and use
|
|
// return _uncheckedIndex(forPosition: i.position - 1)
|
|
return _index(forPosition: i.position - 1)
|
|
}
|
|
|
|
public func distance(from start: MinimalIndex, to end: MinimalIndex)
|
|
-> Int {
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if start != endIndex {
|
|
_failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
|
|
}
|
|
if end != endIndex {
|
|
_failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
|
|
}
|
|
return end.position - start.position
|
|
}
|
|
|
|
public func index(_ i: Index, offsetBy n: Int) -> Index {
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if i != endIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
}
|
|
return _index(forPosition: i.position + n)
|
|
}
|
|
|
|
public subscript(i: MinimalIndex) -> T {
|
|
get {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _elements[i.position]
|
|
}
|
|
}
|
|
|
|
public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalBidirectionalRandomAccessCollection<T>> {
|
|
get {
|
|
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
}
|
|
|
|
|
|
public var underestimatedCount: Int
|
|
|
|
internal var _elements: [T]
|
|
internal let _collectionState: _CollectionState
|
|
}
|
|
|
|
/// A minimal implementation of `Collection` with extra checks.
|
|
public struct MinimalRangeReplaceableBidirectionalCollection<T> : BidirectionalCollection, RangeReplaceableCollection {
|
|
/// Creates a collection with given contents, but a unique modification
|
|
/// history. No other instance has the same modification history.
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == T {
|
|
self._elements = Array(elements)
|
|
|
|
self._collectionState = _CollectionState(
|
|
newRootStateForElementCount: self._elements.count)
|
|
|
|
switch underestimatedCount {
|
|
case .precise:
|
|
self.underestimatedCount = _elements.count
|
|
|
|
case .half:
|
|
self.underestimatedCount = _elements.count / 2
|
|
|
|
case .overestimate:
|
|
self.underestimatedCount = _elements.count * 3 + 5
|
|
|
|
case .value(let count):
|
|
self.underestimatedCount = count
|
|
}
|
|
}
|
|
|
|
public init() {
|
|
self.underestimatedCount = 0
|
|
self._elements = []
|
|
self._collectionState =
|
|
_CollectionState(name: "\(type(of: self))", elementCount: 0)
|
|
}
|
|
|
|
public init<S : Sequence>(_ elements: S) where S.Element == T {
|
|
self.underestimatedCount = 0
|
|
self._elements = Array(elements)
|
|
self._collectionState =
|
|
_CollectionState(newRootStateForElementCount: self._elements.count)
|
|
}
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<T> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return MinimalIterator(_elements)
|
|
}
|
|
|
|
public typealias Index = MinimalIndex
|
|
|
|
internal func _index(forPosition i: Int) -> MinimalIndex {
|
|
return MinimalIndex(
|
|
collectionState: _collectionState,
|
|
position: i,
|
|
startIndex: _elements.startIndex,
|
|
endIndex: _elements.endIndex)
|
|
}
|
|
|
|
internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
|
|
return MinimalIndex(
|
|
_collectionState: _collectionState,
|
|
uncheckedPosition: i)
|
|
}
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.startIndex)
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.endIndex)
|
|
}
|
|
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ index: MinimalIndex,
|
|
bounds: Range<MinimalIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: index.position),
|
|
index)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
index.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ range: Range<MinimalIndex>,
|
|
bounds: Range<MinimalIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.lowerBound.position),
|
|
range.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.upperBound.position),
|
|
range.upperBound)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
range.lowerBound.position..<range.upperBound.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func index(after i: MinimalIndex) -> MinimalIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _uncheckedIndex(forPosition: i.position + 1)
|
|
}
|
|
|
|
public func index(before i: MinimalIndex) -> MinimalIndex {
|
|
// FIXME: swift-3-indexing-model: perform a range check and use
|
|
// return _uncheckedIndex(forPosition: i.position - 1)
|
|
return _index(forPosition: i.position - 1)
|
|
}
|
|
|
|
public func distance(from start: MinimalIndex, to end: MinimalIndex)
|
|
-> Int {
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if start != endIndex {
|
|
_failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
|
|
}
|
|
if end != endIndex {
|
|
_failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
|
|
}
|
|
return end.position - start.position
|
|
}
|
|
|
|
public func index(_ i: Index, offsetBy n: Int) -> Index {
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if i != endIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
}
|
|
return _index(forPosition: i.position + n)
|
|
}
|
|
|
|
public subscript(i: MinimalIndex) -> T {
|
|
get {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _elements[i.position]
|
|
}
|
|
}
|
|
|
|
public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalRangeReplaceableBidirectionalCollection<T>> {
|
|
get {
|
|
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
}
|
|
|
|
public mutating func reserveCapacity(_ n: Int) {
|
|
_willMutate(.reserveCapacity(capacity: n))
|
|
_elements.reserveCapacity(n)
|
|
reservedCapacity = Swift.max(reservedCapacity, n)
|
|
}
|
|
|
|
public mutating func append(_ x: T) {
|
|
_willMutate(.append)
|
|
_elements.append(x)
|
|
}
|
|
|
|
public mutating func append<S : Sequence>(contentsOf newElements: S)
|
|
where S.Element == T {
|
|
let oldCount = count
|
|
_elements.append(contentsOf: newElements)
|
|
let newCount = count
|
|
_willMutate(.appendContentsOf(count: newCount - oldCount))
|
|
}
|
|
|
|
public mutating func replaceSubrange<C>(
|
|
_ subRange: Range<MinimalIndex>,
|
|
with newElements: C
|
|
) where C : Collection, C.Element == T {
|
|
let oldCount = count
|
|
_elements.replaceSubrange(
|
|
subRange.lowerBound.position..<subRange.upperBound.position,
|
|
with: newElements)
|
|
let newCount = count
|
|
_willMutate(.replaceRange(
|
|
subRange: subRange.lowerBound.position..<subRange.upperBound.position,
|
|
replacementCount:
|
|
subRange.upperBound.position - subRange.lowerBound.position
|
|
+ newCount - oldCount))
|
|
}
|
|
|
|
public mutating func insert(_ newElement: T, at i: MinimalIndex) {
|
|
_willMutate(.insert(atIndex: i.position))
|
|
_elements.insert(newElement, at: i.position)
|
|
}
|
|
|
|
public mutating func insert<S : Collection>(
|
|
contentsOf newElements: S, at i: MinimalIndex
|
|
) where S.Element == T {
|
|
let oldCount = count
|
|
_elements.insert(contentsOf: newElements, at: i.position)
|
|
let newCount = count
|
|
|
|
if newCount - oldCount != 0 {
|
|
_willMutate(.insertContentsOf(
|
|
atIndex: i.position,
|
|
count: newCount - oldCount))
|
|
}
|
|
}
|
|
|
|
@discardableResult
|
|
public mutating func remove(at i: MinimalIndex) -> T {
|
|
_willMutate(.removeAtIndex(index: i.position))
|
|
return _elements.remove(at: i.position)
|
|
}
|
|
|
|
@discardableResult
|
|
public mutating func removeLast() -> T {
|
|
_willMutate(.removeLast)
|
|
return _elements.removeLast()
|
|
}
|
|
|
|
public mutating func removeSubrange(_ subRange: Range<MinimalIndex>) {
|
|
if !subRange.isEmpty {
|
|
_willMutate(.removeRange(
|
|
subRange: subRange.lowerBound.position..<subRange.upperBound.position))
|
|
}
|
|
_elements.removeSubrange(
|
|
subRange.lowerBound.position..<subRange.upperBound.position
|
|
)
|
|
}
|
|
|
|
public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
|
|
_willMutate(.removeAll(keepCapacity: keepCapacity))
|
|
// Ignore the value of `keepCapacity`.
|
|
_elements.removeAll(keepingCapacity: false)
|
|
}
|
|
|
|
internal mutating func _willMutate(_ operation: _CollectionOperation) {
|
|
_collectionState = _CollectionStateTransition(
|
|
previousState: _collectionState,
|
|
operation: operation)._nextState
|
|
}
|
|
|
|
public var underestimatedCount: Int
|
|
public var reservedCapacity: Int = 0
|
|
|
|
internal var _elements: [T]
|
|
internal var _collectionState: _CollectionState
|
|
}
|
|
|
|
|
|
/// A minimal implementation of `Collection` with extra checks.
|
|
public struct MinimalMutableBidirectionalCollection<T> : BidirectionalCollection, MutableCollection {
|
|
/// Creates a collection with given contents, but a unique modification
|
|
/// history. No other instance has the same modification history.
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == T {
|
|
self._elements = Array(elements)
|
|
|
|
self._collectionState = _CollectionState(
|
|
newRootStateForElementCount: self._elements.count)
|
|
|
|
switch underestimatedCount {
|
|
case .precise:
|
|
self.underestimatedCount = _elements.count
|
|
|
|
case .half:
|
|
self.underestimatedCount = _elements.count / 2
|
|
|
|
case .overestimate:
|
|
self.underestimatedCount = _elements.count * 3 + 5
|
|
|
|
case .value(let count):
|
|
self.underestimatedCount = count
|
|
}
|
|
}
|
|
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<T> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return MinimalIterator(_elements)
|
|
}
|
|
|
|
public typealias Index = MinimalIndex
|
|
|
|
internal func _index(forPosition i: Int) -> MinimalIndex {
|
|
return MinimalIndex(
|
|
collectionState: _collectionState,
|
|
position: i,
|
|
startIndex: _elements.startIndex,
|
|
endIndex: _elements.endIndex)
|
|
}
|
|
|
|
internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
|
|
return MinimalIndex(
|
|
_collectionState: _collectionState,
|
|
uncheckedPosition: i)
|
|
}
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.startIndex)
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.endIndex)
|
|
}
|
|
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ index: MinimalIndex,
|
|
bounds: Range<MinimalIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: index.position),
|
|
index)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
index.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ range: Range<MinimalIndex>,
|
|
bounds: Range<MinimalIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.lowerBound.position),
|
|
range.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.upperBound.position),
|
|
range.upperBound)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
range.lowerBound.position..<range.upperBound.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func index(after i: MinimalIndex) -> MinimalIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _uncheckedIndex(forPosition: i.position + 1)
|
|
}
|
|
|
|
public func index(before i: MinimalIndex) -> MinimalIndex {
|
|
// FIXME: swift-3-indexing-model: perform a range check and use
|
|
// return _uncheckedIndex(forPosition: i.position - 1)
|
|
return _index(forPosition: i.position - 1)
|
|
}
|
|
|
|
public func distance(from start: MinimalIndex, to end: MinimalIndex)
|
|
-> Int {
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if start != endIndex {
|
|
_failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
|
|
}
|
|
if end != endIndex {
|
|
_failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
|
|
}
|
|
return end.position - start.position
|
|
}
|
|
|
|
public func index(_ i: Index, offsetBy n: Int) -> Index {
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if i != endIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
}
|
|
return _index(forPosition: i.position + n)
|
|
}
|
|
|
|
public subscript(i: MinimalIndex) -> T {
|
|
get {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _elements[i.position]
|
|
}
|
|
set {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
_elements[i.position] = newValue
|
|
}
|
|
}
|
|
|
|
public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalMutableBidirectionalCollection<T>> {
|
|
get {
|
|
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
set {
|
|
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
|
|
_writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
|
|
}
|
|
}
|
|
|
|
|
|
public var underestimatedCount: Int
|
|
|
|
internal var _elements: [T]
|
|
internal let _collectionState: _CollectionState
|
|
}
|
|
|
|
|
|
/// A minimal implementation of `Collection` with extra checks.
|
|
public struct MinimalMutableRangeReplaceableBidirectionalCollection<T> : BidirectionalCollection, MutableCollection, RangeReplaceableCollection {
|
|
/// Creates a collection with given contents, but a unique modification
|
|
/// history. No other instance has the same modification history.
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == T {
|
|
self._elements = Array(elements)
|
|
|
|
self._collectionState = _CollectionState(
|
|
newRootStateForElementCount: self._elements.count)
|
|
|
|
switch underestimatedCount {
|
|
case .precise:
|
|
self.underestimatedCount = _elements.count
|
|
|
|
case .half:
|
|
self.underestimatedCount = _elements.count / 2
|
|
|
|
case .overestimate:
|
|
self.underestimatedCount = _elements.count * 3 + 5
|
|
|
|
case .value(let count):
|
|
self.underestimatedCount = count
|
|
}
|
|
}
|
|
|
|
public init() {
|
|
self.underestimatedCount = 0
|
|
self._elements = []
|
|
self._collectionState =
|
|
_CollectionState(name: "\(type(of: self))", elementCount: 0)
|
|
}
|
|
|
|
public init<S : Sequence>(_ elements: S) where S.Element == T {
|
|
self.underestimatedCount = 0
|
|
self._elements = Array(elements)
|
|
self._collectionState =
|
|
_CollectionState(newRootStateForElementCount: self._elements.count)
|
|
}
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<T> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return MinimalIterator(_elements)
|
|
}
|
|
|
|
public typealias Index = MinimalIndex
|
|
|
|
internal func _index(forPosition i: Int) -> MinimalIndex {
|
|
return MinimalIndex(
|
|
collectionState: _collectionState,
|
|
position: i,
|
|
startIndex: _elements.startIndex,
|
|
endIndex: _elements.endIndex)
|
|
}
|
|
|
|
internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
|
|
return MinimalIndex(
|
|
_collectionState: _collectionState,
|
|
uncheckedPosition: i)
|
|
}
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.startIndex)
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.endIndex)
|
|
}
|
|
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ index: MinimalIndex,
|
|
bounds: Range<MinimalIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: index.position),
|
|
index)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
index.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ range: Range<MinimalIndex>,
|
|
bounds: Range<MinimalIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.lowerBound.position),
|
|
range.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.upperBound.position),
|
|
range.upperBound)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
range.lowerBound.position..<range.upperBound.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func index(after i: MinimalIndex) -> MinimalIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _uncheckedIndex(forPosition: i.position + 1)
|
|
}
|
|
|
|
public func index(before i: MinimalIndex) -> MinimalIndex {
|
|
// FIXME: swift-3-indexing-model: perform a range check and use
|
|
// return _uncheckedIndex(forPosition: i.position - 1)
|
|
return _index(forPosition: i.position - 1)
|
|
}
|
|
|
|
public func distance(from start: MinimalIndex, to end: MinimalIndex)
|
|
-> Int {
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if start != endIndex {
|
|
_failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
|
|
}
|
|
if end != endIndex {
|
|
_failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
|
|
}
|
|
return end.position - start.position
|
|
}
|
|
|
|
public func index(_ i: Index, offsetBy n: Int) -> Index {
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if i != endIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
}
|
|
return _index(forPosition: i.position + n)
|
|
}
|
|
|
|
public subscript(i: MinimalIndex) -> T {
|
|
get {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _elements[i.position]
|
|
}
|
|
set {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
_elements[i.position] = newValue
|
|
}
|
|
}
|
|
|
|
public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalMutableRangeReplaceableBidirectionalCollection<T>> {
|
|
get {
|
|
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
set {
|
|
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
|
|
_writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
|
|
}
|
|
}
|
|
|
|
public mutating func reserveCapacity(_ n: Int) {
|
|
_willMutate(.reserveCapacity(capacity: n))
|
|
_elements.reserveCapacity(n)
|
|
reservedCapacity = Swift.max(reservedCapacity, n)
|
|
}
|
|
|
|
public mutating func append(_ x: T) {
|
|
_willMutate(.append)
|
|
_elements.append(x)
|
|
}
|
|
|
|
public mutating func append<S : Sequence>(contentsOf newElements: S)
|
|
where S.Element == T {
|
|
let oldCount = count
|
|
_elements.append(contentsOf: newElements)
|
|
let newCount = count
|
|
_willMutate(.appendContentsOf(count: newCount - oldCount))
|
|
}
|
|
|
|
public mutating func replaceSubrange<C>(
|
|
_ subRange: Range<MinimalIndex>,
|
|
with newElements: C
|
|
) where C : Collection, C.Element == T {
|
|
let oldCount = count
|
|
_elements.replaceSubrange(
|
|
subRange.lowerBound.position..<subRange.upperBound.position,
|
|
with: newElements)
|
|
let newCount = count
|
|
_willMutate(.replaceRange(
|
|
subRange: subRange.lowerBound.position..<subRange.upperBound.position,
|
|
replacementCount:
|
|
subRange.upperBound.position - subRange.lowerBound.position
|
|
+ newCount - oldCount))
|
|
}
|
|
|
|
public mutating func insert(_ newElement: T, at i: MinimalIndex) {
|
|
_willMutate(.insert(atIndex: i.position))
|
|
_elements.insert(newElement, at: i.position)
|
|
}
|
|
|
|
public mutating func insert<S : Collection>(
|
|
contentsOf newElements: S, at i: MinimalIndex
|
|
) where S.Element == T {
|
|
let oldCount = count
|
|
_elements.insert(contentsOf: newElements, at: i.position)
|
|
let newCount = count
|
|
|
|
if newCount - oldCount != 0 {
|
|
_willMutate(.insertContentsOf(
|
|
atIndex: i.position,
|
|
count: newCount - oldCount))
|
|
}
|
|
}
|
|
|
|
@discardableResult
|
|
public mutating func remove(at i: MinimalIndex) -> T {
|
|
_willMutate(.removeAtIndex(index: i.position))
|
|
return _elements.remove(at: i.position)
|
|
}
|
|
|
|
@discardableResult
|
|
public mutating func removeLast() -> T {
|
|
_willMutate(.removeLast)
|
|
return _elements.removeLast()
|
|
}
|
|
|
|
public mutating func removeSubrange(_ subRange: Range<MinimalIndex>) {
|
|
if !subRange.isEmpty {
|
|
_willMutate(.removeRange(
|
|
subRange: subRange.lowerBound.position..<subRange.upperBound.position))
|
|
}
|
|
_elements.removeSubrange(
|
|
subRange.lowerBound.position..<subRange.upperBound.position
|
|
)
|
|
}
|
|
|
|
public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
|
|
_willMutate(.removeAll(keepCapacity: keepCapacity))
|
|
// Ignore the value of `keepCapacity`.
|
|
_elements.removeAll(keepingCapacity: false)
|
|
}
|
|
|
|
internal mutating func _willMutate(_ operation: _CollectionOperation) {
|
|
_collectionState = _CollectionStateTransition(
|
|
previousState: _collectionState,
|
|
operation: operation)._nextState
|
|
}
|
|
|
|
public var underestimatedCount: Int
|
|
public var reservedCapacity: Int = 0
|
|
|
|
internal var _elements: [T]
|
|
internal var _collectionState: _CollectionState
|
|
}
|
|
|
|
|
|
/// A minimal implementation of `Collection` with extra checks.
|
|
public struct MinimalRandomAccessCollection<T> : RandomAccessCollection {
|
|
/// Creates a collection with given contents, but a unique modification
|
|
/// history. No other instance has the same modification history.
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == T {
|
|
self._elements = Array(elements)
|
|
|
|
self._collectionState = _CollectionState(
|
|
newRootStateForElementCount: self._elements.count)
|
|
|
|
switch underestimatedCount {
|
|
case .precise:
|
|
self.underestimatedCount = _elements.count
|
|
|
|
case .half:
|
|
self.underestimatedCount = _elements.count / 2
|
|
|
|
case .overestimate:
|
|
self.underestimatedCount = _elements.count * 3 + 5
|
|
|
|
case .value(let count):
|
|
self.underestimatedCount = count
|
|
}
|
|
}
|
|
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<T> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return MinimalIterator(_elements)
|
|
}
|
|
|
|
public typealias Index = MinimalIndex
|
|
|
|
internal func _index(forPosition i: Int) -> MinimalIndex {
|
|
return MinimalIndex(
|
|
collectionState: _collectionState,
|
|
position: i,
|
|
startIndex: _elements.startIndex,
|
|
endIndex: _elements.endIndex)
|
|
}
|
|
|
|
internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
|
|
return MinimalIndex(
|
|
_collectionState: _collectionState,
|
|
uncheckedPosition: i)
|
|
}
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.startIndex)
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.endIndex)
|
|
}
|
|
|
|
// FIXME: this shouldn't be necessary, should come by default
|
|
public typealias Indices = DefaultIndices<MinimalRandomAccessCollection<T>>
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ index: MinimalIndex,
|
|
bounds: Range<MinimalIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: index.position),
|
|
index)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
index.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ range: Range<MinimalIndex>,
|
|
bounds: Range<MinimalIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.lowerBound.position),
|
|
range.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.upperBound.position),
|
|
range.upperBound)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
range.lowerBound.position..<range.upperBound.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func index(after i: MinimalIndex) -> MinimalIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _uncheckedIndex(forPosition: i.position + 1)
|
|
}
|
|
|
|
public func index(before i: MinimalIndex) -> MinimalIndex {
|
|
// FIXME: swift-3-indexing-model: perform a range check and use
|
|
// return _uncheckedIndex(forPosition: i.position - 1)
|
|
return _index(forPosition: i.position - 1)
|
|
}
|
|
|
|
public func distance(from start: MinimalIndex, to end: MinimalIndex)
|
|
-> Int {
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if start != endIndex {
|
|
_failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
|
|
}
|
|
if end != endIndex {
|
|
_failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
|
|
}
|
|
return end.position - start.position
|
|
}
|
|
|
|
public func index(_ i: Index, offsetBy n: Int) -> Index {
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if i != endIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
}
|
|
return _index(forPosition: i.position + n)
|
|
}
|
|
|
|
public subscript(i: MinimalIndex) -> T {
|
|
get {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _elements[i.position]
|
|
}
|
|
}
|
|
|
|
public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalRandomAccessCollection<T>> {
|
|
get {
|
|
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
}
|
|
|
|
|
|
public var underestimatedCount: Int
|
|
|
|
internal var _elements: [T]
|
|
internal let _collectionState: _CollectionState
|
|
}
|
|
|
|
|
|
/// A minimal implementation of `Collection` with extra checks.
|
|
public struct MinimalRandomAccessCollectionWithStrideableIndex<T> : RandomAccessCollection {
|
|
/// Creates a collection with given contents, but a unique modification
|
|
/// history. No other instance has the same modification history.
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == T {
|
|
self._elements = Array(elements)
|
|
|
|
self._collectionState = _CollectionState(
|
|
newRootStateForElementCount: self._elements.count)
|
|
|
|
switch underestimatedCount {
|
|
case .precise:
|
|
self.underestimatedCount = _elements.count
|
|
|
|
case .half:
|
|
self.underestimatedCount = _elements.count / 2
|
|
|
|
case .overestimate:
|
|
self.underestimatedCount = _elements.count * 3 + 5
|
|
|
|
case .value(let count):
|
|
self.underestimatedCount = count
|
|
}
|
|
}
|
|
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<T> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return MinimalIterator(_elements)
|
|
}
|
|
|
|
public typealias Index = MinimalStrideableIndex
|
|
|
|
internal func _index(forPosition i: Int) -> MinimalStrideableIndex {
|
|
return MinimalStrideableIndex(
|
|
collectionState: _collectionState,
|
|
position: i,
|
|
startIndex: _elements.startIndex,
|
|
endIndex: _elements.endIndex)
|
|
}
|
|
|
|
internal func _uncheckedIndex(forPosition i: Int) -> MinimalStrideableIndex {
|
|
return MinimalStrideableIndex(
|
|
_collectionState: _collectionState,
|
|
uncheckedPosition: i)
|
|
}
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalStrideableIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.startIndex)
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalStrideableIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.endIndex)
|
|
}
|
|
|
|
public typealias Indices = Range<MinimalStrideableIndex>
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ index: MinimalStrideableIndex,
|
|
bounds: Range<MinimalStrideableIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: index.position),
|
|
index)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
index.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ range: Range<MinimalStrideableIndex>,
|
|
bounds: Range<MinimalStrideableIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.lowerBound.position),
|
|
range.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.upperBound.position),
|
|
range.upperBound)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
range.lowerBound.position..<range.upperBound.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func index(after i: MinimalStrideableIndex) -> MinimalStrideableIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _uncheckedIndex(forPosition: i.position + 1)
|
|
}
|
|
|
|
public func index(before i: MinimalStrideableIndex) -> MinimalStrideableIndex {
|
|
// FIXME: swift-3-indexing-model: perform a range check and use
|
|
// return _uncheckedIndex(forPosition: i.position - 1)
|
|
return _index(forPosition: i.position - 1)
|
|
}
|
|
|
|
public func distance(from start: MinimalStrideableIndex, to end: MinimalStrideableIndex)
|
|
-> Int {
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if start != endIndex {
|
|
_failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
|
|
}
|
|
if end != endIndex {
|
|
_failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
|
|
}
|
|
return end.position - start.position
|
|
}
|
|
|
|
public func index(_ i: Index, offsetBy n: Int) -> Index {
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if i != endIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
}
|
|
return _index(forPosition: i.position + n)
|
|
}
|
|
|
|
public subscript(i: MinimalStrideableIndex) -> T {
|
|
get {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _elements[i.position]
|
|
}
|
|
}
|
|
|
|
public subscript(bounds: Range<MinimalStrideableIndex>) -> Slice<MinimalRandomAccessCollectionWithStrideableIndex<T>> {
|
|
get {
|
|
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
}
|
|
|
|
|
|
public var underestimatedCount: Int
|
|
|
|
internal var _elements: [T]
|
|
internal let _collectionState: _CollectionState
|
|
}
|
|
|
|
|
|
/// A minimal implementation of `Collection` with extra checks.
|
|
public struct MinimalRangeReplaceableRandomAccessCollection<T> : RandomAccessCollection, RangeReplaceableCollection {
|
|
/// Creates a collection with given contents, but a unique modification
|
|
/// history. No other instance has the same modification history.
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == T {
|
|
self._elements = Array(elements)
|
|
|
|
self._collectionState = _CollectionState(
|
|
newRootStateForElementCount: self._elements.count)
|
|
|
|
switch underestimatedCount {
|
|
case .precise:
|
|
self.underestimatedCount = _elements.count
|
|
|
|
case .half:
|
|
self.underestimatedCount = _elements.count / 2
|
|
|
|
case .overestimate:
|
|
self.underestimatedCount = _elements.count * 3 + 5
|
|
|
|
case .value(let count):
|
|
self.underestimatedCount = count
|
|
}
|
|
}
|
|
|
|
public init() {
|
|
self.underestimatedCount = 0
|
|
self._elements = []
|
|
self._collectionState =
|
|
_CollectionState(name: "\(type(of: self))", elementCount: 0)
|
|
}
|
|
|
|
public init<S : Sequence>(_ elements: S) where S.Element == T {
|
|
self.underestimatedCount = 0
|
|
self._elements = Array(elements)
|
|
self._collectionState =
|
|
_CollectionState(newRootStateForElementCount: self._elements.count)
|
|
}
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<T> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return MinimalIterator(_elements)
|
|
}
|
|
|
|
public typealias Index = MinimalIndex
|
|
|
|
internal func _index(forPosition i: Int) -> MinimalIndex {
|
|
return MinimalIndex(
|
|
collectionState: _collectionState,
|
|
position: i,
|
|
startIndex: _elements.startIndex,
|
|
endIndex: _elements.endIndex)
|
|
}
|
|
|
|
internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
|
|
return MinimalIndex(
|
|
_collectionState: _collectionState,
|
|
uncheckedPosition: i)
|
|
}
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.startIndex)
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.endIndex)
|
|
}
|
|
|
|
// FIXME: this shouldn't be necessary, should come by default
|
|
public typealias Indices = DefaultIndices<MinimalRangeReplaceableRandomAccessCollection<T>>
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ index: MinimalIndex,
|
|
bounds: Range<MinimalIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: index.position),
|
|
index)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
index.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ range: Range<MinimalIndex>,
|
|
bounds: Range<MinimalIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.lowerBound.position),
|
|
range.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.upperBound.position),
|
|
range.upperBound)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
range.lowerBound.position..<range.upperBound.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func index(after i: MinimalIndex) -> MinimalIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _uncheckedIndex(forPosition: i.position + 1)
|
|
}
|
|
|
|
public func index(before i: MinimalIndex) -> MinimalIndex {
|
|
// FIXME: swift-3-indexing-model: perform a range check and use
|
|
// return _uncheckedIndex(forPosition: i.position - 1)
|
|
return _index(forPosition: i.position - 1)
|
|
}
|
|
|
|
public func distance(from start: MinimalIndex, to end: MinimalIndex)
|
|
-> Int {
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if start != endIndex {
|
|
_failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
|
|
}
|
|
if end != endIndex {
|
|
_failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
|
|
}
|
|
return end.position - start.position
|
|
}
|
|
|
|
public func index(_ i: Index, offsetBy n: Int) -> Index {
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if i != endIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
}
|
|
return _index(forPosition: i.position + n)
|
|
}
|
|
|
|
public subscript(i: MinimalIndex) -> T {
|
|
get {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _elements[i.position]
|
|
}
|
|
}
|
|
|
|
public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalRangeReplaceableRandomAccessCollection<T>> {
|
|
get {
|
|
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
}
|
|
|
|
public mutating func reserveCapacity(_ n: Int) {
|
|
_willMutate(.reserveCapacity(capacity: n))
|
|
_elements.reserveCapacity(n)
|
|
reservedCapacity = Swift.max(reservedCapacity, n)
|
|
}
|
|
|
|
public mutating func append(_ x: T) {
|
|
_willMutate(.append)
|
|
_elements.append(x)
|
|
}
|
|
|
|
public mutating func append<S : Sequence>(contentsOf newElements: S)
|
|
where S.Element == T {
|
|
let oldCount = count
|
|
_elements.append(contentsOf: newElements)
|
|
let newCount = count
|
|
_willMutate(.appendContentsOf(count: newCount - oldCount))
|
|
}
|
|
|
|
public mutating func replaceSubrange<C>(
|
|
_ subRange: Range<MinimalIndex>,
|
|
with newElements: C
|
|
) where C : Collection, C.Element == T {
|
|
let oldCount = count
|
|
_elements.replaceSubrange(
|
|
subRange.lowerBound.position..<subRange.upperBound.position,
|
|
with: newElements)
|
|
let newCount = count
|
|
_willMutate(.replaceRange(
|
|
subRange: subRange.lowerBound.position..<subRange.upperBound.position,
|
|
replacementCount:
|
|
subRange.upperBound.position - subRange.lowerBound.position
|
|
+ newCount - oldCount))
|
|
}
|
|
|
|
public mutating func insert(_ newElement: T, at i: MinimalIndex) {
|
|
_willMutate(.insert(atIndex: i.position))
|
|
_elements.insert(newElement, at: i.position)
|
|
}
|
|
|
|
public mutating func insert<S : Collection>(
|
|
contentsOf newElements: S, at i: MinimalIndex
|
|
) where S.Element == T {
|
|
let oldCount = count
|
|
_elements.insert(contentsOf: newElements, at: i.position)
|
|
let newCount = count
|
|
|
|
if newCount - oldCount != 0 {
|
|
_willMutate(.insertContentsOf(
|
|
atIndex: i.position,
|
|
count: newCount - oldCount))
|
|
}
|
|
}
|
|
|
|
@discardableResult
|
|
public mutating func remove(at i: MinimalIndex) -> T {
|
|
_willMutate(.removeAtIndex(index: i.position))
|
|
return _elements.remove(at: i.position)
|
|
}
|
|
|
|
@discardableResult
|
|
public mutating func removeLast() -> T {
|
|
_willMutate(.removeLast)
|
|
return _elements.removeLast()
|
|
}
|
|
|
|
public mutating func removeSubrange(_ subRange: Range<MinimalIndex>) {
|
|
if !subRange.isEmpty {
|
|
_willMutate(.removeRange(
|
|
subRange: subRange.lowerBound.position..<subRange.upperBound.position))
|
|
}
|
|
_elements.removeSubrange(
|
|
subRange.lowerBound.position..<subRange.upperBound.position
|
|
)
|
|
}
|
|
|
|
public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
|
|
_willMutate(.removeAll(keepCapacity: keepCapacity))
|
|
// Ignore the value of `keepCapacity`.
|
|
_elements.removeAll(keepingCapacity: false)
|
|
}
|
|
|
|
internal mutating func _willMutate(_ operation: _CollectionOperation) {
|
|
_collectionState = _CollectionStateTransition(
|
|
previousState: _collectionState,
|
|
operation: operation)._nextState
|
|
}
|
|
|
|
public var underestimatedCount: Int
|
|
public var reservedCapacity: Int = 0
|
|
|
|
internal var _elements: [T]
|
|
internal var _collectionState: _CollectionState
|
|
}
|
|
|
|
|
|
/// A minimal implementation of `Collection` with extra checks.
|
|
public struct MinimalRangeReplaceableRandomAccessCollectionWithStrideableIndex<T> : RandomAccessCollection, RangeReplaceableCollection {
|
|
/// Creates a collection with given contents, but a unique modification
|
|
/// history. No other instance has the same modification history.
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == T {
|
|
self._elements = Array(elements)
|
|
|
|
self._collectionState = _CollectionState(
|
|
newRootStateForElementCount: self._elements.count)
|
|
|
|
switch underestimatedCount {
|
|
case .precise:
|
|
self.underestimatedCount = _elements.count
|
|
|
|
case .half:
|
|
self.underestimatedCount = _elements.count / 2
|
|
|
|
case .overestimate:
|
|
self.underestimatedCount = _elements.count * 3 + 5
|
|
|
|
case .value(let count):
|
|
self.underestimatedCount = count
|
|
}
|
|
}
|
|
|
|
public init() {
|
|
self.underestimatedCount = 0
|
|
self._elements = []
|
|
self._collectionState =
|
|
_CollectionState(name: "\(type(of: self))", elementCount: 0)
|
|
}
|
|
|
|
public init<S : Sequence>(_ elements: S) where S.Element == T {
|
|
self.underestimatedCount = 0
|
|
self._elements = Array(elements)
|
|
self._collectionState =
|
|
_CollectionState(newRootStateForElementCount: self._elements.count)
|
|
}
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<T> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return MinimalIterator(_elements)
|
|
}
|
|
|
|
public typealias Index = MinimalStrideableIndex
|
|
|
|
internal func _index(forPosition i: Int) -> MinimalStrideableIndex {
|
|
return MinimalStrideableIndex(
|
|
collectionState: _collectionState,
|
|
position: i,
|
|
startIndex: _elements.startIndex,
|
|
endIndex: _elements.endIndex)
|
|
}
|
|
|
|
internal func _uncheckedIndex(forPosition i: Int) -> MinimalStrideableIndex {
|
|
return MinimalStrideableIndex(
|
|
_collectionState: _collectionState,
|
|
uncheckedPosition: i)
|
|
}
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalStrideableIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.startIndex)
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalStrideableIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.endIndex)
|
|
}
|
|
|
|
public typealias Indices = Range<MinimalStrideableIndex>
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ index: MinimalStrideableIndex,
|
|
bounds: Range<MinimalStrideableIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: index.position),
|
|
index)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
index.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ range: Range<MinimalStrideableIndex>,
|
|
bounds: Range<MinimalStrideableIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.lowerBound.position),
|
|
range.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.upperBound.position),
|
|
range.upperBound)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
range.lowerBound.position..<range.upperBound.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func index(after i: MinimalStrideableIndex) -> MinimalStrideableIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _uncheckedIndex(forPosition: i.position + 1)
|
|
}
|
|
|
|
public func index(before i: MinimalStrideableIndex) -> MinimalStrideableIndex {
|
|
// FIXME: swift-3-indexing-model: perform a range check and use
|
|
// return _uncheckedIndex(forPosition: i.position - 1)
|
|
return _index(forPosition: i.position - 1)
|
|
}
|
|
|
|
public func distance(from start: MinimalStrideableIndex, to end: MinimalStrideableIndex)
|
|
-> Int {
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if start != endIndex {
|
|
_failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
|
|
}
|
|
if end != endIndex {
|
|
_failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
|
|
}
|
|
return end.position - start.position
|
|
}
|
|
|
|
public func index(_ i: Index, offsetBy n: Int) -> Index {
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if i != endIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
}
|
|
return _index(forPosition: i.position + n)
|
|
}
|
|
|
|
public subscript(i: MinimalStrideableIndex) -> T {
|
|
get {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _elements[i.position]
|
|
}
|
|
}
|
|
|
|
public subscript(bounds: Range<MinimalStrideableIndex>) -> Slice<MinimalRangeReplaceableRandomAccessCollectionWithStrideableIndex<T>> {
|
|
get {
|
|
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
}
|
|
|
|
public mutating func reserveCapacity(_ n: Int) {
|
|
_willMutate(.reserveCapacity(capacity: n))
|
|
_elements.reserveCapacity(n)
|
|
reservedCapacity = Swift.max(reservedCapacity, n)
|
|
}
|
|
|
|
public mutating func append(_ x: T) {
|
|
_willMutate(.append)
|
|
_elements.append(x)
|
|
}
|
|
|
|
public mutating func append<S : Sequence>(contentsOf newElements: S)
|
|
where S.Element == T {
|
|
let oldCount = count
|
|
_elements.append(contentsOf: newElements)
|
|
let newCount = count
|
|
_willMutate(.appendContentsOf(count: newCount - oldCount))
|
|
}
|
|
|
|
public mutating func replaceSubrange<C>(
|
|
_ subRange: Range<MinimalStrideableIndex>,
|
|
with newElements: C
|
|
) where C : Collection, C.Element == T {
|
|
let oldCount = count
|
|
_elements.replaceSubrange(
|
|
subRange.lowerBound.position..<subRange.upperBound.position,
|
|
with: newElements)
|
|
let newCount = count
|
|
_willMutate(.replaceRange(
|
|
subRange: subRange.lowerBound.position..<subRange.upperBound.position,
|
|
replacementCount:
|
|
subRange.upperBound.position - subRange.lowerBound.position
|
|
+ newCount - oldCount))
|
|
}
|
|
|
|
public mutating func insert(_ newElement: T, at i: MinimalStrideableIndex) {
|
|
_willMutate(.insert(atIndex: i.position))
|
|
_elements.insert(newElement, at: i.position)
|
|
}
|
|
|
|
public mutating func insert<S : Collection>(
|
|
contentsOf newElements: S, at i: MinimalStrideableIndex
|
|
) where S.Element == T {
|
|
let oldCount = count
|
|
_elements.insert(contentsOf: newElements, at: i.position)
|
|
let newCount = count
|
|
|
|
if newCount - oldCount != 0 {
|
|
_willMutate(.insertContentsOf(
|
|
atIndex: i.position,
|
|
count: newCount - oldCount))
|
|
}
|
|
}
|
|
|
|
@discardableResult
|
|
public mutating func remove(at i: MinimalStrideableIndex) -> T {
|
|
_willMutate(.removeAtIndex(index: i.position))
|
|
return _elements.remove(at: i.position)
|
|
}
|
|
|
|
@discardableResult
|
|
public mutating func removeLast() -> T {
|
|
_willMutate(.removeLast)
|
|
return _elements.removeLast()
|
|
}
|
|
|
|
public mutating func removeSubrange(_ subRange: Range<MinimalStrideableIndex>) {
|
|
if !subRange.isEmpty {
|
|
_willMutate(.removeRange(
|
|
subRange: subRange.lowerBound.position..<subRange.upperBound.position))
|
|
}
|
|
_elements.removeSubrange(
|
|
subRange.lowerBound.position..<subRange.upperBound.position
|
|
)
|
|
}
|
|
|
|
public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
|
|
_willMutate(.removeAll(keepCapacity: keepCapacity))
|
|
// Ignore the value of `keepCapacity`.
|
|
_elements.removeAll(keepingCapacity: false)
|
|
}
|
|
|
|
internal mutating func _willMutate(_ operation: _CollectionOperation) {
|
|
_collectionState = _CollectionStateTransition(
|
|
previousState: _collectionState,
|
|
operation: operation)._nextState
|
|
}
|
|
|
|
public var underestimatedCount: Int
|
|
public var reservedCapacity: Int = 0
|
|
|
|
internal var _elements: [T]
|
|
internal var _collectionState: _CollectionState
|
|
}
|
|
|
|
|
|
/// A minimal implementation of `Collection` with extra checks.
|
|
public struct MinimalMutableRandomAccessCollection<T> : RandomAccessCollection, MutableCollection {
|
|
/// Creates a collection with given contents, but a unique modification
|
|
/// history. No other instance has the same modification history.
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == T {
|
|
self._elements = Array(elements)
|
|
|
|
self._collectionState = _CollectionState(
|
|
newRootStateForElementCount: self._elements.count)
|
|
|
|
switch underestimatedCount {
|
|
case .precise:
|
|
self.underestimatedCount = _elements.count
|
|
|
|
case .half:
|
|
self.underestimatedCount = _elements.count / 2
|
|
|
|
case .overestimate:
|
|
self.underestimatedCount = _elements.count * 3 + 5
|
|
|
|
case .value(let count):
|
|
self.underestimatedCount = count
|
|
}
|
|
}
|
|
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<T> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return MinimalIterator(_elements)
|
|
}
|
|
|
|
public typealias Index = MinimalIndex
|
|
|
|
internal func _index(forPosition i: Int) -> MinimalIndex {
|
|
return MinimalIndex(
|
|
collectionState: _collectionState,
|
|
position: i,
|
|
startIndex: _elements.startIndex,
|
|
endIndex: _elements.endIndex)
|
|
}
|
|
|
|
internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
|
|
return MinimalIndex(
|
|
_collectionState: _collectionState,
|
|
uncheckedPosition: i)
|
|
}
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.startIndex)
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.endIndex)
|
|
}
|
|
|
|
// FIXME: this shouldn't be necessary, should come by default
|
|
public typealias Indices = DefaultIndices<MinimalMutableRandomAccessCollection<T>>
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ index: MinimalIndex,
|
|
bounds: Range<MinimalIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: index.position),
|
|
index)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
index.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ range: Range<MinimalIndex>,
|
|
bounds: Range<MinimalIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.lowerBound.position),
|
|
range.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.upperBound.position),
|
|
range.upperBound)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
range.lowerBound.position..<range.upperBound.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func index(after i: MinimalIndex) -> MinimalIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _uncheckedIndex(forPosition: i.position + 1)
|
|
}
|
|
|
|
public func index(before i: MinimalIndex) -> MinimalIndex {
|
|
// FIXME: swift-3-indexing-model: perform a range check and use
|
|
// return _uncheckedIndex(forPosition: i.position - 1)
|
|
return _index(forPosition: i.position - 1)
|
|
}
|
|
|
|
public func distance(from start: MinimalIndex, to end: MinimalIndex)
|
|
-> Int {
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if start != endIndex {
|
|
_failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
|
|
}
|
|
if end != endIndex {
|
|
_failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
|
|
}
|
|
return end.position - start.position
|
|
}
|
|
|
|
public func index(_ i: Index, offsetBy n: Int) -> Index {
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if i != endIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
}
|
|
return _index(forPosition: i.position + n)
|
|
}
|
|
|
|
public subscript(i: MinimalIndex) -> T {
|
|
get {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _elements[i.position]
|
|
}
|
|
set {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
_elements[i.position] = newValue
|
|
}
|
|
}
|
|
|
|
public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalMutableRandomAccessCollection<T>> {
|
|
get {
|
|
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
set {
|
|
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
|
|
_writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
|
|
}
|
|
}
|
|
|
|
|
|
public var underestimatedCount: Int
|
|
|
|
internal var _elements: [T]
|
|
internal let _collectionState: _CollectionState
|
|
}
|
|
|
|
|
|
/// A minimal implementation of `Collection` with extra checks.
|
|
public struct MinimalMutableRangeReplaceableRandomAccessCollection<T> : RandomAccessCollection, MutableCollection, RangeReplaceableCollection {
|
|
/// Creates a collection with given contents, but a unique modification
|
|
/// history. No other instance has the same modification history.
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == T {
|
|
self._elements = Array(elements)
|
|
|
|
self._collectionState = _CollectionState(
|
|
newRootStateForElementCount: self._elements.count)
|
|
|
|
switch underestimatedCount {
|
|
case .precise:
|
|
self.underestimatedCount = _elements.count
|
|
|
|
case .half:
|
|
self.underestimatedCount = _elements.count / 2
|
|
|
|
case .overestimate:
|
|
self.underestimatedCount = _elements.count * 3 + 5
|
|
|
|
case .value(let count):
|
|
self.underestimatedCount = count
|
|
}
|
|
}
|
|
|
|
public init() {
|
|
self.underestimatedCount = 0
|
|
self._elements = []
|
|
self._collectionState =
|
|
_CollectionState(name: "\(type(of: self))", elementCount: 0)
|
|
}
|
|
|
|
public init<S : Sequence>(_ elements: S) where S.Element == T {
|
|
self.underestimatedCount = 0
|
|
self._elements = Array(elements)
|
|
self._collectionState =
|
|
_CollectionState(newRootStateForElementCount: self._elements.count)
|
|
}
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<T> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return MinimalIterator(_elements)
|
|
}
|
|
|
|
public typealias Index = MinimalIndex
|
|
|
|
internal func _index(forPosition i: Int) -> MinimalIndex {
|
|
return MinimalIndex(
|
|
collectionState: _collectionState,
|
|
position: i,
|
|
startIndex: _elements.startIndex,
|
|
endIndex: _elements.endIndex)
|
|
}
|
|
|
|
internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
|
|
return MinimalIndex(
|
|
_collectionState: _collectionState,
|
|
uncheckedPosition: i)
|
|
}
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.startIndex)
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return _uncheckedIndex(forPosition: _elements.endIndex)
|
|
}
|
|
|
|
// FIXME: this shouldn't be necessary, should come by default
|
|
public typealias Indices = DefaultIndices<MinimalMutableRangeReplaceableRandomAccessCollection<T>>
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ index: MinimalIndex,
|
|
bounds: Range<MinimalIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: index.position),
|
|
index)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
index.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func _failEarlyRangeCheck(
|
|
_ range: Range<MinimalIndex>,
|
|
bounds: Range<MinimalIndex>
|
|
) {
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.lowerBound.position),
|
|
range.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: range.upperBound.position),
|
|
range.upperBound)
|
|
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.lowerBound.position),
|
|
bounds.lowerBound)
|
|
_expectCompatibleIndices(
|
|
_uncheckedIndex(forPosition: bounds.upperBound.position),
|
|
bounds.upperBound)
|
|
|
|
expectTrapping(
|
|
range.lowerBound.position..<range.upperBound.position,
|
|
in: bounds.lowerBound.position..<bounds.upperBound.position)
|
|
}
|
|
|
|
public func index(after i: MinimalIndex) -> MinimalIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _uncheckedIndex(forPosition: i.position + 1)
|
|
}
|
|
|
|
public func index(before i: MinimalIndex) -> MinimalIndex {
|
|
// FIXME: swift-3-indexing-model: perform a range check and use
|
|
// return _uncheckedIndex(forPosition: i.position - 1)
|
|
return _index(forPosition: i.position - 1)
|
|
}
|
|
|
|
public func distance(from start: MinimalIndex, to end: MinimalIndex)
|
|
-> Int {
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if start != endIndex {
|
|
_failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
|
|
}
|
|
if end != endIndex {
|
|
_failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
|
|
}
|
|
return end.position - start.position
|
|
}
|
|
|
|
public func index(_ i: Index, offsetBy n: Int) -> Index {
|
|
// FIXME: swift-3-indexing-model: perform a range check properly.
|
|
if i != endIndex {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
}
|
|
return _index(forPosition: i.position + n)
|
|
}
|
|
|
|
public subscript(i: MinimalIndex) -> T {
|
|
get {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
return _elements[i.position]
|
|
}
|
|
set {
|
|
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
|
|
_elements[i.position] = newValue
|
|
}
|
|
}
|
|
|
|
public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalMutableRangeReplaceableRandomAccessCollection<T>> {
|
|
get {
|
|
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
set {
|
|
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
|
|
_writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
|
|
}
|
|
}
|
|
|
|
public mutating func reserveCapacity(_ n: Int) {
|
|
_willMutate(.reserveCapacity(capacity: n))
|
|
_elements.reserveCapacity(n)
|
|
reservedCapacity = Swift.max(reservedCapacity, n)
|
|
}
|
|
|
|
public mutating func append(_ x: T) {
|
|
_willMutate(.append)
|
|
_elements.append(x)
|
|
}
|
|
|
|
public mutating func append<S : Sequence>(contentsOf newElements: S)
|
|
where S.Element == T {
|
|
let oldCount = count
|
|
_elements.append(contentsOf: newElements)
|
|
let newCount = count
|
|
_willMutate(.appendContentsOf(count: newCount - oldCount))
|
|
}
|
|
|
|
public mutating func replaceSubrange<C>(
|
|
_ subRange: Range<MinimalIndex>,
|
|
with newElements: C
|
|
) where C : Collection, C.Element == T {
|
|
let oldCount = count
|
|
_elements.replaceSubrange(
|
|
subRange.lowerBound.position..<subRange.upperBound.position,
|
|
with: newElements)
|
|
let newCount = count
|
|
_willMutate(.replaceRange(
|
|
subRange: subRange.lowerBound.position..<subRange.upperBound.position,
|
|
replacementCount:
|
|
subRange.upperBound.position - subRange.lowerBound.position
|
|
+ newCount - oldCount))
|
|
}
|
|
|
|
public mutating func insert(_ newElement: T, at i: MinimalIndex) {
|
|
_willMutate(.insert(atIndex: i.position))
|
|
_elements.insert(newElement, at: i.position)
|
|
}
|
|
|
|
public mutating func insert<S : Collection>(
|
|
contentsOf newElements: S, at i: MinimalIndex
|
|
) where S.Element == T {
|
|
let oldCount = count
|
|
_elements.insert(contentsOf: newElements, at: i.position)
|
|
let newCount = count
|
|
|
|
if newCount - oldCount != 0 {
|
|
_willMutate(.insertContentsOf(
|
|
atIndex: i.position,
|
|
count: newCount - oldCount))
|
|
}
|
|
}
|
|
|
|
@discardableResult
|
|
public mutating func remove(at i: MinimalIndex) -> T {
|
|
_willMutate(.removeAtIndex(index: i.position))
|
|
return _elements.remove(at: i.position)
|
|
}
|
|
|
|
@discardableResult
|
|
public mutating func removeLast() -> T {
|
|
_willMutate(.removeLast)
|
|
return _elements.removeLast()
|
|
}
|
|
|
|
public mutating func removeSubrange(_ subRange: Range<MinimalIndex>) {
|
|
if !subRange.isEmpty {
|
|
_willMutate(.removeRange(
|
|
subRange: subRange.lowerBound.position..<subRange.upperBound.position))
|
|
}
|
|
_elements.removeSubrange(
|
|
subRange.lowerBound.position..<subRange.upperBound.position
|
|
)
|
|
}
|
|
|
|
public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
|
|
_willMutate(.removeAll(keepCapacity: keepCapacity))
|
|
// Ignore the value of `keepCapacity`.
|
|
_elements.removeAll(keepingCapacity: false)
|
|
}
|
|
|
|
internal mutating func _willMutate(_ operation: _CollectionOperation) {
|
|
_collectionState = _CollectionStateTransition(
|
|
previousState: _collectionState,
|
|
operation: operation)._nextState
|
|
}
|
|
|
|
public var underestimatedCount: Int
|
|
public var reservedCapacity: Int = 0
|
|
|
|
internal var _elements: [T]
|
|
internal var _collectionState: _CollectionState
|
|
}
|
|
|
|
|
|
/// A Sequence that uses as many default implementations as
|
|
/// `Sequence` can provide.
|
|
public struct DefaultedSequence<Element> : Sequence {
|
|
public let base: MinimalSequence<Element>
|
|
|
|
public init(base: MinimalSequence<Element>) {
|
|
self.base = base
|
|
}
|
|
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == Element {
|
|
self.init(base: MinimalSequence(
|
|
elements: elements, underestimatedCount: underestimatedCount))
|
|
}
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
return base.makeIterator()
|
|
}
|
|
|
|
public var underestimatedCount: Int {
|
|
return base.underestimatedCount
|
|
}
|
|
}
|
|
|
|
|
|
/// A Collection that uses as many default implementations as
|
|
/// `Collection` can provide.
|
|
public struct DefaultedCollection<Element> : Collection {
|
|
public typealias Base = MinimalCollection<Element>
|
|
public typealias Iterator = MinimalIterator<Element>
|
|
public typealias Index = MinimalIndex
|
|
|
|
|
|
public let base: Base
|
|
|
|
public init(base: Base) {
|
|
self.base = base
|
|
}
|
|
|
|
public init(_ array: [Element]) {
|
|
self.base = Base(elements: array)
|
|
}
|
|
|
|
public init(elements: [Element]) {
|
|
self.base = Base(elements: elements)
|
|
}
|
|
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == Element {
|
|
self.init(base:
|
|
MinimalCollection(elements: elements, underestimatedCount: underestimatedCount))
|
|
}
|
|
|
|
public var underestimatedCount: Int {
|
|
return base.underestimatedCount
|
|
}
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return base.makeIterator()
|
|
}
|
|
|
|
|
|
public let timesSuccessorCalled = ResettableValue(0)
|
|
|
|
public func index(after i: MinimalIndex) -> MinimalIndex {
|
|
timesSuccessorCalled.value += 1
|
|
return base.index(after: i)
|
|
}
|
|
|
|
|
|
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return base.startIndex
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return base.endIndex
|
|
}
|
|
|
|
public subscript(i: MinimalIndex) -> Element {
|
|
get {
|
|
return base[i]
|
|
}
|
|
}
|
|
|
|
// FIXME: swift-3-indexing-model: use defaults.
|
|
// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
|
|
|
|
public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedCollection<Base.Element>> {
|
|
get {
|
|
// FIXME: swift-3-indexing-model: range check.
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
FIXME: swift-3-indexing-model: uncomment this.
|
|
public struct DefaultedForwardRangeReplaceableSlice<Element>
|
|
: RangeReplaceableCollection {
|
|
|
|
public typealias Self_ = DefaultedForwardRangeReplaceableSlice<Element>
|
|
public typealias Base = MinimalCollection<Element>
|
|
public typealias Iterator = MinimalIterator<Element>
|
|
public typealias Index = MinimalIndex
|
|
|
|
public var base: Base
|
|
public var startIndex: Index
|
|
public var endIndex: Index
|
|
|
|
public init() {
|
|
expectSliceType(Self_.self)
|
|
|
|
self.base = Base()
|
|
self.startIndex = base.startIndex
|
|
self.endIndex = base.endIndex
|
|
}
|
|
|
|
public init(base: Base) {
|
|
self.base = base
|
|
self.startIndex = base.startIndex
|
|
self.endIndex = base.endIndex
|
|
}
|
|
|
|
public init(base: Base, bounds: Range<Index>) {
|
|
self.base = base
|
|
self.startIndex = bounds.lowerBound
|
|
self.endIndex = bounds.upperBound
|
|
}
|
|
|
|
public init(_ array: [Element]) {
|
|
self = DefaultedForwardRangeReplaceableSlice(
|
|
base: Base(elements: array))
|
|
}
|
|
|
|
public init(elements: [Element]) {
|
|
self = DefaultedForwardRangeReplaceableSlice(
|
|
base: Base(elements: elements))
|
|
}
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
return MinimalIterator(Array(self))
|
|
}
|
|
|
|
public subscript(index: Index) -> Element {
|
|
Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
|
|
return base[index]
|
|
}
|
|
|
|
public subscript(bounds: Range<Index>) -> Self_ {
|
|
Index._failEarlyRangeCheck2(
|
|
rangeStart: bounds.lowerBound,
|
|
rangeEnd: bounds.upperBound,
|
|
boundsStart: startIndex,
|
|
boundsEnd: endIndex)
|
|
return DefaultedForwardRangeReplaceableSlice(
|
|
base: base, bounds: bounds)
|
|
}
|
|
|
|
public mutating func replaceSubrange<
|
|
C : Collection
|
|
>(
|
|
_ subRange: Range<Index>,
|
|
with newElements: C
|
|
) where C.Element == Element {
|
|
let startOffset = startIndex.position
|
|
let endOffset =
|
|
endIndex.position
|
|
- subRange.count
|
|
+ numericCast(newElements.count) as Int
|
|
Index._failEarlyRangeCheck2(
|
|
rangeStart: subRange.lowerBound,
|
|
rangeEnd: subRange.upperBound,
|
|
boundsStart: startIndex,
|
|
boundsEnd: endIndex)
|
|
base.replaceSubrange(subRange, with: newElements)
|
|
startIndex = base.startIndex.advanced(by: startOffset)
|
|
endIndex = base.startIndex.advanced(by: endOffset)
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
/// A Collection that uses as many default implementations as
|
|
/// `Collection` can provide.
|
|
public struct DefaultedRangeReplaceableCollection<Element> : Collection, RangeReplaceableCollection {
|
|
public typealias Base = MinimalRangeReplaceableCollection<Element>
|
|
public typealias Iterator = MinimalIterator<Element>
|
|
public typealias Index = MinimalIndex
|
|
|
|
|
|
public var base: Base
|
|
|
|
public init(base: Base) {
|
|
self.base = base
|
|
}
|
|
|
|
public init(_ array: [Element]) {
|
|
self.base = Base(elements: array)
|
|
}
|
|
|
|
public init(elements: [Element]) {
|
|
self.base = Base(elements: elements)
|
|
}
|
|
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == Element {
|
|
self.init(base:
|
|
MinimalRangeReplaceableCollection(elements: elements, underestimatedCount: underestimatedCount))
|
|
}
|
|
|
|
public var underestimatedCount: Int {
|
|
return base.underestimatedCount
|
|
}
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return base.makeIterator()
|
|
}
|
|
|
|
|
|
public let timesSuccessorCalled = ResettableValue(0)
|
|
|
|
public func index(after i: MinimalIndex) -> MinimalIndex {
|
|
timesSuccessorCalled.value += 1
|
|
return base.index(after: i)
|
|
}
|
|
|
|
|
|
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return base.startIndex
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return base.endIndex
|
|
}
|
|
|
|
public subscript(i: MinimalIndex) -> Element {
|
|
get {
|
|
return base[i]
|
|
}
|
|
}
|
|
|
|
// FIXME: swift-3-indexing-model: use defaults.
|
|
// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
|
|
|
|
public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedRangeReplaceableCollection<Base.Element>> {
|
|
get {
|
|
// FIXME: swift-3-indexing-model: range check.
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
}
|
|
|
|
public init() {
|
|
base = Base()
|
|
}
|
|
|
|
public mutating func replaceSubrange<C>(
|
|
_ subRange: Range<DefaultedRangeReplaceableCollection<Element>.Index>,
|
|
with newElements: C
|
|
) where C : Collection, C.Element == Element {
|
|
base.replaceSubrange(subRange, with: newElements)
|
|
}
|
|
}
|
|
|
|
/*
|
|
FIXME: swift-3-indexing-model: uncomment this.
|
|
public struct DefaultedForwardRangeReplaceableSlice<Element>
|
|
: RangeReplaceableCollection {
|
|
|
|
public typealias Self_ = DefaultedForwardRangeReplaceableSlice<Element>
|
|
public typealias Base = MinimalRangeReplaceableCollection<Element>
|
|
public typealias Iterator = MinimalIterator<Element>
|
|
public typealias Index = MinimalIndex
|
|
|
|
public var base: Base
|
|
public var startIndex: Index
|
|
public var endIndex: Index
|
|
|
|
public init() {
|
|
expectSliceType(Self_.self)
|
|
|
|
self.base = Base()
|
|
self.startIndex = base.startIndex
|
|
self.endIndex = base.endIndex
|
|
}
|
|
|
|
public init(base: Base) {
|
|
self.base = base
|
|
self.startIndex = base.startIndex
|
|
self.endIndex = base.endIndex
|
|
}
|
|
|
|
public init(base: Base, bounds: Range<Index>) {
|
|
self.base = base
|
|
self.startIndex = bounds.lowerBound
|
|
self.endIndex = bounds.upperBound
|
|
}
|
|
|
|
public init(_ array: [Element]) {
|
|
self = DefaultedForwardRangeReplaceableSlice(
|
|
base: Base(elements: array))
|
|
}
|
|
|
|
public init(elements: [Element]) {
|
|
self = DefaultedForwardRangeReplaceableSlice(
|
|
base: Base(elements: elements))
|
|
}
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
return MinimalIterator(Array(self))
|
|
}
|
|
|
|
public subscript(index: Index) -> Element {
|
|
Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
|
|
return base[index]
|
|
}
|
|
|
|
public subscript(bounds: Range<Index>) -> Self_ {
|
|
Index._failEarlyRangeCheck2(
|
|
rangeStart: bounds.lowerBound,
|
|
rangeEnd: bounds.upperBound,
|
|
boundsStart: startIndex,
|
|
boundsEnd: endIndex)
|
|
return DefaultedForwardRangeReplaceableSlice(
|
|
base: base, bounds: bounds)
|
|
}
|
|
|
|
public mutating func replaceSubrange<
|
|
C : Collection
|
|
>(
|
|
_ subRange: Range<Index>,
|
|
with newElements: C
|
|
) where C.Element == Element {
|
|
let startOffset = startIndex.position
|
|
let endOffset =
|
|
endIndex.position
|
|
- subRange.count
|
|
+ numericCast(newElements.count) as Int
|
|
Index._failEarlyRangeCheck2(
|
|
rangeStart: subRange.lowerBound,
|
|
rangeEnd: subRange.upperBound,
|
|
boundsStart: startIndex,
|
|
boundsEnd: endIndex)
|
|
base.replaceSubrange(subRange, with: newElements)
|
|
startIndex = base.startIndex.advanced(by: startOffset)
|
|
endIndex = base.startIndex.advanced(by: endOffset)
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
/// A Collection that uses as many default implementations as
|
|
/// `Collection` can provide.
|
|
public struct DefaultedMutableCollection<Element> : Collection, MutableCollection {
|
|
public typealias Base = MinimalMutableCollection<Element>
|
|
public typealias Iterator = MinimalIterator<Element>
|
|
public typealias Index = MinimalIndex
|
|
|
|
|
|
public var base: Base
|
|
|
|
public init(base: Base) {
|
|
self.base = base
|
|
}
|
|
|
|
public init(_ array: [Element]) {
|
|
self.base = Base(elements: array)
|
|
}
|
|
|
|
public init(elements: [Element]) {
|
|
self.base = Base(elements: elements)
|
|
}
|
|
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == Element {
|
|
self.init(base:
|
|
MinimalMutableCollection(elements: elements, underestimatedCount: underestimatedCount))
|
|
}
|
|
|
|
public var underestimatedCount: Int {
|
|
return base.underestimatedCount
|
|
}
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return base.makeIterator()
|
|
}
|
|
|
|
|
|
public let timesSuccessorCalled = ResettableValue(0)
|
|
|
|
public func index(after i: MinimalIndex) -> MinimalIndex {
|
|
timesSuccessorCalled.value += 1
|
|
return base.index(after: i)
|
|
}
|
|
|
|
|
|
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return base.startIndex
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return base.endIndex
|
|
}
|
|
|
|
public subscript(i: MinimalIndex) -> Element {
|
|
get {
|
|
return base[i]
|
|
}
|
|
set {
|
|
base[i] = newValue
|
|
}
|
|
}
|
|
|
|
// FIXME: swift-3-indexing-model: use defaults.
|
|
// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
|
|
|
|
public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedMutableCollection<Base.Element>> {
|
|
get {
|
|
// FIXME: swift-3-indexing-model: range check.
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
set {
|
|
_writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
FIXME: swift-3-indexing-model: uncomment this.
|
|
public struct DefaultedForwardRangeReplaceableSlice<Element>
|
|
: RangeReplaceableCollection {
|
|
|
|
public typealias Self_ = DefaultedForwardRangeReplaceableSlice<Element>
|
|
public typealias Base = MinimalMutableCollection<Element>
|
|
public typealias Iterator = MinimalIterator<Element>
|
|
public typealias Index = MinimalIndex
|
|
|
|
public var base: Base
|
|
public var startIndex: Index
|
|
public var endIndex: Index
|
|
|
|
public init() {
|
|
expectSliceType(Self_.self)
|
|
|
|
self.base = Base()
|
|
self.startIndex = base.startIndex
|
|
self.endIndex = base.endIndex
|
|
}
|
|
|
|
public init(base: Base) {
|
|
self.base = base
|
|
self.startIndex = base.startIndex
|
|
self.endIndex = base.endIndex
|
|
}
|
|
|
|
public init(base: Base, bounds: Range<Index>) {
|
|
self.base = base
|
|
self.startIndex = bounds.lowerBound
|
|
self.endIndex = bounds.upperBound
|
|
}
|
|
|
|
public init(_ array: [Element]) {
|
|
self = DefaultedForwardRangeReplaceableSlice(
|
|
base: Base(elements: array))
|
|
}
|
|
|
|
public init(elements: [Element]) {
|
|
self = DefaultedForwardRangeReplaceableSlice(
|
|
base: Base(elements: elements))
|
|
}
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
return MinimalIterator(Array(self))
|
|
}
|
|
|
|
public subscript(index: Index) -> Element {
|
|
Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
|
|
return base[index]
|
|
}
|
|
|
|
public subscript(bounds: Range<Index>) -> Self_ {
|
|
Index._failEarlyRangeCheck2(
|
|
rangeStart: bounds.lowerBound,
|
|
rangeEnd: bounds.upperBound,
|
|
boundsStart: startIndex,
|
|
boundsEnd: endIndex)
|
|
return DefaultedForwardRangeReplaceableSlice(
|
|
base: base, bounds: bounds)
|
|
}
|
|
|
|
public mutating func replaceSubrange<
|
|
C : Collection
|
|
>(
|
|
_ subRange: Range<Index>,
|
|
with newElements: C
|
|
) where C.Element == Element {
|
|
let startOffset = startIndex.position
|
|
let endOffset =
|
|
endIndex.position
|
|
- subRange.count
|
|
+ numericCast(newElements.count) as Int
|
|
Index._failEarlyRangeCheck2(
|
|
rangeStart: subRange.lowerBound,
|
|
rangeEnd: subRange.upperBound,
|
|
boundsStart: startIndex,
|
|
boundsEnd: endIndex)
|
|
base.replaceSubrange(subRange, with: newElements)
|
|
startIndex = base.startIndex.advanced(by: startOffset)
|
|
endIndex = base.startIndex.advanced(by: endOffset)
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
/// A Collection that uses as many default implementations as
|
|
/// `Collection` can provide.
|
|
public struct DefaultedMutableRangeReplaceableCollection<Element> : Collection, MutableCollection, RangeReplaceableCollection {
|
|
public typealias Base = MinimalMutableRangeReplaceableCollection<Element>
|
|
public typealias Iterator = MinimalIterator<Element>
|
|
public typealias Index = MinimalIndex
|
|
|
|
|
|
public var base: Base
|
|
|
|
public init(base: Base) {
|
|
self.base = base
|
|
}
|
|
|
|
public init(_ array: [Element]) {
|
|
self.base = Base(elements: array)
|
|
}
|
|
|
|
public init(elements: [Element]) {
|
|
self.base = Base(elements: elements)
|
|
}
|
|
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == Element {
|
|
self.init(base:
|
|
MinimalMutableRangeReplaceableCollection(elements: elements, underestimatedCount: underestimatedCount))
|
|
}
|
|
|
|
public var underestimatedCount: Int {
|
|
return base.underestimatedCount
|
|
}
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return base.makeIterator()
|
|
}
|
|
|
|
|
|
public let timesSuccessorCalled = ResettableValue(0)
|
|
|
|
public func index(after i: MinimalIndex) -> MinimalIndex {
|
|
timesSuccessorCalled.value += 1
|
|
return base.index(after: i)
|
|
}
|
|
|
|
|
|
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return base.startIndex
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return base.endIndex
|
|
}
|
|
|
|
public subscript(i: MinimalIndex) -> Element {
|
|
get {
|
|
return base[i]
|
|
}
|
|
set {
|
|
base[i] = newValue
|
|
}
|
|
}
|
|
|
|
// FIXME: swift-3-indexing-model: use defaults.
|
|
// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
|
|
|
|
public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedMutableRangeReplaceableCollection<Base.Element>> {
|
|
get {
|
|
// FIXME: swift-3-indexing-model: range check.
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
set {
|
|
_writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
|
|
}
|
|
}
|
|
|
|
public init() {
|
|
base = Base()
|
|
}
|
|
|
|
public mutating func replaceSubrange<C>(
|
|
_ subRange: Range<DefaultedMutableRangeReplaceableCollection<Element>.Index>,
|
|
with newElements: C
|
|
) where C : Collection, C.Element == Element {
|
|
base.replaceSubrange(subRange, with: newElements)
|
|
}
|
|
}
|
|
|
|
/*
|
|
FIXME: swift-3-indexing-model: uncomment this.
|
|
public struct DefaultedForwardRangeReplaceableSlice<Element>
|
|
: RangeReplaceableCollection {
|
|
|
|
public typealias Self_ = DefaultedForwardRangeReplaceableSlice<Element>
|
|
public typealias Base = MinimalMutableRangeReplaceableCollection<Element>
|
|
public typealias Iterator = MinimalIterator<Element>
|
|
public typealias Index = MinimalIndex
|
|
|
|
public var base: Base
|
|
public var startIndex: Index
|
|
public var endIndex: Index
|
|
|
|
public init() {
|
|
expectSliceType(Self_.self)
|
|
|
|
self.base = Base()
|
|
self.startIndex = base.startIndex
|
|
self.endIndex = base.endIndex
|
|
}
|
|
|
|
public init(base: Base) {
|
|
self.base = base
|
|
self.startIndex = base.startIndex
|
|
self.endIndex = base.endIndex
|
|
}
|
|
|
|
public init(base: Base, bounds: Range<Index>) {
|
|
self.base = base
|
|
self.startIndex = bounds.lowerBound
|
|
self.endIndex = bounds.upperBound
|
|
}
|
|
|
|
public init(_ array: [Element]) {
|
|
self = DefaultedForwardRangeReplaceableSlice(
|
|
base: Base(elements: array))
|
|
}
|
|
|
|
public init(elements: [Element]) {
|
|
self = DefaultedForwardRangeReplaceableSlice(
|
|
base: Base(elements: elements))
|
|
}
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
return MinimalIterator(Array(self))
|
|
}
|
|
|
|
public subscript(index: Index) -> Element {
|
|
Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
|
|
return base[index]
|
|
}
|
|
|
|
public subscript(bounds: Range<Index>) -> Self_ {
|
|
Index._failEarlyRangeCheck2(
|
|
rangeStart: bounds.lowerBound,
|
|
rangeEnd: bounds.upperBound,
|
|
boundsStart: startIndex,
|
|
boundsEnd: endIndex)
|
|
return DefaultedForwardRangeReplaceableSlice(
|
|
base: base, bounds: bounds)
|
|
}
|
|
|
|
public mutating func replaceSubrange<
|
|
C : Collection
|
|
>(
|
|
_ subRange: Range<Index>,
|
|
with newElements: C
|
|
) where C.Element == Element {
|
|
let startOffset = startIndex.position
|
|
let endOffset =
|
|
endIndex.position
|
|
- subRange.count
|
|
+ numericCast(newElements.count) as Int
|
|
Index._failEarlyRangeCheck2(
|
|
rangeStart: subRange.lowerBound,
|
|
rangeEnd: subRange.upperBound,
|
|
boundsStart: startIndex,
|
|
boundsEnd: endIndex)
|
|
base.replaceSubrange(subRange, with: newElements)
|
|
startIndex = base.startIndex.advanced(by: startOffset)
|
|
endIndex = base.startIndex.advanced(by: endOffset)
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
/// A Collection that uses as many default implementations as
|
|
/// `Collection` can provide.
|
|
public struct DefaultedBidirectionalCollection<Element> : BidirectionalCollection {
|
|
public typealias Base = MinimalBidirectionalCollection<Element>
|
|
public typealias Iterator = MinimalIterator<Element>
|
|
public typealias Index = MinimalIndex
|
|
|
|
|
|
public let base: Base
|
|
|
|
public init(base: Base) {
|
|
self.base = base
|
|
}
|
|
|
|
public init(_ array: [Element]) {
|
|
self.base = Base(elements: array)
|
|
}
|
|
|
|
public init(elements: [Element]) {
|
|
self.base = Base(elements: elements)
|
|
}
|
|
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == Element {
|
|
self.init(base:
|
|
MinimalBidirectionalCollection(elements: elements, underestimatedCount: underestimatedCount))
|
|
}
|
|
|
|
public var underestimatedCount: Int {
|
|
return base.underestimatedCount
|
|
}
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return base.makeIterator()
|
|
}
|
|
|
|
|
|
public let timesSuccessorCalled = ResettableValue(0)
|
|
|
|
public func index(after i: MinimalIndex) -> MinimalIndex {
|
|
timesSuccessorCalled.value += 1
|
|
return base.index(after: i)
|
|
}
|
|
|
|
public let timesPredecessorCalled = ResettableValue(0)
|
|
|
|
public func index(before i: MinimalIndex) -> MinimalIndex {
|
|
timesPredecessorCalled.value += 1
|
|
return base.index(before: i)
|
|
}
|
|
|
|
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return base.startIndex
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return base.endIndex
|
|
}
|
|
|
|
public subscript(i: MinimalIndex) -> Element {
|
|
get {
|
|
return base[i]
|
|
}
|
|
}
|
|
|
|
// FIXME: swift-3-indexing-model: use defaults.
|
|
// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
|
|
|
|
public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedBidirectionalCollection<Base.Element>> {
|
|
get {
|
|
// FIXME: swift-3-indexing-model: range check.
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
FIXME: swift-3-indexing-model: uncomment this.
|
|
public struct DefaultedBidirectionalRangeReplaceableSlice<Element>
|
|
: RangeReplaceableCollection {
|
|
|
|
public typealias Self_ = DefaultedBidirectionalRangeReplaceableSlice<Element>
|
|
public typealias Base = MinimalBidirectionalCollection<Element>
|
|
public typealias Iterator = MinimalIterator<Element>
|
|
public typealias Index = MinimalIndex
|
|
|
|
public var base: Base
|
|
public var startIndex: Index
|
|
public var endIndex: Index
|
|
|
|
public init() {
|
|
expectSliceType(Self_.self)
|
|
|
|
self.base = Base()
|
|
self.startIndex = base.startIndex
|
|
self.endIndex = base.endIndex
|
|
}
|
|
|
|
public init(base: Base) {
|
|
self.base = base
|
|
self.startIndex = base.startIndex
|
|
self.endIndex = base.endIndex
|
|
}
|
|
|
|
public init(base: Base, bounds: Range<Index>) {
|
|
self.base = base
|
|
self.startIndex = bounds.lowerBound
|
|
self.endIndex = bounds.upperBound
|
|
}
|
|
|
|
public init(_ array: [Element]) {
|
|
self = DefaultedBidirectionalRangeReplaceableSlice(
|
|
base: Base(elements: array))
|
|
}
|
|
|
|
public init(elements: [Element]) {
|
|
self = DefaultedBidirectionalRangeReplaceableSlice(
|
|
base: Base(elements: elements))
|
|
}
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
return MinimalIterator(Array(self))
|
|
}
|
|
|
|
public subscript(index: Index) -> Element {
|
|
Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
|
|
return base[index]
|
|
}
|
|
|
|
public subscript(bounds: Range<Index>) -> Self_ {
|
|
Index._failEarlyRangeCheck2(
|
|
rangeStart: bounds.lowerBound,
|
|
rangeEnd: bounds.upperBound,
|
|
boundsStart: startIndex,
|
|
boundsEnd: endIndex)
|
|
return DefaultedBidirectionalRangeReplaceableSlice(
|
|
base: base, bounds: bounds)
|
|
}
|
|
|
|
public mutating func replaceSubrange<
|
|
C : Collection
|
|
>(
|
|
_ subRange: Range<Index>,
|
|
with newElements: C
|
|
) where C.Element == Element {
|
|
let startOffset = startIndex.position
|
|
let endOffset =
|
|
endIndex.position
|
|
- subRange.count
|
|
+ numericCast(newElements.count) as Int
|
|
Index._failEarlyRangeCheck2(
|
|
rangeStart: subRange.lowerBound,
|
|
rangeEnd: subRange.upperBound,
|
|
boundsStart: startIndex,
|
|
boundsEnd: endIndex)
|
|
base.replaceSubrange(subRange, with: newElements)
|
|
startIndex = base.startIndex.advanced(by: startOffset)
|
|
endIndex = base.startIndex.advanced(by: endOffset)
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
/// A Collection that uses as many default implementations as
|
|
/// `Collection` can provide.
|
|
public struct DefaultedRangeReplaceableBidirectionalCollection<Element> : BidirectionalCollection, RangeReplaceableCollection {
|
|
public typealias Base = MinimalRangeReplaceableBidirectionalCollection<Element>
|
|
public typealias Iterator = MinimalIterator<Element>
|
|
public typealias Index = MinimalIndex
|
|
|
|
|
|
public var base: Base
|
|
|
|
public init(base: Base) {
|
|
self.base = base
|
|
}
|
|
|
|
public init(_ array: [Element]) {
|
|
self.base = Base(elements: array)
|
|
}
|
|
|
|
public init(elements: [Element]) {
|
|
self.base = Base(elements: elements)
|
|
}
|
|
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == Element {
|
|
self.init(base:
|
|
MinimalRangeReplaceableBidirectionalCollection(elements: elements, underestimatedCount: underestimatedCount))
|
|
}
|
|
|
|
public var underestimatedCount: Int {
|
|
return base.underestimatedCount
|
|
}
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return base.makeIterator()
|
|
}
|
|
|
|
|
|
public let timesSuccessorCalled = ResettableValue(0)
|
|
|
|
public func index(after i: MinimalIndex) -> MinimalIndex {
|
|
timesSuccessorCalled.value += 1
|
|
return base.index(after: i)
|
|
}
|
|
|
|
public let timesPredecessorCalled = ResettableValue(0)
|
|
|
|
public func index(before i: MinimalIndex) -> MinimalIndex {
|
|
timesPredecessorCalled.value += 1
|
|
return base.index(before: i)
|
|
}
|
|
|
|
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return base.startIndex
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return base.endIndex
|
|
}
|
|
|
|
public subscript(i: MinimalIndex) -> Element {
|
|
get {
|
|
return base[i]
|
|
}
|
|
}
|
|
|
|
// FIXME: swift-3-indexing-model: use defaults.
|
|
// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
|
|
|
|
public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedRangeReplaceableBidirectionalCollection<Base.Element>> {
|
|
get {
|
|
// FIXME: swift-3-indexing-model: range check.
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
}
|
|
|
|
public init() {
|
|
base = Base()
|
|
}
|
|
|
|
public mutating func replaceSubrange<C>(
|
|
_ subRange: Range<DefaultedRangeReplaceableBidirectionalCollection<Element>.Index>,
|
|
with newElements: C
|
|
) where C : Collection, C.Element == Element {
|
|
base.replaceSubrange(subRange, with: newElements)
|
|
}
|
|
}
|
|
|
|
/*
|
|
FIXME: swift-3-indexing-model: uncomment this.
|
|
public struct DefaultedBidirectionalRangeReplaceableSlice<Element>
|
|
: RangeReplaceableCollection {
|
|
|
|
public typealias Self_ = DefaultedBidirectionalRangeReplaceableSlice<Element>
|
|
public typealias Base = MinimalRangeReplaceableBidirectionalCollection<Element>
|
|
public typealias Iterator = MinimalIterator<Element>
|
|
public typealias Index = MinimalIndex
|
|
|
|
public var base: Base
|
|
public var startIndex: Index
|
|
public var endIndex: Index
|
|
|
|
public init() {
|
|
expectSliceType(Self_.self)
|
|
|
|
self.base = Base()
|
|
self.startIndex = base.startIndex
|
|
self.endIndex = base.endIndex
|
|
}
|
|
|
|
public init(base: Base) {
|
|
self.base = base
|
|
self.startIndex = base.startIndex
|
|
self.endIndex = base.endIndex
|
|
}
|
|
|
|
public init(base: Base, bounds: Range<Index>) {
|
|
self.base = base
|
|
self.startIndex = bounds.lowerBound
|
|
self.endIndex = bounds.upperBound
|
|
}
|
|
|
|
public init(_ array: [Element]) {
|
|
self = DefaultedBidirectionalRangeReplaceableSlice(
|
|
base: Base(elements: array))
|
|
}
|
|
|
|
public init(elements: [Element]) {
|
|
self = DefaultedBidirectionalRangeReplaceableSlice(
|
|
base: Base(elements: elements))
|
|
}
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
return MinimalIterator(Array(self))
|
|
}
|
|
|
|
public subscript(index: Index) -> Element {
|
|
Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
|
|
return base[index]
|
|
}
|
|
|
|
public subscript(bounds: Range<Index>) -> Self_ {
|
|
Index._failEarlyRangeCheck2(
|
|
rangeStart: bounds.lowerBound,
|
|
rangeEnd: bounds.upperBound,
|
|
boundsStart: startIndex,
|
|
boundsEnd: endIndex)
|
|
return DefaultedBidirectionalRangeReplaceableSlice(
|
|
base: base, bounds: bounds)
|
|
}
|
|
|
|
public mutating func replaceSubrange<
|
|
C : Collection
|
|
>(
|
|
_ subRange: Range<Index>,
|
|
with newElements: C
|
|
) where C.Element == Element {
|
|
let startOffset = startIndex.position
|
|
let endOffset =
|
|
endIndex.position
|
|
- subRange.count
|
|
+ numericCast(newElements.count) as Int
|
|
Index._failEarlyRangeCheck2(
|
|
rangeStart: subRange.lowerBound,
|
|
rangeEnd: subRange.upperBound,
|
|
boundsStart: startIndex,
|
|
boundsEnd: endIndex)
|
|
base.replaceSubrange(subRange, with: newElements)
|
|
startIndex = base.startIndex.advanced(by: startOffset)
|
|
endIndex = base.startIndex.advanced(by: endOffset)
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
/// A Collection that uses as many default implementations as
|
|
/// `Collection` can provide.
|
|
public struct DefaultedMutableBidirectionalCollection<Element> : BidirectionalCollection, MutableCollection {
|
|
public typealias Base = MinimalMutableBidirectionalCollection<Element>
|
|
public typealias Iterator = MinimalIterator<Element>
|
|
public typealias Index = MinimalIndex
|
|
|
|
|
|
public var base: Base
|
|
|
|
public init(base: Base) {
|
|
self.base = base
|
|
}
|
|
|
|
public init(_ array: [Element]) {
|
|
self.base = Base(elements: array)
|
|
}
|
|
|
|
public init(elements: [Element]) {
|
|
self.base = Base(elements: elements)
|
|
}
|
|
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == Element {
|
|
self.init(base:
|
|
MinimalMutableBidirectionalCollection(elements: elements, underestimatedCount: underestimatedCount))
|
|
}
|
|
|
|
public var underestimatedCount: Int {
|
|
return base.underestimatedCount
|
|
}
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return base.makeIterator()
|
|
}
|
|
|
|
|
|
public let timesSuccessorCalled = ResettableValue(0)
|
|
|
|
public func index(after i: MinimalIndex) -> MinimalIndex {
|
|
timesSuccessorCalled.value += 1
|
|
return base.index(after: i)
|
|
}
|
|
|
|
public let timesPredecessorCalled = ResettableValue(0)
|
|
|
|
public func index(before i: MinimalIndex) -> MinimalIndex {
|
|
timesPredecessorCalled.value += 1
|
|
return base.index(before: i)
|
|
}
|
|
|
|
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return base.startIndex
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return base.endIndex
|
|
}
|
|
|
|
public subscript(i: MinimalIndex) -> Element {
|
|
get {
|
|
return base[i]
|
|
}
|
|
set {
|
|
base[i] = newValue
|
|
}
|
|
}
|
|
|
|
// FIXME: swift-3-indexing-model: use defaults.
|
|
// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
|
|
|
|
public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedMutableBidirectionalCollection<Base.Element>> {
|
|
get {
|
|
// FIXME: swift-3-indexing-model: range check.
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
set {
|
|
_writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
FIXME: swift-3-indexing-model: uncomment this.
|
|
public struct DefaultedBidirectionalRangeReplaceableSlice<Element>
|
|
: RangeReplaceableCollection {
|
|
|
|
public typealias Self_ = DefaultedBidirectionalRangeReplaceableSlice<Element>
|
|
public typealias Base = MinimalMutableBidirectionalCollection<Element>
|
|
public typealias Iterator = MinimalIterator<Element>
|
|
public typealias Index = MinimalIndex
|
|
|
|
public var base: Base
|
|
public var startIndex: Index
|
|
public var endIndex: Index
|
|
|
|
public init() {
|
|
expectSliceType(Self_.self)
|
|
|
|
self.base = Base()
|
|
self.startIndex = base.startIndex
|
|
self.endIndex = base.endIndex
|
|
}
|
|
|
|
public init(base: Base) {
|
|
self.base = base
|
|
self.startIndex = base.startIndex
|
|
self.endIndex = base.endIndex
|
|
}
|
|
|
|
public init(base: Base, bounds: Range<Index>) {
|
|
self.base = base
|
|
self.startIndex = bounds.lowerBound
|
|
self.endIndex = bounds.upperBound
|
|
}
|
|
|
|
public init(_ array: [Element]) {
|
|
self = DefaultedBidirectionalRangeReplaceableSlice(
|
|
base: Base(elements: array))
|
|
}
|
|
|
|
public init(elements: [Element]) {
|
|
self = DefaultedBidirectionalRangeReplaceableSlice(
|
|
base: Base(elements: elements))
|
|
}
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
return MinimalIterator(Array(self))
|
|
}
|
|
|
|
public subscript(index: Index) -> Element {
|
|
Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
|
|
return base[index]
|
|
}
|
|
|
|
public subscript(bounds: Range<Index>) -> Self_ {
|
|
Index._failEarlyRangeCheck2(
|
|
rangeStart: bounds.lowerBound,
|
|
rangeEnd: bounds.upperBound,
|
|
boundsStart: startIndex,
|
|
boundsEnd: endIndex)
|
|
return DefaultedBidirectionalRangeReplaceableSlice(
|
|
base: base, bounds: bounds)
|
|
}
|
|
|
|
public mutating func replaceSubrange<
|
|
C : Collection
|
|
>(
|
|
_ subRange: Range<Index>,
|
|
with newElements: C
|
|
) where C.Element == Element {
|
|
let startOffset = startIndex.position
|
|
let endOffset =
|
|
endIndex.position
|
|
- subRange.count
|
|
+ numericCast(newElements.count) as Int
|
|
Index._failEarlyRangeCheck2(
|
|
rangeStart: subRange.lowerBound,
|
|
rangeEnd: subRange.upperBound,
|
|
boundsStart: startIndex,
|
|
boundsEnd: endIndex)
|
|
base.replaceSubrange(subRange, with: newElements)
|
|
startIndex = base.startIndex.advanced(by: startOffset)
|
|
endIndex = base.startIndex.advanced(by: endOffset)
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
/// A Collection that uses as many default implementations as
|
|
/// `Collection` can provide.
|
|
public struct DefaultedMutableRangeReplaceableBidirectionalCollection<Element> : BidirectionalCollection, MutableCollection, RangeReplaceableCollection {
|
|
public typealias Base = MinimalMutableRangeReplaceableBidirectionalCollection<Element>
|
|
public typealias Iterator = MinimalIterator<Element>
|
|
public typealias Index = MinimalIndex
|
|
|
|
|
|
public var base: Base
|
|
|
|
public init(base: Base) {
|
|
self.base = base
|
|
}
|
|
|
|
public init(_ array: [Element]) {
|
|
self.base = Base(elements: array)
|
|
}
|
|
|
|
public init(elements: [Element]) {
|
|
self.base = Base(elements: elements)
|
|
}
|
|
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == Element {
|
|
self.init(base:
|
|
MinimalMutableRangeReplaceableBidirectionalCollection(elements: elements, underestimatedCount: underestimatedCount))
|
|
}
|
|
|
|
public var underestimatedCount: Int {
|
|
return base.underestimatedCount
|
|
}
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return base.makeIterator()
|
|
}
|
|
|
|
|
|
public let timesSuccessorCalled = ResettableValue(0)
|
|
|
|
public func index(after i: MinimalIndex) -> MinimalIndex {
|
|
timesSuccessorCalled.value += 1
|
|
return base.index(after: i)
|
|
}
|
|
|
|
public let timesPredecessorCalled = ResettableValue(0)
|
|
|
|
public func index(before i: MinimalIndex) -> MinimalIndex {
|
|
timesPredecessorCalled.value += 1
|
|
return base.index(before: i)
|
|
}
|
|
|
|
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return base.startIndex
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return base.endIndex
|
|
}
|
|
|
|
public subscript(i: MinimalIndex) -> Element {
|
|
get {
|
|
return base[i]
|
|
}
|
|
set {
|
|
base[i] = newValue
|
|
}
|
|
}
|
|
|
|
// FIXME: swift-3-indexing-model: use defaults.
|
|
// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
|
|
|
|
public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedMutableRangeReplaceableBidirectionalCollection<Base.Element>> {
|
|
get {
|
|
// FIXME: swift-3-indexing-model: range check.
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
set {
|
|
_writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
|
|
}
|
|
}
|
|
|
|
public init() {
|
|
base = Base()
|
|
}
|
|
|
|
public mutating func replaceSubrange<C>(
|
|
_ subRange: Range<DefaultedMutableRangeReplaceableBidirectionalCollection<Element>.Index>,
|
|
with newElements: C
|
|
) where C : Collection, C.Element == Element {
|
|
base.replaceSubrange(subRange, with: newElements)
|
|
}
|
|
}
|
|
|
|
/*
|
|
FIXME: swift-3-indexing-model: uncomment this.
|
|
public struct DefaultedBidirectionalRangeReplaceableSlice<Element>
|
|
: RangeReplaceableCollection {
|
|
|
|
public typealias Self_ = DefaultedBidirectionalRangeReplaceableSlice<Element>
|
|
public typealias Base = MinimalMutableRangeReplaceableBidirectionalCollection<Element>
|
|
public typealias Iterator = MinimalIterator<Element>
|
|
public typealias Index = MinimalIndex
|
|
|
|
public var base: Base
|
|
public var startIndex: Index
|
|
public var endIndex: Index
|
|
|
|
public init() {
|
|
expectSliceType(Self_.self)
|
|
|
|
self.base = Base()
|
|
self.startIndex = base.startIndex
|
|
self.endIndex = base.endIndex
|
|
}
|
|
|
|
public init(base: Base) {
|
|
self.base = base
|
|
self.startIndex = base.startIndex
|
|
self.endIndex = base.endIndex
|
|
}
|
|
|
|
public init(base: Base, bounds: Range<Index>) {
|
|
self.base = base
|
|
self.startIndex = bounds.lowerBound
|
|
self.endIndex = bounds.upperBound
|
|
}
|
|
|
|
public init(_ array: [Element]) {
|
|
self = DefaultedBidirectionalRangeReplaceableSlice(
|
|
base: Base(elements: array))
|
|
}
|
|
|
|
public init(elements: [Element]) {
|
|
self = DefaultedBidirectionalRangeReplaceableSlice(
|
|
base: Base(elements: elements))
|
|
}
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
return MinimalIterator(Array(self))
|
|
}
|
|
|
|
public subscript(index: Index) -> Element {
|
|
Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
|
|
return base[index]
|
|
}
|
|
|
|
public subscript(bounds: Range<Index>) -> Self_ {
|
|
Index._failEarlyRangeCheck2(
|
|
rangeStart: bounds.lowerBound,
|
|
rangeEnd: bounds.upperBound,
|
|
boundsStart: startIndex,
|
|
boundsEnd: endIndex)
|
|
return DefaultedBidirectionalRangeReplaceableSlice(
|
|
base: base, bounds: bounds)
|
|
}
|
|
|
|
public mutating func replaceSubrange<
|
|
C : Collection
|
|
>(
|
|
_ subRange: Range<Index>,
|
|
with newElements: C
|
|
) where C.Element == Element {
|
|
let startOffset = startIndex.position
|
|
let endOffset =
|
|
endIndex.position
|
|
- subRange.count
|
|
+ numericCast(newElements.count) as Int
|
|
Index._failEarlyRangeCheck2(
|
|
rangeStart: subRange.lowerBound,
|
|
rangeEnd: subRange.upperBound,
|
|
boundsStart: startIndex,
|
|
boundsEnd: endIndex)
|
|
base.replaceSubrange(subRange, with: newElements)
|
|
startIndex = base.startIndex.advanced(by: startOffset)
|
|
endIndex = base.startIndex.advanced(by: endOffset)
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
/// A Collection that uses as many default implementations as
|
|
/// `Collection` can provide.
|
|
public struct DefaultedRandomAccessCollection<Element> : RandomAccessCollection {
|
|
public typealias Base = MinimalRandomAccessCollection<Element>
|
|
public typealias Iterator = MinimalIterator<Element>
|
|
public typealias Index = MinimalIndex
|
|
|
|
// FIXME: this shouldn't be necessary, should come by default
|
|
public typealias Indices = DefaultIndices<DefaultedRandomAccessCollection<Element>>
|
|
|
|
public let base: Base
|
|
|
|
public init(base: Base) {
|
|
self.base = base
|
|
}
|
|
|
|
public init(_ array: [Element]) {
|
|
self.base = Base(elements: array)
|
|
}
|
|
|
|
public init(elements: [Element]) {
|
|
self.base = Base(elements: elements)
|
|
}
|
|
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == Element {
|
|
self.init(base:
|
|
MinimalRandomAccessCollection(elements: elements, underestimatedCount: underestimatedCount))
|
|
}
|
|
|
|
public var underestimatedCount: Int {
|
|
return base.underestimatedCount
|
|
}
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return base.makeIterator()
|
|
}
|
|
|
|
|
|
public let timesSuccessorCalled = ResettableValue(0)
|
|
|
|
public func index(after i: MinimalIndex) -> MinimalIndex {
|
|
timesSuccessorCalled.value += 1
|
|
return base.index(after: i)
|
|
}
|
|
|
|
public let timesPredecessorCalled = ResettableValue(0)
|
|
|
|
public func index(before i: MinimalIndex) -> MinimalIndex {
|
|
timesPredecessorCalled.value += 1
|
|
return base.index(before: i)
|
|
}
|
|
|
|
public func distance(from start: MinimalIndex, to end: MinimalIndex)
|
|
-> Int {
|
|
return base.distance(from: start, to: end)
|
|
}
|
|
|
|
public func index(_ i: Index, offsetBy n: Int) -> Index {
|
|
return base.index(i, offsetBy: n)
|
|
}
|
|
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return base.startIndex
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return base.endIndex
|
|
}
|
|
|
|
public subscript(i: MinimalIndex) -> Element {
|
|
get {
|
|
return base[i]
|
|
}
|
|
}
|
|
|
|
// FIXME: swift-3-indexing-model: use defaults.
|
|
// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
|
|
|
|
public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedRandomAccessCollection<Base.Element>> {
|
|
get {
|
|
// FIXME: swift-3-indexing-model: range check.
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
FIXME: swift-3-indexing-model: uncomment this.
|
|
public struct DefaultedRandomAccessRangeReplaceableSlice<Element>
|
|
: RangeReplaceableCollection {
|
|
|
|
public typealias Self_ = DefaultedRandomAccessRangeReplaceableSlice<Element>
|
|
public typealias Base = MinimalRandomAccessCollection<Element>
|
|
public typealias Iterator = MinimalIterator<Element>
|
|
public typealias Index = MinimalIndex
|
|
|
|
public var base: Base
|
|
public var startIndex: Index
|
|
public var endIndex: Index
|
|
|
|
public init() {
|
|
expectSliceType(Self_.self)
|
|
|
|
self.base = Base()
|
|
self.startIndex = base.startIndex
|
|
self.endIndex = base.endIndex
|
|
}
|
|
|
|
public init(base: Base) {
|
|
self.base = base
|
|
self.startIndex = base.startIndex
|
|
self.endIndex = base.endIndex
|
|
}
|
|
|
|
public init(base: Base, bounds: Range<Index>) {
|
|
self.base = base
|
|
self.startIndex = bounds.lowerBound
|
|
self.endIndex = bounds.upperBound
|
|
}
|
|
|
|
public init(_ array: [Element]) {
|
|
self = DefaultedRandomAccessRangeReplaceableSlice(
|
|
base: Base(elements: array))
|
|
}
|
|
|
|
public init(elements: [Element]) {
|
|
self = DefaultedRandomAccessRangeReplaceableSlice(
|
|
base: Base(elements: elements))
|
|
}
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
return MinimalIterator(Array(self))
|
|
}
|
|
|
|
public subscript(index: Index) -> Element {
|
|
Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
|
|
return base[index]
|
|
}
|
|
|
|
public subscript(bounds: Range<Index>) -> Self_ {
|
|
Index._failEarlyRangeCheck2(
|
|
rangeStart: bounds.lowerBound,
|
|
rangeEnd: bounds.upperBound,
|
|
boundsStart: startIndex,
|
|
boundsEnd: endIndex)
|
|
return DefaultedRandomAccessRangeReplaceableSlice(
|
|
base: base, bounds: bounds)
|
|
}
|
|
|
|
public mutating func replaceSubrange<
|
|
C : Collection
|
|
>(
|
|
_ subRange: Range<Index>,
|
|
with newElements: C
|
|
) where C.Element == Element {
|
|
let startOffset = startIndex.position
|
|
let endOffset =
|
|
endIndex.position
|
|
- subRange.count
|
|
+ numericCast(newElements.count) as Int
|
|
Index._failEarlyRangeCheck2(
|
|
rangeStart: subRange.lowerBound,
|
|
rangeEnd: subRange.upperBound,
|
|
boundsStart: startIndex,
|
|
boundsEnd: endIndex)
|
|
base.replaceSubrange(subRange, with: newElements)
|
|
startIndex = base.startIndex.advanced(by: startOffset)
|
|
endIndex = base.startIndex.advanced(by: endOffset)
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
/// A Collection that uses as many default implementations as
|
|
/// `Collection` can provide.
|
|
public struct DefaultedRandomAccessCollectionWithStrideableIndex<Element> : RandomAccessCollection {
|
|
public typealias Base = MinimalRandomAccessCollectionWithStrideableIndex<Element>
|
|
public typealias Iterator = MinimalIterator<Element>
|
|
public typealias Index = MinimalStrideableIndex
|
|
|
|
public typealias Indices = Range<MinimalStrideableIndex>
|
|
|
|
public let base: Base
|
|
|
|
public init(base: Base) {
|
|
self.base = base
|
|
}
|
|
|
|
public init(_ array: [Element]) {
|
|
self.base = Base(elements: array)
|
|
}
|
|
|
|
public init(elements: [Element]) {
|
|
self.base = Base(elements: elements)
|
|
}
|
|
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == Element {
|
|
self.init(base:
|
|
MinimalRandomAccessCollectionWithStrideableIndex(elements: elements, underestimatedCount: underestimatedCount))
|
|
}
|
|
|
|
public var underestimatedCount: Int {
|
|
return base.underestimatedCount
|
|
}
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return base.makeIterator()
|
|
}
|
|
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalStrideableIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return base.startIndex
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalStrideableIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return base.endIndex
|
|
}
|
|
|
|
public subscript(i: MinimalStrideableIndex) -> Element {
|
|
get {
|
|
return base[i]
|
|
}
|
|
}
|
|
|
|
// FIXME: swift-3-indexing-model: use defaults.
|
|
// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
|
|
|
|
public subscript(bounds: Range<MinimalStrideableIndex>) -> Slice<DefaultedRandomAccessCollectionWithStrideableIndex<Base.Element>> {
|
|
get {
|
|
// FIXME: swift-3-indexing-model: range check.
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
FIXME: swift-3-indexing-model: uncomment this.
|
|
public struct DefaultedRandomAccessRangeReplaceableSlice<Element>
|
|
: RangeReplaceableCollection {
|
|
|
|
public typealias Self_ = DefaultedRandomAccessRangeReplaceableSlice<Element>
|
|
public typealias Base = MinimalRandomAccessCollectionWithStrideableIndex<Element>
|
|
public typealias Iterator = MinimalIterator<Element>
|
|
public typealias Index = MinimalStrideableIndex
|
|
|
|
public var base: Base
|
|
public var startIndex: Index
|
|
public var endIndex: Index
|
|
|
|
public init() {
|
|
expectSliceType(Self_.self)
|
|
|
|
self.base = Base()
|
|
self.startIndex = base.startIndex
|
|
self.endIndex = base.endIndex
|
|
}
|
|
|
|
public init(base: Base) {
|
|
self.base = base
|
|
self.startIndex = base.startIndex
|
|
self.endIndex = base.endIndex
|
|
}
|
|
|
|
public init(base: Base, bounds: Range<Index>) {
|
|
self.base = base
|
|
self.startIndex = bounds.lowerBound
|
|
self.endIndex = bounds.upperBound
|
|
}
|
|
|
|
public init(_ array: [Element]) {
|
|
self = DefaultedRandomAccessRangeReplaceableSlice(
|
|
base: Base(elements: array))
|
|
}
|
|
|
|
public init(elements: [Element]) {
|
|
self = DefaultedRandomAccessRangeReplaceableSlice(
|
|
base: Base(elements: elements))
|
|
}
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
return MinimalIterator(Array(self))
|
|
}
|
|
|
|
public subscript(index: Index) -> Element {
|
|
Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
|
|
return base[index]
|
|
}
|
|
|
|
public subscript(bounds: Range<Index>) -> Self_ {
|
|
Index._failEarlyRangeCheck2(
|
|
rangeStart: bounds.lowerBound,
|
|
rangeEnd: bounds.upperBound,
|
|
boundsStart: startIndex,
|
|
boundsEnd: endIndex)
|
|
return DefaultedRandomAccessRangeReplaceableSlice(
|
|
base: base, bounds: bounds)
|
|
}
|
|
|
|
public mutating func replaceSubrange<
|
|
C : Collection
|
|
>(
|
|
_ subRange: Range<Index>,
|
|
with newElements: C
|
|
) where C.Element == Element {
|
|
let startOffset = startIndex.position
|
|
let endOffset =
|
|
endIndex.position
|
|
- subRange.count
|
|
+ numericCast(newElements.count) as Int
|
|
Index._failEarlyRangeCheck2(
|
|
rangeStart: subRange.lowerBound,
|
|
rangeEnd: subRange.upperBound,
|
|
boundsStart: startIndex,
|
|
boundsEnd: endIndex)
|
|
base.replaceSubrange(subRange, with: newElements)
|
|
startIndex = base.startIndex.advanced(by: startOffset)
|
|
endIndex = base.startIndex.advanced(by: endOffset)
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
/// A Collection that uses as many default implementations as
|
|
/// `Collection` can provide.
|
|
public struct DefaultedRangeReplaceableRandomAccessCollection<Element> : RandomAccessCollection, RangeReplaceableCollection {
|
|
public typealias Base = MinimalRangeReplaceableRandomAccessCollection<Element>
|
|
public typealias Iterator = MinimalIterator<Element>
|
|
public typealias Index = MinimalIndex
|
|
|
|
// FIXME: this shouldn't be necessary, should come by default
|
|
public typealias Indices = DefaultIndices<DefaultedRangeReplaceableRandomAccessCollection<Element>>
|
|
|
|
public var base: Base
|
|
|
|
public init(base: Base) {
|
|
self.base = base
|
|
}
|
|
|
|
public init(_ array: [Element]) {
|
|
self.base = Base(elements: array)
|
|
}
|
|
|
|
public init(elements: [Element]) {
|
|
self.base = Base(elements: elements)
|
|
}
|
|
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == Element {
|
|
self.init(base:
|
|
MinimalRangeReplaceableRandomAccessCollection(elements: elements, underestimatedCount: underestimatedCount))
|
|
}
|
|
|
|
public var underestimatedCount: Int {
|
|
return base.underestimatedCount
|
|
}
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return base.makeIterator()
|
|
}
|
|
|
|
|
|
public let timesSuccessorCalled = ResettableValue(0)
|
|
|
|
public func index(after i: MinimalIndex) -> MinimalIndex {
|
|
timesSuccessorCalled.value += 1
|
|
return base.index(after: i)
|
|
}
|
|
|
|
public let timesPredecessorCalled = ResettableValue(0)
|
|
|
|
public func index(before i: MinimalIndex) -> MinimalIndex {
|
|
timesPredecessorCalled.value += 1
|
|
return base.index(before: i)
|
|
}
|
|
|
|
public func distance(from start: MinimalIndex, to end: MinimalIndex)
|
|
-> Int {
|
|
return base.distance(from: start, to: end)
|
|
}
|
|
|
|
public func index(_ i: Index, offsetBy n: Int) -> Index {
|
|
return base.index(i, offsetBy: n)
|
|
}
|
|
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return base.startIndex
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return base.endIndex
|
|
}
|
|
|
|
public subscript(i: MinimalIndex) -> Element {
|
|
get {
|
|
return base[i]
|
|
}
|
|
}
|
|
|
|
// FIXME: swift-3-indexing-model: use defaults.
|
|
// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
|
|
|
|
public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedRangeReplaceableRandomAccessCollection<Base.Element>> {
|
|
get {
|
|
// FIXME: swift-3-indexing-model: range check.
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
}
|
|
|
|
public init() {
|
|
base = Base()
|
|
}
|
|
|
|
public mutating func replaceSubrange<C>(
|
|
_ subRange: Range<DefaultedRangeReplaceableRandomAccessCollection<Element>.Index>,
|
|
with newElements: C
|
|
) where C : Collection, C.Element == Element {
|
|
base.replaceSubrange(subRange, with: newElements)
|
|
}
|
|
}
|
|
|
|
/*
|
|
FIXME: swift-3-indexing-model: uncomment this.
|
|
public struct DefaultedRandomAccessRangeReplaceableSlice<Element>
|
|
: RangeReplaceableCollection {
|
|
|
|
public typealias Self_ = DefaultedRandomAccessRangeReplaceableSlice<Element>
|
|
public typealias Base = MinimalRangeReplaceableRandomAccessCollection<Element>
|
|
public typealias Iterator = MinimalIterator<Element>
|
|
public typealias Index = MinimalIndex
|
|
|
|
public var base: Base
|
|
public var startIndex: Index
|
|
public var endIndex: Index
|
|
|
|
public init() {
|
|
expectSliceType(Self_.self)
|
|
|
|
self.base = Base()
|
|
self.startIndex = base.startIndex
|
|
self.endIndex = base.endIndex
|
|
}
|
|
|
|
public init(base: Base) {
|
|
self.base = base
|
|
self.startIndex = base.startIndex
|
|
self.endIndex = base.endIndex
|
|
}
|
|
|
|
public init(base: Base, bounds: Range<Index>) {
|
|
self.base = base
|
|
self.startIndex = bounds.lowerBound
|
|
self.endIndex = bounds.upperBound
|
|
}
|
|
|
|
public init(_ array: [Element]) {
|
|
self = DefaultedRandomAccessRangeReplaceableSlice(
|
|
base: Base(elements: array))
|
|
}
|
|
|
|
public init(elements: [Element]) {
|
|
self = DefaultedRandomAccessRangeReplaceableSlice(
|
|
base: Base(elements: elements))
|
|
}
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
return MinimalIterator(Array(self))
|
|
}
|
|
|
|
public subscript(index: Index) -> Element {
|
|
Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
|
|
return base[index]
|
|
}
|
|
|
|
public subscript(bounds: Range<Index>) -> Self_ {
|
|
Index._failEarlyRangeCheck2(
|
|
rangeStart: bounds.lowerBound,
|
|
rangeEnd: bounds.upperBound,
|
|
boundsStart: startIndex,
|
|
boundsEnd: endIndex)
|
|
return DefaultedRandomAccessRangeReplaceableSlice(
|
|
base: base, bounds: bounds)
|
|
}
|
|
|
|
public mutating func replaceSubrange<
|
|
C : Collection
|
|
>(
|
|
_ subRange: Range<Index>,
|
|
with newElements: C
|
|
) where C.Element == Element {
|
|
let startOffset = startIndex.position
|
|
let endOffset =
|
|
endIndex.position
|
|
- subRange.count
|
|
+ numericCast(newElements.count) as Int
|
|
Index._failEarlyRangeCheck2(
|
|
rangeStart: subRange.lowerBound,
|
|
rangeEnd: subRange.upperBound,
|
|
boundsStart: startIndex,
|
|
boundsEnd: endIndex)
|
|
base.replaceSubrange(subRange, with: newElements)
|
|
startIndex = base.startIndex.advanced(by: startOffset)
|
|
endIndex = base.startIndex.advanced(by: endOffset)
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
/// A Collection that uses as many default implementations as
|
|
/// `Collection` can provide.
|
|
public struct DefaultedMutableRandomAccessCollection<Element> : RandomAccessCollection, MutableCollection {
|
|
public typealias Base = MinimalMutableRandomAccessCollection<Element>
|
|
public typealias Iterator = MinimalIterator<Element>
|
|
public typealias Index = MinimalIndex
|
|
|
|
// FIXME: this shouldn't be necessary, should come by default
|
|
public typealias Indices = DefaultIndices<DefaultedMutableRandomAccessCollection<Element>>
|
|
|
|
public var base: Base
|
|
|
|
public init(base: Base) {
|
|
self.base = base
|
|
}
|
|
|
|
public init(_ array: [Element]) {
|
|
self.base = Base(elements: array)
|
|
}
|
|
|
|
public init(elements: [Element]) {
|
|
self.base = Base(elements: elements)
|
|
}
|
|
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == Element {
|
|
self.init(base:
|
|
MinimalMutableRandomAccessCollection(elements: elements, underestimatedCount: underestimatedCount))
|
|
}
|
|
|
|
public var underestimatedCount: Int {
|
|
return base.underestimatedCount
|
|
}
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return base.makeIterator()
|
|
}
|
|
|
|
|
|
public let timesSuccessorCalled = ResettableValue(0)
|
|
|
|
public func index(after i: MinimalIndex) -> MinimalIndex {
|
|
timesSuccessorCalled.value += 1
|
|
return base.index(after: i)
|
|
}
|
|
|
|
public let timesPredecessorCalled = ResettableValue(0)
|
|
|
|
public func index(before i: MinimalIndex) -> MinimalIndex {
|
|
timesPredecessorCalled.value += 1
|
|
return base.index(before: i)
|
|
}
|
|
|
|
public func distance(from start: MinimalIndex, to end: MinimalIndex)
|
|
-> Int {
|
|
return base.distance(from: start, to: end)
|
|
}
|
|
|
|
public func index(_ i: Index, offsetBy n: Int) -> Index {
|
|
return base.index(i, offsetBy: n)
|
|
}
|
|
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return base.startIndex
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return base.endIndex
|
|
}
|
|
|
|
public subscript(i: MinimalIndex) -> Element {
|
|
get {
|
|
return base[i]
|
|
}
|
|
set {
|
|
base[i] = newValue
|
|
}
|
|
}
|
|
|
|
// FIXME: swift-3-indexing-model: use defaults.
|
|
// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
|
|
|
|
public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedMutableRandomAccessCollection<Base.Element>> {
|
|
get {
|
|
// FIXME: swift-3-indexing-model: range check.
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
set {
|
|
_writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
FIXME: swift-3-indexing-model: uncomment this.
|
|
public struct DefaultedRandomAccessRangeReplaceableSlice<Element>
|
|
: RangeReplaceableCollection {
|
|
|
|
public typealias Self_ = DefaultedRandomAccessRangeReplaceableSlice<Element>
|
|
public typealias Base = MinimalMutableRandomAccessCollection<Element>
|
|
public typealias Iterator = MinimalIterator<Element>
|
|
public typealias Index = MinimalIndex
|
|
|
|
public var base: Base
|
|
public var startIndex: Index
|
|
public var endIndex: Index
|
|
|
|
public init() {
|
|
expectSliceType(Self_.self)
|
|
|
|
self.base = Base()
|
|
self.startIndex = base.startIndex
|
|
self.endIndex = base.endIndex
|
|
}
|
|
|
|
public init(base: Base) {
|
|
self.base = base
|
|
self.startIndex = base.startIndex
|
|
self.endIndex = base.endIndex
|
|
}
|
|
|
|
public init(base: Base, bounds: Range<Index>) {
|
|
self.base = base
|
|
self.startIndex = bounds.lowerBound
|
|
self.endIndex = bounds.upperBound
|
|
}
|
|
|
|
public init(_ array: [Element]) {
|
|
self = DefaultedRandomAccessRangeReplaceableSlice(
|
|
base: Base(elements: array))
|
|
}
|
|
|
|
public init(elements: [Element]) {
|
|
self = DefaultedRandomAccessRangeReplaceableSlice(
|
|
base: Base(elements: elements))
|
|
}
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
return MinimalIterator(Array(self))
|
|
}
|
|
|
|
public subscript(index: Index) -> Element {
|
|
Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
|
|
return base[index]
|
|
}
|
|
|
|
public subscript(bounds: Range<Index>) -> Self_ {
|
|
Index._failEarlyRangeCheck2(
|
|
rangeStart: bounds.lowerBound,
|
|
rangeEnd: bounds.upperBound,
|
|
boundsStart: startIndex,
|
|
boundsEnd: endIndex)
|
|
return DefaultedRandomAccessRangeReplaceableSlice(
|
|
base: base, bounds: bounds)
|
|
}
|
|
|
|
public mutating func replaceSubrange<
|
|
C : Collection
|
|
>(
|
|
_ subRange: Range<Index>,
|
|
with newElements: C
|
|
) where C.Element == Element {
|
|
let startOffset = startIndex.position
|
|
let endOffset =
|
|
endIndex.position
|
|
- subRange.count
|
|
+ numericCast(newElements.count) as Int
|
|
Index._failEarlyRangeCheck2(
|
|
rangeStart: subRange.lowerBound,
|
|
rangeEnd: subRange.upperBound,
|
|
boundsStart: startIndex,
|
|
boundsEnd: endIndex)
|
|
base.replaceSubrange(subRange, with: newElements)
|
|
startIndex = base.startIndex.advanced(by: startOffset)
|
|
endIndex = base.startIndex.advanced(by: endOffset)
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
/// A Collection that uses as many default implementations as
|
|
/// `Collection` can provide.
|
|
public struct DefaultedMutableRangeReplaceableRandomAccessCollection<Element> : RandomAccessCollection, MutableCollection, RangeReplaceableCollection {
|
|
public typealias Base = MinimalMutableRangeReplaceableRandomAccessCollection<Element>
|
|
public typealias Iterator = MinimalIterator<Element>
|
|
public typealias Index = MinimalIndex
|
|
|
|
// FIXME: this shouldn't be necessary, should come by default
|
|
public typealias Indices = DefaultIndices<DefaultedMutableRangeReplaceableRandomAccessCollection<Element>>
|
|
|
|
public var base: Base
|
|
|
|
public init(base: Base) {
|
|
self.base = base
|
|
}
|
|
|
|
public init(_ array: [Element]) {
|
|
self.base = Base(elements: array)
|
|
}
|
|
|
|
public init(elements: [Element]) {
|
|
self.base = Base(elements: elements)
|
|
}
|
|
|
|
public init<S : Sequence>(
|
|
elements: S,
|
|
underestimatedCount: UnderestimatedCountBehavior = .value(0)
|
|
) where S.Element == Element {
|
|
self.init(base:
|
|
MinimalMutableRangeReplaceableRandomAccessCollection(elements: elements, underestimatedCount: underestimatedCount))
|
|
}
|
|
|
|
public var underestimatedCount: Int {
|
|
return base.underestimatedCount
|
|
}
|
|
|
|
public let timesMakeIteratorCalled = ResettableValue(0)
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
timesMakeIteratorCalled.value += 1
|
|
return base.makeIterator()
|
|
}
|
|
|
|
|
|
public let timesSuccessorCalled = ResettableValue(0)
|
|
|
|
public func index(after i: MinimalIndex) -> MinimalIndex {
|
|
timesSuccessorCalled.value += 1
|
|
return base.index(after: i)
|
|
}
|
|
|
|
public let timesPredecessorCalled = ResettableValue(0)
|
|
|
|
public func index(before i: MinimalIndex) -> MinimalIndex {
|
|
timesPredecessorCalled.value += 1
|
|
return base.index(before: i)
|
|
}
|
|
|
|
public func distance(from start: MinimalIndex, to end: MinimalIndex)
|
|
-> Int {
|
|
return base.distance(from: start, to: end)
|
|
}
|
|
|
|
public func index(_ i: Index, offsetBy n: Int) -> Index {
|
|
return base.index(i, offsetBy: n)
|
|
}
|
|
|
|
|
|
public let timesStartIndexCalled = ResettableValue(0)
|
|
|
|
public var startIndex: MinimalIndex {
|
|
timesStartIndexCalled.value += 1
|
|
return base.startIndex
|
|
}
|
|
|
|
public let timesEndIndexCalled = ResettableValue(0)
|
|
|
|
public var endIndex: MinimalIndex {
|
|
timesEndIndexCalled.value += 1
|
|
return base.endIndex
|
|
}
|
|
|
|
public subscript(i: MinimalIndex) -> Element {
|
|
get {
|
|
return base[i]
|
|
}
|
|
set {
|
|
base[i] = newValue
|
|
}
|
|
}
|
|
|
|
// FIXME: swift-3-indexing-model: use defaults.
|
|
// if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
|
|
|
|
public subscript(bounds: Range<MinimalIndex>) -> Slice<DefaultedMutableRangeReplaceableRandomAccessCollection<Base.Element>> {
|
|
get {
|
|
// FIXME: swift-3-indexing-model: range check.
|
|
return Slice(base: self, bounds: bounds)
|
|
}
|
|
set {
|
|
_writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
|
|
}
|
|
}
|
|
|
|
public init() {
|
|
base = Base()
|
|
}
|
|
|
|
public mutating func replaceSubrange<C>(
|
|
_ subRange: Range<DefaultedMutableRangeReplaceableRandomAccessCollection<Element>.Index>,
|
|
with newElements: C
|
|
) where C : Collection, C.Element == Element {
|
|
base.replaceSubrange(subRange, with: newElements)
|
|
}
|
|
}
|
|
|
|
/*
|
|
FIXME: swift-3-indexing-model: uncomment this.
|
|
public struct DefaultedRandomAccessRangeReplaceableSlice<Element>
|
|
: RangeReplaceableCollection {
|
|
|
|
public typealias Self_ = DefaultedRandomAccessRangeReplaceableSlice<Element>
|
|
public typealias Base = MinimalMutableRangeReplaceableRandomAccessCollection<Element>
|
|
public typealias Iterator = MinimalIterator<Element>
|
|
public typealias Index = MinimalIndex
|
|
|
|
public var base: Base
|
|
public var startIndex: Index
|
|
public var endIndex: Index
|
|
|
|
public init() {
|
|
expectSliceType(Self_.self)
|
|
|
|
self.base = Base()
|
|
self.startIndex = base.startIndex
|
|
self.endIndex = base.endIndex
|
|
}
|
|
|
|
public init(base: Base) {
|
|
self.base = base
|
|
self.startIndex = base.startIndex
|
|
self.endIndex = base.endIndex
|
|
}
|
|
|
|
public init(base: Base, bounds: Range<Index>) {
|
|
self.base = base
|
|
self.startIndex = bounds.lowerBound
|
|
self.endIndex = bounds.upperBound
|
|
}
|
|
|
|
public init(_ array: [Element]) {
|
|
self = DefaultedRandomAccessRangeReplaceableSlice(
|
|
base: Base(elements: array))
|
|
}
|
|
|
|
public init(elements: [Element]) {
|
|
self = DefaultedRandomAccessRangeReplaceableSlice(
|
|
base: Base(elements: elements))
|
|
}
|
|
|
|
public func makeIterator() -> MinimalIterator<Element> {
|
|
return MinimalIterator(Array(self))
|
|
}
|
|
|
|
public subscript(index: Index) -> Element {
|
|
Index._failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
|
|
return base[index]
|
|
}
|
|
|
|
public subscript(bounds: Range<Index>) -> Self_ {
|
|
Index._failEarlyRangeCheck2(
|
|
rangeStart: bounds.lowerBound,
|
|
rangeEnd: bounds.upperBound,
|
|
boundsStart: startIndex,
|
|
boundsEnd: endIndex)
|
|
return DefaultedRandomAccessRangeReplaceableSlice(
|
|
base: base, bounds: bounds)
|
|
}
|
|
|
|
public mutating func replaceSubrange<
|
|
C : Collection
|
|
>(
|
|
_ subRange: Range<Index>,
|
|
with newElements: C
|
|
) where C.Element == Element {
|
|
let startOffset = startIndex.position
|
|
let endOffset =
|
|
endIndex.position
|
|
- subRange.count
|
|
+ numericCast(newElements.count) as Int
|
|
Index._failEarlyRangeCheck2(
|
|
rangeStart: subRange.lowerBound,
|
|
rangeEnd: subRange.upperBound,
|
|
boundsStart: startIndex,
|
|
boundsEnd: endIndex)
|
|
base.replaceSubrange(subRange, with: newElements)
|
|
startIndex = base.startIndex.advanced(by: startOffset)
|
|
endIndex = base.startIndex.advanced(by: endOffset)
|
|
}
|
|
}
|
|
*/
|