resolveReferences walks the textNode tree searching for any leaf reference metadata and resolves each against the corresponding trunk references. Since pointer addresses in memory are not particularly readable to the user, it replaces each pointer value with an arbitrary and unique reference ID.
(s textNode)
| 112 | // Since pointer addresses in memory are not particularly readable to the user, |
| 113 | // it replaces each pointer value with an arbitrary and unique reference ID. |
| 114 | func resolveReferences(s textNode) { |
| 115 | var walkNodes func(textNode, func(textNode)) |
| 116 | walkNodes = func(s textNode, f func(textNode)) { |
| 117 | f(s) |
| 118 | switch s := s.(type) { |
| 119 | case *textWrap: |
| 120 | walkNodes(s.Value, f) |
| 121 | case textList: |
| 122 | for _, r := range s { |
| 123 | walkNodes(r.Value, f) |
| 124 | } |
| 125 | } |
| 126 | } |
| 127 | |
| 128 | // Collect all trunks and leaves with reference metadata. |
| 129 | var trunks, leaves []*textWrap |
| 130 | walkNodes(s, func(s textNode) { |
| 131 | if s, ok := s.(*textWrap); ok { |
| 132 | switch s.Metadata.(type) { |
| 133 | case leafReference: |
| 134 | leaves = append(leaves, s) |
| 135 | case trunkReference, trunkReferences: |
| 136 | trunks = append(trunks, s) |
| 137 | } |
| 138 | } |
| 139 | }) |
| 140 | |
| 141 | // No leaf references to resolve. |
| 142 | if len(leaves) == 0 { |
| 143 | return |
| 144 | } |
| 145 | |
| 146 | // Collect the set of all leaf references to resolve. |
| 147 | leafPtrs := make(map[value.Pointer]bool) |
| 148 | for _, leaf := range leaves { |
| 149 | leafPtrs[leaf.Metadata.(leafReference).p] = true |
| 150 | } |
| 151 | |
| 152 | // Collect the set of trunk pointers that are always paired together. |
| 153 | // This allows us to assign a single ID to both pointers for brevity. |
| 154 | // If a pointer in a pair ever occurs by itself or as a different pair, |
| 155 | // then the pair is broken. |
| 156 | pairedTrunkPtrs := make(map[value.Pointer]value.Pointer) |
| 157 | unpair := func(p value.Pointer) { |
| 158 | if !pairedTrunkPtrs[p].IsNil() { |
| 159 | pairedTrunkPtrs[pairedTrunkPtrs[p]] = value.Pointer{} // invalidate other half |
| 160 | } |
| 161 | pairedTrunkPtrs[p] = value.Pointer{} // invalidate this half |
| 162 | } |
| 163 | for _, trunk := range trunks { |
| 164 | switch p := trunk.Metadata.(type) { |
| 165 | case trunkReference: |
| 166 | unpair(p.p) // standalone pointer cannot be part of a pair |
| 167 | case trunkReferences: |
| 168 | p0, ok0 := pairedTrunkPtrs[p.pp[0]] |
| 169 | p1, ok1 := pairedTrunkPtrs[p.pp[1]] |
| 170 | switch { |
| 171 | case !ok0 && !ok1: |
no test coverage detected