github.com/cayleygraph/cayley@v0.7.7/graph/iterator/save.go (about) 1 package iterator 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/cayleygraph/cayley/graph" 8 ) 9 10 var ( 11 _ graph.IteratorFuture = (*Save)(nil) 12 _ graph.Tagger = (*Save)(nil) 13 ) 14 15 func Tag(it graph.Iterator, tag string) graph.Iterator { 16 if s, ok := it.(graph.Tagger); ok { 17 s.AddTags(tag) 18 return s 19 } else if s, ok := graph.AsShape(it).(graph.TaggerShape); ok { 20 s.AddTags(tag) 21 return graph.AsLegacy(s) 22 } 23 return NewSave(it, tag) 24 } 25 26 func TagShape(it graph.IteratorShape, tag string) graph.IteratorShape { 27 if s, ok := it.(graph.TaggerShape); ok { 28 s.AddTags(tag) 29 return s 30 } else if s, ok := graph.AsLegacy(it).(graph.Tagger); ok { 31 s.AddTags(tag) 32 return graph.AsShape(s) 33 } 34 return newSave(it, tag) 35 } 36 37 func NewSave(on graph.Iterator, tags ...string) *Save { 38 it := &Save{ 39 it: newSave(graph.AsShape(on), tags...), 40 } 41 it.Iterator = graph.NewLegacy(it.it, it) 42 return it 43 } 44 45 type Save struct { 46 it *save 47 graph.Iterator 48 } 49 50 func (it *Save) AsShape() graph.IteratorShape { 51 it.Close() 52 return it.it 53 } 54 55 // Add a tag to the iterator. 56 func (it *Save) AddTags(tag ...string) { 57 it.it.AddTags(tag...) 58 } 59 60 func (it *Save) AddFixedTag(tag string, value graph.Ref) { 61 it.it.AddFixedTag(tag, value) 62 } 63 64 // Tags returns the tags held in the tagger. The returned value must not be mutated. 65 func (it *Save) Tags() []string { 66 return it.it.Tags() 67 } 68 69 // Fixed returns the fixed tags held in the tagger. The returned value must not be mutated. 70 func (it *Save) FixedTags() map[string]graph.Ref { 71 return it.it.FixedTags() 72 } 73 74 func (it *Save) CopyFromTagger(st graph.TaggerBase) { 75 it.it.CopyFromTagger(st) 76 } 77 78 var ( 79 _ graph.IteratorShapeCompat = (*save)(nil) 80 _ graph.TaggerShape = (*save)(nil) 81 ) 82 83 func newSave(on graph.IteratorShape, tags ...string) *save { 84 s := &save{it: on} 85 s.AddTags(tags...) 86 return s 87 } 88 89 type save struct { 90 it graph.IteratorShape 91 tags []string 92 fixedTags map[string]graph.Ref 93 } 94 95 func (it *save) Iterate() graph.Scanner { 96 return newSaveNext(it.it.Iterate(), it.tags, it.fixedTags) 97 } 98 99 func (it *save) Lookup() graph.Index { 100 return newSaveContains(it.it.Lookup(), it.tags, it.fixedTags) 101 } 102 103 func (it *save) AsLegacy() graph.Iterator { 104 it2 := &Save{it: it} 105 it2.Iterator = graph.NewLegacy(it, it2) 106 return it2 107 } 108 109 func (it *save) String() string { 110 return fmt.Sprintf("Save(%v, %v)", it.tags, it.fixedTags) 111 } 112 113 // Add a tag to the iterator. 114 func (it *save) AddTags(tag ...string) { 115 it.tags = append(it.tags, tag...) 116 } 117 118 func (it *save) AddFixedTag(tag string, value graph.Ref) { 119 if it.fixedTags == nil { 120 it.fixedTags = make(map[string]graph.Ref) 121 } 122 it.fixedTags[tag] = value 123 } 124 125 // Tags returns the tags held in the tagger. The returned value must not be mutated. 126 func (it *save) Tags() []string { 127 return it.tags 128 } 129 130 // Fixed returns the fixed tags held in the tagger. The returned value must not be mutated. 131 func (it *save) FixedTags() map[string]graph.Ref { 132 return it.fixedTags 133 } 134 135 func (it *save) CopyFromTagger(st graph.TaggerBase) { 136 it.tags = append(it.tags, st.Tags()...) 137 138 fixed := st.FixedTags() 139 if len(fixed) == 0 { 140 return 141 } 142 if it.fixedTags == nil { 143 it.fixedTags = make(map[string]graph.Ref, len(fixed)) 144 } 145 for k, v := range fixed { 146 it.fixedTags[k] = v 147 } 148 } 149 150 func (it *save) Stats(ctx context.Context) (graph.IteratorCosts, error) { 151 return it.it.Stats(ctx) 152 } 153 154 func (it *save) Optimize(ctx context.Context) (nit graph.IteratorShape, no bool) { 155 sub, ok := it.it.Optimize(ctx) 156 if len(it.tags) == 0 && len(it.fixedTags) == 0 { 157 return sub, true 158 } 159 if st, ok2 := sub.(graph.TaggerShape); ok2 { 160 st.CopyFromTagger(it) 161 return st, true 162 } else if st, ok2 := graph.AsLegacy(sub).(graph.Tagger); ok2 { 163 st.CopyFromTagger(it) 164 return graph.AsShape(st), true 165 } 166 if !ok { 167 return it, false 168 } 169 s := newSave(sub) 170 s.CopyFromTagger(it) 171 return s, true 172 } 173 174 func (it *save) SubIterators() []graph.IteratorShape { 175 return []graph.IteratorShape{it.it} 176 } 177 178 func newSaveNext(it graph.Scanner, tags []string, fixed map[string]graph.Ref) *saveNext { 179 return &saveNext{it: it, tags: tags, fixedTags: fixed} 180 } 181 182 type saveNext struct { 183 it graph.Scanner 184 tags []string 185 fixedTags map[string]graph.Ref 186 } 187 188 func (it *saveNext) String() string { 189 return fmt.Sprintf("Save(%v, %v)", it.tags, it.fixedTags) 190 } 191 192 func (it *saveNext) TagResults(dst map[string]graph.Ref) { 193 it.it.TagResults(dst) 194 195 v := it.Result() 196 for _, tag := range it.tags { 197 dst[tag] = v 198 } 199 200 for tag, value := range it.fixedTags { 201 dst[tag] = value 202 } 203 } 204 205 func (it *saveNext) Result() graph.Ref { 206 return it.it.Result() 207 } 208 209 func (it *saveNext) Next(ctx context.Context) bool { 210 return it.it.Next(ctx) 211 } 212 213 func (it *saveNext) NextPath(ctx context.Context) bool { 214 return it.it.NextPath(ctx) 215 } 216 217 func (it *saveNext) Err() error { 218 return it.it.Err() 219 } 220 221 func (it *saveNext) Close() error { 222 return it.it.Close() 223 } 224 225 func newSaveContains(it graph.Index, tags []string, fixed map[string]graph.Ref) *saveContains { 226 return &saveContains{it: it, tags: tags, fixed: fixed} 227 } 228 229 type saveContains struct { 230 it graph.Index 231 tags []string 232 fixed map[string]graph.Ref 233 } 234 235 func (it *saveContains) String() string { 236 return fmt.Sprintf("SaveContains(%v, %v)", it.tags, it.fixed) 237 } 238 239 func (it *saveContains) TagResults(dst map[string]graph.Ref) { 240 it.it.TagResults(dst) 241 242 v := it.Result() 243 for _, tag := range it.tags { 244 dst[tag] = v 245 } 246 247 for tag, value := range it.fixed { 248 dst[tag] = value 249 } 250 } 251 252 func (it *saveContains) Result() graph.Ref { 253 return it.it.Result() 254 } 255 256 func (it *saveContains) NextPath(ctx context.Context) bool { 257 return it.it.NextPath(ctx) 258 } 259 260 func (it *saveContains) Contains(ctx context.Context, v graph.Ref) bool { 261 return it.it.Contains(ctx, v) 262 } 263 264 func (it *saveContains) Err() error { 265 return it.it.Err() 266 } 267 268 func (it *saveContains) Close() error { 269 return it.it.Close() 270 }