//===----------------------------------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2020-2023 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 // //===----------------------------------------------------------------------===// @available(macOS 12, iOS 15, tvOS 15, watchOS 8, *) extension AttributedString.Runs { @preconcurrency public struct AttributesSlice1 : BidirectionalCollection, Sendable where T.Value : Sendable { public typealias Index = AttributedString.Index // FIXME: Why no labels? public typealias Element = (T.Value?, Range) internal typealias Runs = AttributedString.Runs let runs : Runs let _names: [String] let _constraints: [AttributeRunBoundaries] init(runs: Runs) { self.runs = runs // FIXME: ☠️ Get these from a proper cache in runs._guts. _names = [T.name] _constraints = T._constraintsInvolved } public struct Iterator: IteratorProtocol, Sendable { // Note: This is basically equivalent to `IndexingIterator`. public typealias Element = AttributesSlice1.Element let _slice: AttributesSlice1 var _index: AttributesSlice1.Index internal init(_ slice: AttributesSlice1) { self._slice = slice self._index = slice.startIndex } public mutating func next() -> Element? { if _index == _slice.endIndex { return nil } let run = _slice.runs[_index] let next = _slice.index(after: _index) let range = _index ..< next _index = next return (run._attributes[T.self], range) } } public func makeIterator() -> Iterator { Iterator(self) } public var startIndex: Index { runs._range.lowerBound } public var endIndex: Index { runs._range.upperBound } public func index(before i: Index) -> Index { runs._slicedRunBoundary( before: i, attributeNames: _names, constraints: _constraints) } public func index(after i: Index) -> Index { runs._slicedRunBoundary( after: i, attributeNames: _names, constraints: _constraints) } public subscript(position: AttributedString.Index) -> Element { let (start, runIndex) = runs._slicedRunBoundary( roundingDown: position, attributeNames: _names, constraints: _constraints) let end = self.index(after: position) let attributes = runs._guts.runs[runIndex.rangeIndex].attributes return (attributes[T.self], start ..< end) } } public subscript(_ keyPath: KeyPath) -> AttributesSlice1 { return AttributesSlice1(runs: self) } public subscript(_ t: T.Type) -> AttributesSlice1 { return AttributesSlice1(runs: self) } } @available(macOS 12, iOS 15, tvOS 15, watchOS 8, *) extension AttributedString.Runs { @preconcurrency public struct AttributesSlice2< T : AttributedStringKey, U : AttributedStringKey > : BidirectionalCollection, Sendable where T.Value : Sendable, U.Value : Sendable { public typealias Index = AttributedString.Index // FIXME: Why no labels? public typealias Element = (T.Value?, U.Value?, Range) internal typealias Runs = AttributedString.Runs let runs : Runs let _names: [String] let _constraints: [AttributeRunBoundaries] init(runs: Runs) { self.runs = runs // FIXME: ☠️ Get these from a proper cache in runs._guts. _names = [T.name, U.name] _constraints = Array(_contents: T.runBoundaries, U.runBoundaries) } public struct Iterator: IteratorProtocol, Sendable { // Note: This is basically equivalent to `IndexingIterator`. public typealias Element = AttributesSlice2.Element let _slice: AttributesSlice2 var _index: AttributedString.Index internal init(_ slice: AttributesSlice2) { self._slice = slice self._index = slice.startIndex } public mutating func next() -> Element? { if _index == _slice.endIndex { return nil } let run = _slice.runs[_index] let next = _slice.index(after: _index) let range = _index ..< next _index = next return (run._attributes[T.self], run._attributes[U.self], range) } } public func makeIterator() -> Iterator { Iterator(self) } public var startIndex: Index { runs._range.lowerBound } public var endIndex: Index { runs._range.upperBound } public func index(before i: Index) -> Index { runs._slicedRunBoundary( before: i, attributeNames: _names, constraints: _constraints) } public func index(after i: Index) -> Index { runs._slicedRunBoundary( after: i, attributeNames: _names, constraints: _constraints) } public subscript(position: AttributedString.Index) -> Element { let (start, runIndex) = runs._slicedRunBoundary( roundingDown: position, attributeNames: _names, constraints: _constraints) let end = self.index(after: position) let attributes = runs._guts.runs[runIndex.rangeIndex].attributes return (attributes[T.self], attributes[U.self], start ..< end) } } public subscript < T : AttributedStringKey, U : AttributedStringKey > ( _ t: KeyPath, _ u: KeyPath ) -> AttributesSlice2 { return AttributesSlice2(runs: self) } public subscript < T : AttributedStringKey, U : AttributedStringKey > ( _ t: T.Type, _ u: U.Type ) -> AttributesSlice2 { return AttributesSlice2(runs: self) } } @available(macOS 12, iOS 15, tvOS 15, watchOS 8, *) extension AttributedString.Runs { @preconcurrency public struct AttributesSlice3< T : AttributedStringKey, U : AttributedStringKey, V : AttributedStringKey > : BidirectionalCollection, Sendable where T.Value : Sendable, U.Value : Sendable, V.Value : Sendable { public typealias Index = AttributedString.Index // FIXME: Why no labels? public typealias Element = (T.Value?, U.Value?, V.Value?, Range) internal typealias Runs = AttributedString.Runs let runs : Runs let _names: [String] let _constraints: [AttributeRunBoundaries] init(runs: Runs) { self.runs = runs // FIXME: ☠️ Get these from a proper cache in runs._guts. _names = [T.name, U.name, V.name] _constraints = Array(_contents: T.runBoundaries, U.runBoundaries, V.runBoundaries) } public struct Iterator: IteratorProtocol, Sendable { // Note: This is basically equivalent to `IndexingIterator`. public typealias Element = AttributesSlice3.Element let _slice: AttributesSlice3 var _index: AttributedString.Index internal init(_ slice: AttributesSlice3) { self._slice = slice self._index = slice.startIndex } public mutating func next() -> Element? { if _index == _slice.endIndex { return nil } let run = _slice.runs[_index] let next = _slice.index(after: _index) let range = _index ..< next _index = next return ( run._attributes[T.self], run._attributes[U.self], run._attributes[V.self], range) } } public func makeIterator() -> Iterator { Iterator(self) } public var startIndex: Index { runs._range.lowerBound } public var endIndex: Index { runs._range.upperBound } public func index(before i: Index) -> Index { runs._slicedRunBoundary( before: i, attributeNames: _names, constraints: _constraints) } public func index(after i: Index) -> Index { runs._slicedRunBoundary( after: i, attributeNames: _names, constraints: _constraints) } public subscript(position: AttributedString.Index) -> Element { let (start, runIndex) = runs._slicedRunBoundary( roundingDown: position, attributeNames: _names, constraints: _constraints) let end = self.index(after: position) let attributes = runs._guts.runs[runIndex.rangeIndex].attributes return (attributes[T.self], attributes[U.self], attributes[V.self], start ..< end) } } public subscript < T : AttributedStringKey, U : AttributedStringKey, V : AttributedStringKey > ( _ t: KeyPath, _ u: KeyPath, _ v: KeyPath ) -> AttributesSlice3 { return AttributesSlice3(runs: self) } public subscript < T : AttributedStringKey, U : AttributedStringKey, V : AttributedStringKey > ( _ t: T.Type, _ u: U.Type, _ v: V.Type ) -> AttributesSlice3 { return AttributesSlice3(runs: self) } } @available(macOS 12, iOS 15, tvOS 15, watchOS 8, *) extension AttributedString.Runs { @preconcurrency public struct AttributesSlice4< T : AttributedStringKey, U : AttributedStringKey, V : AttributedStringKey, W : AttributedStringKey > : BidirectionalCollection, Sendable where T.Value : Sendable, U.Value : Sendable, V.Value : Sendable, W.Value : Sendable { public typealias Index = AttributedString.Index // FIXME: Why no labels? public typealias Element = (T.Value?, U.Value?, V.Value?, W.Value?, Range) internal typealias Runs = AttributedString.Runs let runs : Runs let _names: [String] let _constraints: [AttributeRunBoundaries] init(runs: Runs) { self.runs = runs // FIXME: ☠️ Get these from a proper cache in runs._guts. _names = [T.name, U.name, V.name, W.name] _constraints = Array( _contents: T.runBoundaries, U.runBoundaries, V.runBoundaries, W.runBoundaries) } public struct Iterator: IteratorProtocol, Sendable { // Note: This is basically equivalent to `IndexingIterator`. public typealias Element = AttributesSlice4.Element let _slice: AttributesSlice4 var _index: AttributedString.Index internal init(_ slice: AttributesSlice4) { self._slice = slice self._index = slice.startIndex } public mutating func next() -> Element? { if _index == _slice.endIndex { return nil } let run = _slice.runs[_index] let next = _slice.index(after: _index) let range = _index ..< next _index = next return ( run._attributes[T.self], run._attributes[U.self], run._attributes[V.self], run._attributes[W.self], range) } } public func makeIterator() -> Iterator { Iterator(self) } public var startIndex: Index { runs._range.lowerBound } public var endIndex: Index { runs._range.upperBound } public func index(before i: Index) -> Index { runs._slicedRunBoundary( before: i, attributeNames: _names, constraints: _constraints) } public func index(after i: Index) -> Index { runs._slicedRunBoundary( after: i, attributeNames: _names, constraints: _constraints) } public subscript(position: AttributedString.Index) -> Element { let (start, runIndex) = runs._slicedRunBoundary( roundingDown: position, attributeNames: _names, constraints: _constraints) let end = self.index(after: position) let attributes = runs._guts.runs[runIndex.rangeIndex].attributes return ( attributes[T.self], attributes[U.self], attributes[V.self], attributes[W.self], start ..< end) } } public subscript < T : AttributedStringKey, U : AttributedStringKey, V : AttributedStringKey, W : AttributedStringKey > ( _ t: KeyPath, _ u: KeyPath, _ v: KeyPath, _ w: KeyPath ) -> AttributesSlice4 { return AttributesSlice4(runs: self) } public subscript < T : AttributedStringKey, U : AttributedStringKey, V : AttributedStringKey, W : AttributedStringKey > ( _ t: T.Type, _ u: U.Type, _ v: V.Type, _ w: W.Type ) -> AttributesSlice4 { return AttributesSlice4(runs: self) } } @available(macOS 12, iOS 15, tvOS 15, watchOS 8, *) extension AttributedString.Runs { @preconcurrency public struct AttributesSlice5< T : AttributedStringKey, U : AttributedStringKey, V : AttributedStringKey, W : AttributedStringKey, X : AttributedStringKey > : BidirectionalCollection, Sendable where T.Value : Sendable, U.Value : Sendable, V.Value : Sendable, W.Value : Sendable, X.Value : Sendable { public typealias Index = AttributedString.Index // FIXME: Why no labels? public typealias Element = (T.Value?, U.Value?, V.Value?, W.Value?, X.Value?, Range) internal typealias Runs = AttributedString.Runs let runs : Runs let _names: [String] let _constraints: [AttributeRunBoundaries] init(runs: Runs) { self.runs = runs // FIXME: ☠️ Get these from a proper cache in runs._guts. _names = [T.name, U.name, V.name, W.name] _constraints = Array( _contents: T.runBoundaries, U.runBoundaries, V.runBoundaries, W.runBoundaries, X.runBoundaries) } public struct Iterator: IteratorProtocol, Sendable { public typealias Element = AttributesSlice5.Element let _slice: AttributesSlice5 var _index: AttributedString.Index internal init(_ slice: AttributesSlice5) { self._slice = slice self._index = slice.startIndex } public mutating func next() -> Element? { if _index == _slice.endIndex { return nil } let run = _slice.runs[_index] let next = _slice.index(after: _index) let range = _index ..< next _index = next return ( run._attributes[T.self], run._attributes[U.self], run._attributes[V.self], run._attributes[W.self], run._attributes[X.self], range) } } public func makeIterator() -> Iterator { Iterator(self) } public var startIndex: Index { runs._range.lowerBound } public var endIndex: Index { runs._range.upperBound } public func index(before i: Index) -> Index { runs._slicedRunBoundary( before: i, attributeNames: _names, constraints: _constraints) } public func index(after i: Index) -> Index { runs._slicedRunBoundary( after: i, attributeNames: _names, constraints: _constraints) } public subscript(position: AttributedString.Index) -> Element { let (start, runIndex) = runs._slicedRunBoundary( roundingDown: position, attributeNames: _names, constraints: _constraints) let end = self.index(after: position) let attributes = runs._guts.runs[runIndex.rangeIndex].attributes return ( attributes[T.self], attributes[U.self], attributes[V.self], attributes[W.self], attributes[X.self], start ..< end) } } public subscript < T : AttributedStringKey, U : AttributedStringKey, V : AttributedStringKey, W : AttributedStringKey, X : AttributedStringKey > ( _ t: KeyPath, _ u: KeyPath, _ v: KeyPath, _ w: KeyPath, _ x: KeyPath ) -> AttributesSlice5 { return AttributesSlice5(runs: self) } public subscript < T : AttributedStringKey, U : AttributedStringKey, V : AttributedStringKey, W : AttributedStringKey, X : AttributedStringKey > ( _ t: T.Type, _ u: U.Type, _ v: V.Type, _ w: W.Type, _ x: X.Type ) -> AttributesSlice5 { return AttributesSlice5(runs: self) } } #if FOUNDATION_FRAMEWORK @available(macOS 12, iOS 15, tvOS 15, watchOS 8, *) extension AttributedString.Runs { @_spi(AttributedString) public struct NSAttributesSlice : BidirectionalCollection, Sendable { public typealias Index = AttributedString.Index // FIXME: Why no labels? public typealias Element = (AttributeContainer, Range) internal typealias Runs = AttributedString.Runs let runs : Runs let keys : [NSAttributedString.Key] private let _names: [String] internal init(runs: Runs, keys: [NSAttributedString.Key]) { self.runs = runs self.keys = keys self._names = keys.map { $0.rawValue } } public struct Iterator: IteratorProtocol, Sendable { // Note: This is basically equivalent to `IndexingIterator`. public typealias Element = NSAttributesSlice.Element let _slice: NSAttributesSlice var _index: AttributedString.Index internal init(_ slice: NSAttributesSlice) { self._slice = slice self._index = slice.startIndex } public mutating func next() -> Element? { if _index == _slice.endIndex { return nil } let run = _slice.runs[_index] let next = _slice.index(after: _index) let range = _index ..< next _index = next return (_slice.buildContainer(from: run._attributes), range) } } public func makeIterator() -> Iterator { Iterator(self) } public var startIndex: Index { runs._range.lowerBound } public var endIndex: Index { runs._range.upperBound } public func index(before i: Index) -> Index { runs._slicedRunBoundary( before: i, attributeNames: _names, constraints: []) } public func index(after i: Index) -> Index { runs._slicedRunBoundary( after: i, attributeNames: _names, constraints: []) } public subscript(position: AttributedString.Index) -> Element { let (start, runIndex) = runs._slicedRunBoundary( roundingDown: position, attributeNames: _names, constraints: []) let end = self.index(after: position) let attributes = runs._guts.runs[runIndex.rangeIndex].attributes return (buildContainer(from: attributes), start ..< end) } private func buildContainer(from storage: AttributedString._AttributeStorage) -> AttributeContainer { AttributeContainer(storage.filter { _names.contains($0.key) }) } } @_spi(AttributedString) public subscript(nsAttributedStringKeys keys: NSAttributedString.Key...) -> NSAttributesSlice { return NSAttributesSlice(runs: self, keys: keys) } } #endif // FOUNDATION_FRAMEWORK extension RangeReplaceableCollection { internal init(_contents item1: Element?) { self.init() if let item1 { self.append(item1) } } internal init(_contents item1: Element?, _ item2: Element?) { self.init() var c = 0 if item1 != nil { c &+= 1 } if item2 != nil { c &+= 1 } guard c > 0 else { return } self.reserveCapacity(c) if let item1 { self.append(item1) } if let item2 { self.append(item2) } } internal init(_contents item1: Element?, _ item2: Element?, _ item3: Element?) { self.init() var c = 0 if item1 != nil { c &+= 1 } if item2 != nil { c &+= 1 } if item3 != nil { c &+= 1 } guard c > 0 else { return } self.reserveCapacity(c) if let item1 { self.append(item1) } if let item2 { self.append(item2) } if let item3 { self.append(item3) } } internal init( _contents item1: Element?, _ item2: Element?, _ item3: Element?, _ item4: Element? ) { self.init() var c = 0 if item1 != nil { c &+= 1 } if item2 != nil { c &+= 1 } if item3 != nil { c &+= 1 } if item4 != nil { c &+= 1 } guard c > 0 else { return } self.reserveCapacity(c) if let item1 { self.append(item1) } if let item2 { self.append(item2) } if let item3 { self.append(item3) } if let item4 { self.append(item4) } } internal init( _contents item1: Element?, _ item2: Element?, _ item3: Element?, _ item4: Element?, _ item5: Element? ) { self.init() var c = 0 if item1 != nil { c &+= 1 } if item2 != nil { c &+= 1 } if item3 != nil { c &+= 1 } if item4 != nil { c &+= 1 } if item5 != nil { c &+= 1 } guard c > 0 else { return } self.reserveCapacity(c) if let item1 { self.append(item1) } if let item2 { self.append(item2) } if let item3 { self.append(item3) } if let item4 { self.append(item4) } if let item5 { self.append(item5) } } }