File: CacheableSequence.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (74 lines) | stat: -rw-r--r-- 2,209 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/*
 This source file is part of the Swift.org open source project

 Copyright (c) 2018 Apple Inc. and the Swift project authors
 Licensed under Apache License v2.0 with Runtime Library Exception

 See http://swift.org/LICENSE.txt for license information
 See http://swift.org/CONTRIBUTORS.txt for Swift project authors
*/

/// Wrapper for caching an arbitrary sequence.
public final class CacheableSequence<T: Sequence>: Sequence {
    public typealias Element = T.Element
    public typealias Iterator = CacheableSequenceIterator<T>

    /// The list of consumed items.
    fileprivate var items: [Element] = []
    
    /// An iterator on the underlying sequence, until complete.
    fileprivate var it: T.Iterator?
    
    public init(_ sequence: T) {
        self.it = sequence.makeIterator()
    }
    
    public func makeIterator() -> Iterator {
        return CacheableSequenceIterator(self)
    }

    /// Get the item at the given index.
    ///
    /// The index must either be at most one past the number of already captured
    /// items.
    fileprivate subscript(_ index: Int) -> Element? {
        assert(index >= 0 && index <= items.count)
        if index < items.count {
            return items[index]
        } else if self.it != nil {
            // If we still have an iterator, attempt to consume a new item.
            guard let item = it!.next() else {
                // We reached the end of the sequence, we can discard the iterator.
                self.it = nil
                return nil
            }
            items.append(item)
            return items[index]
        } else {
            return nil
        }
    }
}

/// An iterator for a CacheableSequence.
public final class CacheableSequenceIterator<T: Sequence>: IteratorProtocol {
    public typealias Element = T.Element
    
    /// The index of the iterator.
    var index = 0

    /// The sequence being iterated.
    let sequence: CacheableSequence<T>
    
    init(_ sequence: CacheableSequence<T>) {
        self.sequence = sequence
    }

    public func next() -> Element? {
        if let item = self.sequence[index] {
            index += 1
            return item
        }
        return nil
    }
}