@@ -1615,6 +1615,167 @@ public struct MinimalBidirectionalCollection<T> : BidirectionalCollection {
16151615 internal let _collectionState : _CollectionState
16161616}
16171617
1618+ /// A minimal implementation of `Collection` with extra checks.
1619+ public struct MinimalBidirectionalRandomAccessCollection < T> : BidirectionalCollection , RandomAccessCollection {
1620+ /// Creates a collection with given contents, but a unique modification
1621+ /// history. No other instance has the same modification history.
1622+ public init < S : Sequence > (
1623+ elements: S ,
1624+ underestimatedCount: UnderestimatedCountBehavior = . value( 0 )
1625+ ) where S. Element == T {
1626+ self . _elements = Array ( elements)
1627+
1628+ self . _collectionState = _CollectionState (
1629+ newRootStateForElementCount: self . _elements. count)
1630+
1631+ switch underestimatedCount {
1632+ case . precise:
1633+ self . underestimatedCount = _elements. count
1634+
1635+ case . half:
1636+ self . underestimatedCount = _elements. count / 2
1637+
1638+ case . overestimate:
1639+ self . underestimatedCount = _elements. count * 3 + 5
1640+
1641+ case . value( let count) :
1642+ self . underestimatedCount = count
1643+ }
1644+ }
1645+
1646+
1647+ public let timesMakeIteratorCalled = ResettableValue ( 0 )
1648+
1649+ public func makeIterator( ) -> MinimalIterator < T > {
1650+ timesMakeIteratorCalled. value += 1
1651+ return MinimalIterator ( _elements)
1652+ }
1653+
1654+ public typealias Index = MinimalIndex
1655+
1656+ internal func _index( forPosition i: Int ) -> MinimalIndex {
1657+ return MinimalIndex (
1658+ collectionState: _collectionState,
1659+ position: i,
1660+ startIndex: _elements. startIndex,
1661+ endIndex: _elements. endIndex)
1662+ }
1663+
1664+ internal func _uncheckedIndex( forPosition i: Int ) -> MinimalIndex {
1665+ return MinimalIndex (
1666+ _collectionState: _collectionState,
1667+ uncheckedPosition: i)
1668+ }
1669+
1670+ public let timesStartIndexCalled = ResettableValue ( 0 )
1671+
1672+ public var startIndex : MinimalIndex {
1673+ timesStartIndexCalled. value += 1
1674+ return _uncheckedIndex ( forPosition: _elements. startIndex)
1675+ }
1676+
1677+ public let timesEndIndexCalled = ResettableValue ( 0 )
1678+
1679+ public var endIndex : MinimalIndex {
1680+ timesEndIndexCalled. value += 1
1681+ return _uncheckedIndex ( forPosition: _elements. endIndex)
1682+ }
1683+
1684+
1685+ public func _failEarlyRangeCheck(
1686+ _ index: MinimalIndex ,
1687+ bounds: Range < MinimalIndex >
1688+ ) {
1689+ _expectCompatibleIndices (
1690+ _uncheckedIndex ( forPosition: index. position) ,
1691+ index)
1692+
1693+ _expectCompatibleIndices (
1694+ _uncheckedIndex ( forPosition: bounds. lowerBound. position) ,
1695+ bounds. lowerBound)
1696+ _expectCompatibleIndices (
1697+ _uncheckedIndex ( forPosition: bounds. upperBound. position) ,
1698+ bounds. upperBound)
1699+
1700+ expectTrapping (
1701+ index. position,
1702+ in: bounds. lowerBound. position..< bounds. upperBound. position)
1703+ }
1704+
1705+ public func _failEarlyRangeCheck(
1706+ _ range: Range < MinimalIndex > ,
1707+ bounds: Range < MinimalIndex >
1708+ ) {
1709+ _expectCompatibleIndices (
1710+ _uncheckedIndex ( forPosition: range. lowerBound. position) ,
1711+ range. lowerBound)
1712+ _expectCompatibleIndices (
1713+ _uncheckedIndex ( forPosition: range. upperBound. position) ,
1714+ range. upperBound)
1715+
1716+ _expectCompatibleIndices (
1717+ _uncheckedIndex ( forPosition: bounds. lowerBound. position) ,
1718+ bounds. lowerBound)
1719+ _expectCompatibleIndices (
1720+ _uncheckedIndex ( forPosition: bounds. upperBound. position) ,
1721+ bounds. upperBound)
1722+
1723+ expectTrapping (
1724+ range. lowerBound. position..< range. upperBound. position,
1725+ in: bounds. lowerBound. position..< bounds. upperBound. position)
1726+ }
1727+
1728+ public func index( after i: MinimalIndex ) -> MinimalIndex {
1729+ _failEarlyRangeCheck ( i, bounds: startIndex..< endIndex)
1730+ return _uncheckedIndex ( forPosition: i. position + 1 )
1731+ }
1732+
1733+ public func index( before i: MinimalIndex ) -> MinimalIndex {
1734+ // FIXME: swift-3-indexing-model: perform a range check and use
1735+ // return _uncheckedIndex(forPosition: i.position - 1)
1736+ return _index ( forPosition: i. position - 1 )
1737+ }
1738+
1739+ public func distance( from start: MinimalIndex , to end: MinimalIndex )
1740+ -> Int {
1741+ // FIXME: swift-3-indexing-model: perform a range check properly.
1742+ if start != endIndex {
1743+ _failEarlyRangeCheck ( start, bounds: startIndex..< endIndex)
1744+ }
1745+ if end != endIndex {
1746+ _failEarlyRangeCheck ( end, bounds: startIndex..< endIndex)
1747+ }
1748+ return end. position - start. position
1749+ }
1750+
1751+ public func index( _ i: Index , offsetBy n: Int ) -> Index {
1752+ // FIXME: swift-3-indexing-model: perform a range check properly.
1753+ if i != endIndex {
1754+ _failEarlyRangeCheck ( i, bounds: startIndex..< endIndex)
1755+ }
1756+ return _index ( forPosition: i. position + n)
1757+ }
1758+
1759+ public subscript( i: MinimalIndex ) -> T {
1760+ get {
1761+ _failEarlyRangeCheck ( i, bounds: startIndex..< endIndex)
1762+ return _elements [ i. position]
1763+ }
1764+ }
1765+
1766+ public subscript( bounds: Range < MinimalIndex > ) -> Slice < MinimalBidirectionalRandomAccessCollection < T > > {
1767+ get {
1768+ _failEarlyRangeCheck ( bounds, bounds: startIndex..< endIndex)
1769+ return Slice ( base: self , bounds: bounds)
1770+ }
1771+ }
1772+
1773+
1774+ public var underestimatedCount : Int
1775+
1776+ internal var _elements : [ T ]
1777+ internal let _collectionState : _CollectionState
1778+ }
16181779
16191780/// A minimal implementation of `Collection` with extra checks.
16201781public struct MinimalRangeReplaceableBidirectionalCollection < T> : BidirectionalCollection , RangeReplaceableCollection {
0 commit comments