mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
* spelling: against Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: algorithmic Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: alignment Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: anything Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: architectural Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: architecture Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: are Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: artificial Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: aside Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: available Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: being Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: bidirectional Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: characters Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: circular Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: compatibility Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: compiled Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: correctly Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: covers Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: declaration Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: dependencies Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: descriptor Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: dictionaries Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: dynamic Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: greater Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: hierarchy Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: immortal Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: initialize Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: initializes Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: iterable Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: message Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: minimum Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: multiple Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: originally Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: simplified Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: sophisticated Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: trivia Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: wasn't Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> Co-authored-by: Josh Soref <jsoref@users.noreply.github.com>
675 lines
22 KiB
Swift
675 lines
22 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
|
|
|
|
public protocol Wrapper {
|
|
associatedtype Base
|
|
init(wrapping base: Base)
|
|
var base: Base { get set }
|
|
}
|
|
|
|
public protocol LoggingType: Wrapper {
|
|
associatedtype Log : AnyObject
|
|
}
|
|
|
|
extension LoggingType {
|
|
public var log: Log.Type {
|
|
return Log.self
|
|
}
|
|
|
|
public var selfType: Any.Type {
|
|
return type(of: self)
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Iterator
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
public class IteratorLog {
|
|
public static func dispatchTester<I>(
|
|
_ iterator: I
|
|
) -> LoggingIterator<LoggingIterator<I>> {
|
|
return LoggingIterator(wrapping: LoggingIterator(wrapping: iterator))
|
|
}
|
|
public static var next = TypeIndexed(0)
|
|
}
|
|
|
|
public struct LoggingIterator<Base : IteratorProtocol> {
|
|
public var base: Base
|
|
}
|
|
|
|
extension LoggingIterator: LoggingType {
|
|
public typealias Log = IteratorLog
|
|
|
|
public init(wrapping base: Base) {
|
|
self.base = base
|
|
}
|
|
}
|
|
|
|
extension LoggingIterator: IteratorProtocol {
|
|
public mutating func next() -> Base.Element? {
|
|
Log.next[selfType] += 1
|
|
return base.next()
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Sequence and Collection logs
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// FIXME: it's not clear if it's really worth this hierarchy. the
|
|
// test.log pattern requires all the static properties be at the top
|
|
// since Log is an associated type that cannot be refined in extensions
|
|
// that add functionality.
|
|
|
|
public class SequenceLogBase {
|
|
// Sequence
|
|
public static var makeIterator = TypeIndexed(0)
|
|
public static var underestimatedCount = TypeIndexed(0)
|
|
public static var dropFirst = TypeIndexed(0)
|
|
public static var dropLast = TypeIndexed(0)
|
|
public static var dropWhile = TypeIndexed(0)
|
|
public static var prefixWhile = TypeIndexed(0)
|
|
public static var prefixMaxLength = TypeIndexed(0)
|
|
public static var suffixMaxLength = TypeIndexed(0)
|
|
public static var withContiguousStorageIfAvailable = TypeIndexed(0)
|
|
public static var _customContainsEquatableElement = TypeIndexed(0)
|
|
public static var _copyToContiguousArray = TypeIndexed(0)
|
|
public static var _copyContents = TypeIndexed(0)
|
|
// Collection
|
|
public static var startIndex = TypeIndexed(0)
|
|
public static var endIndex = TypeIndexed(0)
|
|
public static var subscriptIndex = TypeIndexed(0)
|
|
public static var subscriptRange = TypeIndexed(0)
|
|
public static var _failEarlyRangeCheckIndex = TypeIndexed(0)
|
|
public static var _failEarlyRangeCheckRange = TypeIndexed(0)
|
|
public static var successor = TypeIndexed(0)
|
|
public static var formSuccessor = TypeIndexed(0)
|
|
public static var indices = TypeIndexed(0)
|
|
public static var isEmpty = TypeIndexed(0)
|
|
public static var count = TypeIndexed(0)
|
|
public static var _customIndexOfEquatableElement = TypeIndexed(0)
|
|
public static var advance = TypeIndexed(0)
|
|
public static var advanceLimit = TypeIndexed(0)
|
|
public static var distance = TypeIndexed(0)
|
|
// BidirectionalCollection
|
|
public static var predecessor = TypeIndexed(0)
|
|
public static var formPredecessor = TypeIndexed(0)
|
|
// MutableCollection
|
|
public static var subscriptIndexSet = TypeIndexed(0)
|
|
public static var subscriptRangeSet = TypeIndexed(0)
|
|
public static var partitionBy = TypeIndexed(0)
|
|
public static var _withUnsafeMutableBufferPointerIfSupported = TypeIndexed(0)
|
|
public static var _withUnsafeMutableBufferPointerIfSupportedNonNilReturns =
|
|
TypeIndexed(0)
|
|
public static var withContiguousMutableStorageIfAvailable = TypeIndexed(0)
|
|
public static var withContiguousMutableStorageIfAvailableNonNilReturns =
|
|
TypeIndexed(0)
|
|
// RangeReplaceableCollection
|
|
public static var init_ = TypeIndexed(0)
|
|
public static var initRepeating = TypeIndexed(0)
|
|
public static var initWithSequence = TypeIndexed(0)
|
|
public static var _customRemoveLast = TypeIndexed(0)
|
|
public static var _customRemoveLastN = TypeIndexed(0)
|
|
public static var append = TypeIndexed(0)
|
|
public static var appendContentsOf = TypeIndexed(0)
|
|
public static var insert = TypeIndexed(0)
|
|
public static var insertContentsOf = TypeIndexed(0)
|
|
public static var removeAll = TypeIndexed(0)
|
|
public static var removeAt = TypeIndexed(0)
|
|
public static var removeFirst = TypeIndexed(0)
|
|
public static var removeFirstN = TypeIndexed(0)
|
|
public static var removeSubrange = TypeIndexed(0)
|
|
public static var replaceSubrange = TypeIndexed(0)
|
|
public static var reserveCapacity = TypeIndexed(0)
|
|
}
|
|
|
|
public class SequenceLog : SequenceLogBase {
|
|
public static func dispatchTester<S>(
|
|
_ s: S
|
|
) -> LoggingSequence<LoggingSequence<S>> {
|
|
return LoggingSequence(wrapping: LoggingSequence(wrapping: s))
|
|
}
|
|
}
|
|
|
|
public class CollectionLog : SequenceLogBase {
|
|
public static func dispatchTester<C>(
|
|
_ c: C
|
|
) -> LoggingCollection<LoggingCollection<C>> {
|
|
return LoggingCollection(wrapping: LoggingCollection(wrapping: c))
|
|
}
|
|
}
|
|
|
|
public class BidirectionalCollectionLog : SequenceLogBase {
|
|
public static func dispatchTester<C>(
|
|
_ c: C
|
|
) -> LoggingBidirectionalCollection<LoggingBidirectionalCollection<C>> {
|
|
return LoggingBidirectionalCollection(
|
|
wrapping: LoggingBidirectionalCollection(wrapping: c))
|
|
}
|
|
}
|
|
|
|
public class MutableCollectionLog : SequenceLogBase {
|
|
public static func dispatchTester<C>(
|
|
_ c: C
|
|
) -> LoggingMutableCollection<LoggingMutableCollection<C>> {
|
|
return LoggingMutableCollection(
|
|
wrapping: LoggingMutableCollection(wrapping: c))
|
|
}
|
|
}
|
|
|
|
/// Data container to keep track of how many times each `Base` type calls methods
|
|
/// of `RangeReplaceableCollection`.
|
|
///
|
|
/// Each static variable is a mapping of Type -> Number of calls.
|
|
public class RangeReplaceableCollectionLog : SequenceLogBase {
|
|
public static func dispatchTester<C>(
|
|
_ rrc: C
|
|
) -> LoggingRangeReplaceableCollection<LoggingRangeReplaceableCollection<C>> {
|
|
return LoggingRangeReplaceableCollection(
|
|
wrapping: LoggingRangeReplaceableCollection(wrapping: rrc)
|
|
)
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Sequence and Collection that count method calls
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// Interposes between `Sequence` method calls to increment each method's
|
|
/// counter.
|
|
public struct LoggingSequence<Base : Sequence> {
|
|
public var base: Base
|
|
}
|
|
|
|
extension LoggingSequence: LoggingType {
|
|
// I know, I know. It doesn't matter though. The benefit of the whole logging
|
|
// class hierarchy is unclear...
|
|
public typealias Log = SequenceLog
|
|
|
|
public init(wrapping base: Base) {
|
|
self.base = base
|
|
}
|
|
}
|
|
|
|
extension LoggingSequence: Sequence {
|
|
public typealias Element = Base.Element
|
|
public typealias Iterator = LoggingIterator<Base.Iterator>
|
|
|
|
public func makeIterator() -> Iterator {
|
|
SequenceLog.makeIterator[selfType] += 1
|
|
return LoggingIterator(wrapping: base.makeIterator())
|
|
}
|
|
|
|
public var underestimatedCount: Int {
|
|
SequenceLog.underestimatedCount[selfType] += 1
|
|
return base.underestimatedCount
|
|
}
|
|
|
|
public func withContiguousStorageIfAvailable<R>(
|
|
_ body: (UnsafeBufferPointer<Element>) throws -> R
|
|
) rethrows -> R? {
|
|
SequenceLog.withContiguousStorageIfAvailable[selfType] += 1
|
|
return try base.withContiguousStorageIfAvailable(body)
|
|
}
|
|
|
|
public func _customContainsEquatableElement(_ element: Element) -> Bool? {
|
|
SequenceLog._customContainsEquatableElement[selfType] += 1
|
|
return base._customContainsEquatableElement(element)
|
|
}
|
|
|
|
/// Create a native array buffer containing the elements of `self`,
|
|
/// in the same order.
|
|
public func _copyToContiguousArray() -> ContiguousArray<Element> {
|
|
SequenceLog._copyToContiguousArray[selfType] += 1
|
|
return base._copyToContiguousArray()
|
|
}
|
|
|
|
/// Copy a Sequence into an array.
|
|
public func _copyContents(
|
|
initializing buffer: UnsafeMutableBufferPointer<Element>
|
|
) -> (Iterator,UnsafeMutableBufferPointer<Element>.Index) {
|
|
SequenceLog._copyContents[selfType] += 1
|
|
let (it,idx) = base._copyContents(initializing: buffer)
|
|
return (Iterator(wrapping: it),idx)
|
|
}
|
|
}
|
|
|
|
public typealias LoggingCollection<Base: Collection> = LoggingSequence<Base>
|
|
|
|
extension LoggingCollection: Collection {
|
|
public typealias Index = Base.Index
|
|
public typealias Indices = Base.Indices
|
|
public typealias SubSequence = Base.SubSequence
|
|
|
|
public var startIndex: Index {
|
|
CollectionLog.startIndex[selfType] += 1
|
|
return base.startIndex
|
|
}
|
|
|
|
public var endIndex: Index {
|
|
CollectionLog.endIndex[selfType] += 1
|
|
return base.endIndex
|
|
}
|
|
|
|
public subscript(position: Index) -> Element {
|
|
CollectionLog.subscriptIndex[selfType] += 1
|
|
return base[position]
|
|
}
|
|
|
|
public subscript(bounds: Range<Index>) -> SubSequence {
|
|
CollectionLog.subscriptRange[selfType] += 1
|
|
return base[bounds]
|
|
}
|
|
|
|
public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
|
|
CollectionLog._failEarlyRangeCheckIndex[selfType] += 1
|
|
base._failEarlyRangeCheck(index, bounds: bounds)
|
|
}
|
|
|
|
public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
|
|
CollectionLog._failEarlyRangeCheckRange[selfType] += 1
|
|
base._failEarlyRangeCheck(range, bounds: bounds)
|
|
}
|
|
|
|
public func index(after i: Index) -> Index {
|
|
CollectionLog.successor[selfType] += 1
|
|
return base.index(after: i)
|
|
}
|
|
|
|
public func formIndex(after i: inout Index) {
|
|
CollectionLog.formSuccessor[selfType] += 1
|
|
base.formIndex(after: &i)
|
|
}
|
|
|
|
public var indices: Indices {
|
|
CollectionLog.indices[selfType] += 1
|
|
return base.indices
|
|
}
|
|
|
|
public var isEmpty: Bool {
|
|
CollectionLog.isEmpty[selfType] += 1
|
|
return base.isEmpty
|
|
}
|
|
|
|
public var count: Int {
|
|
CollectionLog.count[selfType] += 1
|
|
return base.count
|
|
}
|
|
|
|
public func _customIndexOfEquatableElement(
|
|
_ element: Element
|
|
) -> Index?? {
|
|
CollectionLog._customIndexOfEquatableElement[selfType] += 1
|
|
return base._customIndexOfEquatableElement(element)
|
|
}
|
|
|
|
public func index(_ i: Index, offsetBy n: Int) -> Index {
|
|
CollectionLog.advance[selfType] += 1
|
|
return base.index(i, offsetBy: n)
|
|
}
|
|
|
|
public func index(
|
|
_ i: Index, offsetBy n: Int, limitedBy limit: Index
|
|
) -> Index? {
|
|
CollectionLog.advanceLimit[selfType] += 1
|
|
return base.index(i, offsetBy: n, limitedBy: limit)
|
|
}
|
|
|
|
public func distance(from start: Index, to end: Index) -> Int {
|
|
CollectionLog.distance[selfType] += 1
|
|
return base.distance(from: start, to: end)
|
|
}
|
|
}
|
|
|
|
public typealias LoggingBidirectionalCollection<
|
|
Base: BidirectionalCollection
|
|
> = LoggingCollection<Base>
|
|
|
|
extension LoggingBidirectionalCollection: BidirectionalCollection {
|
|
public func index(before i: Index) -> Index {
|
|
BidirectionalCollectionLog.predecessor[selfType] += 1
|
|
return base.index(before: i)
|
|
}
|
|
|
|
public func formIndex(before i: inout Index) {
|
|
BidirectionalCollectionLog.formPredecessor[selfType] += 1
|
|
base.formIndex(before: &i)
|
|
}
|
|
}
|
|
|
|
public typealias LoggingRandomAccessCollection<Base: RandomAccessCollection>
|
|
= LoggingBidirectionalCollection<Base>
|
|
|
|
extension LoggingRandomAccessCollection: RandomAccessCollection { }
|
|
|
|
public typealias LoggingMutableCollection<Base: MutableCollection>
|
|
= LoggingCollection<Base>
|
|
|
|
extension LoggingMutableCollection: MutableCollection {
|
|
public subscript(position: Index) -> Element {
|
|
get {
|
|
MutableCollectionLog.subscriptIndex[selfType] += 1
|
|
return base[position]
|
|
}
|
|
set {
|
|
MutableCollectionLog.subscriptIndexSet[selfType] += 1
|
|
base[position] = newValue
|
|
}
|
|
}
|
|
|
|
public subscript(bounds: Range<Index>) -> SubSequence {
|
|
get {
|
|
MutableCollectionLog.subscriptRange[selfType] += 1
|
|
return base[bounds]
|
|
}
|
|
set {
|
|
MutableCollectionLog.subscriptRangeSet[selfType] += 1
|
|
base[bounds] = newValue
|
|
}
|
|
}
|
|
|
|
public mutating func partition(
|
|
by belongsInSecondPartition: (Iterator.Element) throws -> Bool
|
|
) rethrows -> Index {
|
|
Log.partitionBy[selfType] += 1
|
|
return try base.partition(by: belongsInSecondPartition)
|
|
}
|
|
|
|
@available(*, deprecated, renamed: "withContiguousMutableStorageIfAvailable")
|
|
public mutating func _withUnsafeMutableBufferPointerIfSupported<R>(
|
|
_ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R
|
|
) rethrows -> R? {
|
|
MutableCollectionLog._withUnsafeMutableBufferPointerIfSupported[selfType] += 1
|
|
let result = try base._withUnsafeMutableBufferPointerIfSupported(body)
|
|
if result != nil {
|
|
Log._withUnsafeMutableBufferPointerIfSupportedNonNilReturns[selfType] += 1
|
|
}
|
|
return result
|
|
}
|
|
|
|
public mutating func withContiguousMutableStorageIfAvailable<R>(
|
|
_ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R
|
|
) rethrows -> R? {
|
|
MutableCollectionLog.withContiguousMutableStorageIfAvailable[selfType] += 1
|
|
let result = try base.withContiguousMutableStorageIfAvailable(body)
|
|
if result != nil {
|
|
Log.withContiguousMutableStorageIfAvailableNonNilReturns[selfType] += 1
|
|
}
|
|
return result
|
|
}
|
|
|
|
}
|
|
|
|
public typealias LoggingMutableBidirectionalCollection<
|
|
Base: MutableCollection & BidirectionalCollection
|
|
> = LoggingMutableCollection<Base>
|
|
|
|
public typealias LoggingMutableRandomAccessCollection<
|
|
Base: MutableCollection & RandomAccessCollection
|
|
> = LoggingMutableCollection<Base>
|
|
|
|
public typealias LoggingRangeReplaceableCollection<
|
|
Base: RangeReplaceableCollection
|
|
> = LoggingCollection<Base>
|
|
|
|
extension LoggingRangeReplaceableCollection: RangeReplaceableCollection {
|
|
public init() {
|
|
self.base = Base()
|
|
RangeReplaceableCollectionLog.init_[selfType] += 1
|
|
}
|
|
|
|
public init(repeating repeatedValue: Element, count: Int) {
|
|
self.base = Base(repeating: repeatedValue, count: count)
|
|
RangeReplaceableCollectionLog.initRepeating[selfType] += 1
|
|
}
|
|
|
|
public init<S : Sequence>(_ elements: S)
|
|
where S.Element == Element {
|
|
self.base = Base(elements)
|
|
RangeReplaceableCollectionLog.initWithSequence[selfType] += 1
|
|
}
|
|
|
|
public mutating func _customRemoveLast() -> Element? {
|
|
RangeReplaceableCollectionLog._customRemoveLast[selfType] += 1
|
|
return base._customRemoveLast()
|
|
}
|
|
|
|
public mutating func _customRemoveLast(_ n: Int) -> Bool {
|
|
RangeReplaceableCollectionLog._customRemoveLastN[selfType] += 1
|
|
return base._customRemoveLast(n)
|
|
}
|
|
|
|
public mutating func append(_ newElement: Element) {
|
|
RangeReplaceableCollectionLog.append[selfType] += 1
|
|
base.append(newElement)
|
|
}
|
|
|
|
public mutating func append<S : Sequence>(
|
|
contentsOf newElements: S
|
|
) where S.Element == Element {
|
|
RangeReplaceableCollectionLog.appendContentsOf[selfType] += 1
|
|
base.append(contentsOf: newElements)
|
|
}
|
|
|
|
public mutating func insert(
|
|
_ newElement: Element, at i: Index
|
|
) {
|
|
RangeReplaceableCollectionLog.insert[selfType] += 1
|
|
base.insert(newElement, at: i)
|
|
}
|
|
|
|
public mutating func insert<C : Collection>(
|
|
contentsOf newElements: C, at i: Index
|
|
) where C.Element == Element {
|
|
RangeReplaceableCollectionLog.insertContentsOf[selfType] += 1
|
|
base.insert(contentsOf: newElements, at: i)
|
|
}
|
|
|
|
public mutating func removeAll(keepingCapacity keepCapacity: Bool) {
|
|
RangeReplaceableCollectionLog.removeAll[selfType] += 1
|
|
base.removeAll(keepingCapacity: keepCapacity)
|
|
}
|
|
|
|
@discardableResult
|
|
public mutating func remove(at index: Index) -> Element {
|
|
RangeReplaceableCollectionLog.removeAt[selfType] += 1
|
|
return base.remove(at: index)
|
|
}
|
|
|
|
@discardableResult
|
|
public mutating func removeFirst() -> Element {
|
|
RangeReplaceableCollectionLog.removeFirst[selfType] += 1
|
|
return base.removeFirst()
|
|
}
|
|
|
|
public mutating func removeFirst(_ n: Int) {
|
|
RangeReplaceableCollectionLog.removeFirstN[selfType] += 1
|
|
base.removeFirst(n)
|
|
}
|
|
|
|
public mutating func removeSubrange(_ bounds: Range<Index>) {
|
|
RangeReplaceableCollectionLog.removeSubrange[selfType] += 1
|
|
base.removeSubrange(bounds)
|
|
}
|
|
|
|
public mutating func replaceSubrange<C : Collection>(
|
|
_ bounds: Range<Index>, with newElements: C
|
|
) where C.Element == Element {
|
|
RangeReplaceableCollectionLog.replaceSubrange[selfType] += 1
|
|
base.replaceSubrange(bounds, with: newElements)
|
|
}
|
|
|
|
public mutating func reserveCapacity(_ n: Int) {
|
|
RangeReplaceableCollectionLog.reserveCapacity[selfType] += 1
|
|
base.reserveCapacity(n)
|
|
}
|
|
}
|
|
|
|
public typealias LoggingRangeReplaceableBidirectionalCollection<
|
|
Base: BidirectionalCollection & RangeReplaceableCollection
|
|
> = LoggingRangeReplaceableCollection<Base>
|
|
|
|
public typealias LoggingRangeReplaceableRandomAccessCollection<
|
|
Base: RandomAccessCollection & RangeReplaceableCollection
|
|
> = LoggingRangeReplaceableCollection<Base>
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Collections that count calls to `withContiguousMutableStorageIfAvailable`
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// Interposes between `withContiguousMutableStorageIfAvailable` method calls
|
|
/// to increment a counter. Calls to this method from within dispatched methods
|
|
/// are uncounted by the standard logging collection wrapper.
|
|
public struct BufferAccessLoggingMutableCollection<
|
|
Base : MutableCollection
|
|
> {
|
|
public var base: Base
|
|
}
|
|
|
|
extension BufferAccessLoggingMutableCollection: LoggingType {
|
|
public typealias Log = MutableCollectionLog
|
|
|
|
public init(wrapping base: Base) {
|
|
self.base = base
|
|
}
|
|
}
|
|
|
|
extension BufferAccessLoggingMutableCollection: Sequence {
|
|
public typealias SubSequence = Base.SubSequence
|
|
public typealias Iterator = Base.Iterator
|
|
public typealias Element = Base.Element
|
|
|
|
public func makeIterator() -> Iterator {
|
|
return base.makeIterator()
|
|
}
|
|
}
|
|
|
|
extension BufferAccessLoggingMutableCollection: MutableCollection {
|
|
public typealias Index = Base.Index
|
|
public typealias Indices = Base.Indices
|
|
|
|
public var startIndex: Index {
|
|
return base.startIndex
|
|
}
|
|
|
|
public var endIndex: Index {
|
|
return base.endIndex
|
|
}
|
|
|
|
public var indices: Indices {
|
|
return base.indices
|
|
}
|
|
|
|
public subscript(position: Index) -> Element {
|
|
get {
|
|
return base[position]
|
|
}
|
|
set {
|
|
base[position] = newValue
|
|
}
|
|
}
|
|
|
|
public subscript(bounds: Range<Index>) -> SubSequence {
|
|
get {
|
|
return base[bounds]
|
|
}
|
|
set {
|
|
base[bounds] = newValue
|
|
}
|
|
}
|
|
|
|
public func index(after i: Index) -> Index {
|
|
return base.index(after: i)
|
|
}
|
|
|
|
public func index(_ i: Index, offsetBy n: Int) -> Index {
|
|
return base.index(i, offsetBy: n)
|
|
}
|
|
|
|
public func distance(from start: Index, to end: Index) -> Int {
|
|
return base.distance(from: start, to: end)
|
|
}
|
|
|
|
@available(*, deprecated, renamed: "withContiguousMutableStorageIfAvailable")
|
|
public mutating func _withUnsafeMutableBufferPointerIfSupported<R>(
|
|
_ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R
|
|
) rethrows -> R? {
|
|
Log._withUnsafeMutableBufferPointerIfSupported[selfType] += 1
|
|
let result = try base._withUnsafeMutableBufferPointerIfSupported(body)
|
|
if result != nil {
|
|
Log._withUnsafeMutableBufferPointerIfSupportedNonNilReturns[selfType] += 1
|
|
}
|
|
return result
|
|
}
|
|
|
|
public mutating func withContiguousMutableStorageIfAvailable<R>(
|
|
_ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R
|
|
) rethrows -> R? {
|
|
Log.withContiguousMutableStorageIfAvailable[selfType] += 1
|
|
let result = try base.withContiguousMutableStorageIfAvailable(body)
|
|
if result != nil {
|
|
Log.withContiguousMutableStorageIfAvailableNonNilReturns[selfType] += 1
|
|
}
|
|
return result
|
|
}
|
|
}
|
|
|
|
public typealias BufferAccessLoggingMutableBidirectionalCollection<
|
|
Base: MutableCollection & BidirectionalCollection
|
|
> = BufferAccessLoggingMutableCollection<Base>
|
|
|
|
extension BufferAccessLoggingMutableBidirectionalCollection: BidirectionalCollection {
|
|
public func index(before i: Index) -> Index {
|
|
return base.index(before: i)
|
|
}
|
|
}
|
|
|
|
public typealias BufferAccessLoggingMutableRandomAccessCollection<
|
|
Base: MutableCollection & RandomAccessCollection
|
|
> = BufferAccessLoggingMutableCollection<Base>
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Custom assertions
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
public func expectCustomizable<T : LoggingType>(
|
|
_: T, _ counters: TypeIndexed<Int>,
|
|
_ message: @autoclosure () -> String = "",
|
|
stackTrace: SourceLocStack = SourceLocStack(),
|
|
showFrame: Bool = true,
|
|
file: String = #file, line: UInt = #line
|
|
) where
|
|
T.Base : LoggingType,
|
|
T.Log == T.Base.Log {
|
|
let newTrace = stackTrace.pushIf(showFrame, file: file, line: line)
|
|
expectNotEqual(0, counters[T.self], message(), stackTrace: newTrace)
|
|
expectEqual(
|
|
counters[T.self], counters[T.Base.self], message(), stackTrace: newTrace)
|
|
}
|
|
|
|
public func expectNotCustomizable<T : LoggingType>(
|
|
_: T, _ counters: TypeIndexed<Int>,
|
|
_ message: @autoclosure () -> String = "",
|
|
stackTrace: SourceLocStack = SourceLocStack(),
|
|
showFrame: Bool = true,
|
|
file: String = #file, line: UInt = #line
|
|
) where
|
|
T.Base : LoggingType,
|
|
T.Log == T.Base.Log {
|
|
let newTrace = stackTrace.pushIf(showFrame, file: file, line: line)
|
|
expectNotEqual(0, counters[T.self], message(), stackTrace: newTrace)
|
|
expectEqual(0, counters[T.Base.self], message(), stackTrace: newTrace)
|
|
}
|