mirror of
https://github.com/apple/swift-foundation.git
synced 2025-05-18 03:09:06 +08:00
107 lines
3.6 KiB
Swift
107 lines
3.6 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#if FOUNDATION_FRAMEWORK
|
|
@_spi(Unstable) internal import CollectionsInternal
|
|
#elseif canImport(_RopeModule)
|
|
internal import _RopeModule
|
|
#elseif canImport(_FoundationCollections)
|
|
internal import _FoundationCollections
|
|
#endif
|
|
|
|
@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
|
|
extension AttributedString.Runs {
|
|
@dynamicMemberLookup
|
|
public struct Run: Sendable {
|
|
internal typealias _AttributeStorage = AttributedString._AttributeStorage
|
|
|
|
internal let _attributes: _AttributeStorage
|
|
internal let _range: Range<BigString.Index>
|
|
|
|
// FIXME: Remove this and update description to only print attribute values
|
|
internal let _guts: AttributedString.Guts
|
|
|
|
internal init(
|
|
_attributes attributes: _AttributeStorage,
|
|
_ range: Range<BigString.Index>,
|
|
_ guts: AttributedString.Guts
|
|
) {
|
|
self._attributes = attributes
|
|
self._range = range
|
|
self._guts = guts
|
|
}
|
|
}
|
|
}
|
|
|
|
@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
|
|
extension AttributedString.Runs.Run: Equatable {
|
|
public static func == (lhs: Self, rhs: Self) -> Bool {
|
|
lhs._range._utf8OffsetRange.count == rhs._range._utf8OffsetRange.count
|
|
&& lhs._attributes == rhs._attributes
|
|
}
|
|
}
|
|
|
|
@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
|
|
extension AttributedString.Runs.Run: CustomStringConvertible {
|
|
public var description: String {
|
|
AttributedSubstring(_guts, in: _range).description
|
|
}
|
|
}
|
|
|
|
@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
|
|
extension AttributedString.Runs.Run {
|
|
public var range: Range<AttributedString.Index> {
|
|
let lower = AttributedString.Index(_range.lowerBound, version: _guts.version)
|
|
let upper = AttributedString.Index(_range.upperBound, version: _guts.version)
|
|
return Range(uncheckedBounds: (lower, upper))
|
|
}
|
|
|
|
internal var _utf8Count: Int {
|
|
_range._utf8OffsetRange.count
|
|
}
|
|
|
|
internal func clamped(to range: Range<BigString.Index>) -> Self {
|
|
Self(_attributes: self._attributes, _range.clamped(to: range), _guts)
|
|
}
|
|
|
|
public var attributes: AttributeContainer {
|
|
AttributeContainer(self._attributes)
|
|
}
|
|
}
|
|
|
|
@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
|
|
extension AttributedString.Runs.Run {
|
|
@preconcurrency
|
|
@inlinable // Trivial implementation, allows callers to optimize away the keypath allocation
|
|
public subscript<K: AttributedStringKey>(
|
|
dynamicMember keyPath: KeyPath<AttributeDynamicLookup, K>
|
|
) -> K.Value?
|
|
where K.Value: Sendable {
|
|
get { self[K.self] }
|
|
}
|
|
|
|
@preconcurrency
|
|
public subscript<K: AttributedStringKey>(_: K.Type) -> K.Value? where K.Value: Sendable {
|
|
get { _attributes[K.self] }
|
|
}
|
|
|
|
public subscript<S: AttributeScope>(
|
|
dynamicMember keyPath: KeyPath<AttributeScopes, S.Type>
|
|
) -> ScopedAttributeContainer<S> {
|
|
get { ScopedAttributeContainer(_attributes) }
|
|
}
|
|
|
|
internal subscript<S: AttributeScope>(_ scope: S.Type) -> ScopedAttributeContainer<S> {
|
|
get { ScopedAttributeContainer(_attributes) }
|
|
}
|
|
}
|