blob: 2192608d7edf2f57a2b863ae89ef926f23607ebf [file] [log] [blame]
//===--- CollectionOfOne.swift - A Collection with one element ------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
/// A collection containing a single element.
///
/// You can use a `CollectionOfOne` instance when you need to efficiently
/// represent a single value as a collection. For example, you can add a
/// single element to an array by using a `CollectionOfOne` instance with the
/// concatenation operator (`+`):
///
/// let a = [1, 2, 3, 4]
/// let toAdd = 100
/// let b = a + CollectionOfOne(toAdd)
/// // b == [1, 2, 3, 4, 100]
@_fixed_layout // trivial-implementation
public struct CollectionOfOne<Element> {
@usableFromInline // trivial-implementation
internal var _element: Element
/// Creates an instance containing just the given element.
///
/// - Parameter element: The element to store in the collection.
@inlinable // trivial-implementation
public init(_ element: Element) {
self._element = element
}
}
extension CollectionOfOne {
/// An iterator that produces one or zero instances of an element.
///
/// `IteratorOverOne` is the iterator for the `CollectionOfOne` type.
@_fixed_layout // trivial-implementation
public struct Iterator {
@usableFromInline // trivial-implementation
internal var _elements: Element?
/// Construct an instance that generates `_element!`, or an empty
/// sequence if `_element == nil`.
@inlinable // trivial-implementation
public // @testable
init(_elements: Element?) {
self._elements = _elements
}
}
}
extension CollectionOfOne.Iterator: IteratorProtocol {
/// Advances to the next element and returns it, or `nil` if no next element
/// exists.
///
/// Once `nil` has been returned, all subsequent calls return `nil`.
///
/// - Returns: The next element in the underlying sequence, if a next element
/// exists; otherwise, `nil`.
@inlinable // trivial-implementation
public mutating func next() -> Element? {
let result = _elements
_elements = nil
return result
}
}
extension CollectionOfOne: RandomAccessCollection, MutableCollection {
public typealias Index = Int
public typealias Indices = Range<Int>
public typealias SubSequence = Slice<CollectionOfOne<Element>>
/// The position of the first element.
///
/// In a `CollectionOfOne` instance, `startIndex` is always `0`.
@inlinable // trivial-implementation
public var startIndex: Index {
return 0
}
/// The "past the end" position---that is, the position one greater than the
/// last valid subscript argument.
///
/// In a `CollectionOfOne` instance, `endIndex` is always `1`.
@inlinable // trivial-implementation
public var endIndex: Index {
return 1
}
/// Returns the position immediately after the given index.
///
/// - Parameter i: A valid index of the collection. `i` must be `0`.
/// - Returns: The index value immediately after `i`.
@inlinable // trivial-implementation
public func index(after i: Index) -> Index {
_precondition(i == startIndex)
return 1
}
/// Returns the position immediately before the given index.
///
/// - Parameter i: A valid index of the collection. `i` must be `1`.
/// - Returns: The index value immediately before `i`.
@inlinable // trivial-implementation
public func index(before i: Index) -> Index {
_precondition(i == endIndex)
return 0
}
/// Returns an iterator over the elements of this collection.
///
/// - Complexity: O(1)
@inlinable // trivial-implementation
public func makeIterator() -> Iterator {
return Iterator(_elements: _element)
}
/// Accesses the element at the specified position.
///
/// - Parameter position: The position of the element to access. The only
/// valid position in a `CollectionOfOne` instance is `0`.
@inlinable // trivial-implementation
public subscript(position: Int) -> Element {
get {
_precondition(position == 0, "Index out of range")
return _element
}
set {
_precondition(position == 0, "Index out of range")
_element = newValue
}
}
@inlinable // trivial-implementation
public subscript(bounds: Range<Int>) -> SubSequence {
get {
_failEarlyRangeCheck(bounds, bounds: 0..<1)
return Slice(base: self, bounds: bounds)
}
set {
_failEarlyRangeCheck(bounds, bounds: 0..<1)
let n = newValue.count
_precondition(bounds.count == n, "CollectionOfOne can't be resized")
if n == 1 { self = newValue.base }
}
}
/// The number of elements in the collection, which is always one.
@inlinable // trivial-implementation
public var count: Int {
return 1
}
}
extension CollectionOfOne : CustomDebugStringConvertible {
/// A textual representation of the collection, suitable for debugging.
public var debugDescription: String {
return "CollectionOfOne(\(String(reflecting: _element)))"
}
}
extension CollectionOfOne : CustomReflectable {
public var customMirror: Mirror {
return Mirror(self, children: ["element": _element])
}
}