File: MarkupData.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 (170 lines) | stat: -rw-r--r-- 6,619 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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/*
 This source file is part of the Swift.org open source project

 Copyright (c) 2021 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 Swift project authors
*/

/// A unique identifier for an element in any markup tree currently in memory.
struct MarkupIdentifier: Equatable {
    /// A globally unique identifier for the root of the tree,
    /// acting as a scope for child identifiers.
    let rootId: UInt64

    /// A locally unique identifier for a child under a root.
    let childId: Int

    /// Returns the identifier for the first child of this identifier's element.
    func firstChild() -> MarkupIdentifier {
        return .init(rootId: rootId, childId: childId + 1)
    }

    /// Returns the identifier for the next sibling of the given raw element.
    ///
    /// - Note: This method assumes that this identifier belongs to `raw`.
    func nextSibling(from raw: RawMarkup) -> MarkupIdentifier {
        return .init(rootId: rootId, childId: childId + raw.subtreeCount)
    }

    /// Returns the identifier for the previous sibling of the given raw element.
    ///
    /// - Note: This method assumes that this identifier belongs to `raw`.
    func previousSibling(from raw: RawMarkup) -> MarkupIdentifier {
        return .init(rootId: rootId, childId: childId - raw.subtreeCount)
    }

    /// Returns the identifier for the last child of this identifier's element.
    func lastChildOfParent(_ parent: RawMarkup) -> MarkupIdentifier {
        return .init(rootId: rootId, childId: childId + parent.subtreeCount)
    }

    /// Returns an identifier for a new root element.
    static func newRoot() -> MarkupIdentifier {
        return .init(rootId: AtomicCounter.next(), childId: 0)
    }
}

/// Metadata for a specific markup element in memory.
struct MarkupMetadata {
    /// A unique identifier under a root element.
    let id: MarkupIdentifier

    /// The index in the parent's children.
    let indexInParent: Int

    init(id: MarkupIdentifier, indexInParent: Int) {
        self.id = id
        self.indexInParent = indexInParent
    }

    /// Returns metadata for the first child of this metadata's element.
    func firstChild() -> MarkupMetadata {
        return MarkupMetadata(id: id.firstChild(), indexInParent: 0)
    }

    /// Returns metadata for the next sibling of the given raw element.
    ///
    /// - Note: This method assumes that this metadata belongs to `raw`.
    func nextSibling(from raw: RawMarkup) -> MarkupMetadata {
        return MarkupMetadata(id: id.nextSibling(from: raw), indexInParent: indexInParent + 1)
    }

    /// Returns metadata for the previous sibling of the given raw element.
    ///
    /// - Note: This method assumes that this metadata belongs to `raw`.
    func previousSibling(from raw: RawMarkup) -> MarkupMetadata {
        return MarkupMetadata(id: id.previousSibling(from: raw), indexInParent: indexInParent - 1)
    }

    /// Returns metadata for the last child of this identifier's element.
    ///
    /// - Note: This method assumes that this metadata belongs to `parent`.
    func lastChildMetadata(of parent: RawMarkup) -> MarkupMetadata {
        return MarkupMetadata(id: id.lastChildOfParent(parent), indexInParent: parent.childCount - 1)
    }
}

/// A specific occurrence of a reusable `RawMarkup` element in a markup tree.
///
/// Since `RawMarkup` nodes can be reused in different trees, there needs to be a way
/// to tell the difference between a paragraph that occurs in one document and
/// that same paragraph reused in another document.
///
/// This bundles a `RawMarkup` node with some metadata that keeps track of
/// where and in which tree the element resides.
struct AbsoluteRawMarkup {
    /// The relative, sharable raw markup element.
    let markup: RawMarkup

    /// Metadata associated with this particular occurrence of the raw markup.
    let metadata: MarkupMetadata
}

/// Internal data for a markup element.
///
/// Unlike `RawMarkup`, this represents a specific element of markup in a specific tree,
/// allowing mechanisms such as finding an element's parent, siblings, and order in which
/// it occurred among its siblings.
/// > Warning: This type is an implementation detail and is not meant to be used directly.
public struct _MarkupData {
    /// The `AbsoluteRawMarkup` backing this element's data.
    let raw: AbsoluteRawMarkup

    /// This element's parent, or `nil` if this is a root.
    let parent: Markup?

    /// The index of the element in its parent if it has one, else `0`.
    var indexInParent: Int {
        return raw.metadata.indexInParent
    }

    /// A unique identifier for this data. Use as you would pointer identity.
    var id: MarkupIdentifier {
        return raw.metadata.id
    }

    /// The root of the tree in which the element resides.
    var root: _MarkupData {
        guard let parent = parent else {
            return self
        }
        return parent._data.root
    }

    /// The source range of the element if it was parsed from text; otherwise, nil.
    var range: SourceRange? {
        return raw.markup.parsedRange
    }

    // Keep the `init` internal as this type is not meant to be initialized outside the framework.

    /// Creates a `MarkupData` from the given `RawMarkup` and place in an immuatable markup tree, explicitly specifying a unique identifier.
    ///
    /// - precondition: `uniqueIdentifier <= AtomicCounter.current`.
    ///
    /// - parameter raw: The `AbsoluteRawMarkup` representing the element.
    /// - parameter parent: This element's parent, `nil` if the element is a root.
    init(_ raw: AbsoluteRawMarkup, parent: Markup? = nil) {
        self.raw = raw
        self.parent = parent
    }

    /// Returns the replaced element in a new tree.
    func replacingSelf(_ newRaw: RawMarkup) -> _MarkupData {
        if let parent = parent {
            let newParent = parent._data.substitutingChild(newRaw, at: indexInParent)
            return newParent.child(at: indexInParent)!._data
        } else {
            return _MarkupData(AbsoluteRawMarkup(markup: newRaw, metadata: MarkupMetadata(id: .newRoot(), indexInParent: 0)), parent: nil)
        }
    }

    /// Returns a new `MarkupData` with the given child now at the `index`.
    func substitutingChild(_ rawChild: RawMarkup, at index: Int) -> Markup {
        let newRaw = raw.markup.substitutingChild(rawChild, at: index)
        return makeMarkup(replacingSelf(newRaw))
    }
}