stitch returns a Dynamic for tags and vecs. If vecs contains any Dynamics, stitch flattens them and returns a value containing no nested Dynamics.
(tags []uint32, vecs []Any)
| 84 | // stitch returns a Dynamic for tags and vecs. If vecs contains any Dynamics, |
| 85 | // stitch flattens them and returns a value containing no nested Dynamics. |
| 86 | func stitch(tags []uint32, vecs []Any) Any { |
| 87 | var foundDynamic bool |
| 88 | var newVecsLen int |
| 89 | for _, vec := range vecs { |
| 90 | if d, ok := vec.(*Dynamic); ok { |
| 91 | foundDynamic = true |
| 92 | newVecsLen += len(d.Values) |
| 93 | } else if o, ok := vec.(*Optional); ok { |
| 94 | foundDynamic = true |
| 95 | newVecsLen += len(o.Dynamic.Values) |
| 96 | } else { |
| 97 | newVecsLen++ |
| 98 | } |
| 99 | } |
| 100 | if !foundDynamic { |
| 101 | return NewDynamic(tags, vecs) |
| 102 | } |
| 103 | newVecs := make([]Any, 0, newVecsLen) // vecs but with nested Dynamics replaced by their values |
| 104 | nestedTags := make([][]uint32, len(vecs)) // tags from nested Dynamics (nil for non-Dynamics) |
| 105 | shifts := make([]uint32, len(vecs)) // tag + shift[tag] translates tag to newVecs |
| 106 | var lastShift uint32 |
| 107 | for i, vec := range vecs { |
| 108 | shifts[i] = lastShift |
| 109 | if d, ok := vec.(*Dynamic); ok { |
| 110 | newVecs = append(newVecs, d.Values...) |
| 111 | nestedTags[i] = d.Tags |
| 112 | lastShift += uint32(len(d.Values)) - 1 |
| 113 | } else if o, ok := vec.(*Optional); ok { |
| 114 | newVecs = append(newVecs, o.Dynamic.Values...) |
| 115 | nestedTags[i] = o.Dynamic.Tags |
| 116 | lastShift += uint32(len(o.Dynamic.Values)) - 1 |
| 117 | } else { |
| 118 | newVecs = append(newVecs, vec) |
| 119 | } |
| 120 | } |
| 121 | newTags := make([]uint32, len(tags)) |
| 122 | for i, t := range tags { |
| 123 | newTag := t + shifts[t] |
| 124 | if nested := nestedTags[t]; len(nested) > 0 { |
| 125 | newTag += nested[0] |
| 126 | nestedTags[t] = nested[1:] |
| 127 | } |
| 128 | newTags[i] = newTag |
| 129 | } |
| 130 | return NewDynamic(newTags, newVecs) |
| 131 | } |