github.com/ipld/go-ipld-prime@v0.21.0/traversal/selector/builder/builder.go (about) 1 package builder 2 3 import ( 4 "github.com/ipld/go-ipld-prime/datamodel" 5 "github.com/ipld/go-ipld-prime/fluent" 6 "github.com/ipld/go-ipld-prime/traversal/selector" 7 ) 8 9 // SelectorSpec is a specification for a selector that can build 10 // a selector datamodel.Node or an actual parsed Selector 11 type SelectorSpec interface { 12 Node() datamodel.Node 13 Selector() (selector.Selector, error) 14 } 15 16 // SelectorSpecBuilder is a utility interface to build selector ipld nodes 17 // quickly. 18 // 19 // It serves two purposes: 20 // 1. Save the user of go-ipld time and mental overhead with an easy 21 // interface for making selector nodes in much less code without having to remember 22 // the selector sigils 23 // 2. Provide a level of protection from selector schema changes, at least in terms 24 // of naming, if not structure 25 type SelectorSpecBuilder interface { 26 ExploreRecursiveEdge() SelectorSpec 27 ExploreRecursive(limit selector.RecursionLimit, sequence SelectorSpec) SelectorSpec 28 ExploreUnion(...SelectorSpec) SelectorSpec 29 ExploreAll(next SelectorSpec) SelectorSpec 30 ExploreIndex(index int64, next SelectorSpec) SelectorSpec 31 ExploreRange(start, end int64, next SelectorSpec) SelectorSpec 32 ExploreFields(ExploreFieldsSpecBuildingClosure) SelectorSpec 33 ExploreInterpretAs(as string, next SelectorSpec) SelectorSpec 34 Matcher() SelectorSpec 35 MatcherSubset(from, to int64) SelectorSpec 36 } 37 38 // ExploreFieldsSpecBuildingClosure is a function that provided to SelectorSpecBuilder's 39 // ExploreFields method that assembles the fields map in the selector using 40 // an ExploreFieldsSpecBuilder 41 type ExploreFieldsSpecBuildingClosure func(ExploreFieldsSpecBuilder) 42 43 // ExploreFieldsSpecBuilder is an interface for assemble the map of fields to 44 // selectors in ExploreFields 45 type ExploreFieldsSpecBuilder interface { 46 Insert(k string, v SelectorSpec) 47 } 48 49 type selectorSpecBuilder struct { 50 np datamodel.NodePrototype 51 } 52 53 type selectorSpec struct { 54 n datamodel.Node 55 } 56 57 func (ss selectorSpec) Node() datamodel.Node { 58 return ss.n 59 } 60 61 func (ss selectorSpec) Selector() (selector.Selector, error) { 62 return selector.ParseSelector(ss.n) 63 } 64 65 // NewSelectorSpecBuilder creates a SelectorSpecBuilder which will store 66 // data in the format determined by the given datamodel.NodePrototype. 67 func NewSelectorSpecBuilder(np datamodel.NodePrototype) SelectorSpecBuilder { 68 return &selectorSpecBuilder{np} 69 } 70 71 func (ssb *selectorSpecBuilder) ExploreRecursiveEdge() SelectorSpec { 72 return selectorSpec{ 73 fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) { 74 na.AssembleEntry(selector.SelectorKey_ExploreRecursiveEdge).CreateMap(0, func(na fluent.MapAssembler) {}) 75 }), 76 } 77 } 78 79 func (ssb *selectorSpecBuilder) ExploreRecursive(limit selector.RecursionLimit, sequence SelectorSpec) SelectorSpec { 80 return selectorSpec{ 81 fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) { 82 na.AssembleEntry(selector.SelectorKey_ExploreRecursive).CreateMap(2, func(na fluent.MapAssembler) { 83 na.AssembleEntry(selector.SelectorKey_Limit).CreateMap(1, func(na fluent.MapAssembler) { 84 switch limit.Mode() { 85 case selector.RecursionLimit_Depth: 86 na.AssembleEntry(selector.SelectorKey_LimitDepth).AssignInt(limit.Depth()) 87 case selector.RecursionLimit_None: 88 na.AssembleEntry(selector.SelectorKey_LimitNone).CreateMap(0, func(na fluent.MapAssembler) {}) 89 default: 90 panic("Unsupported recursion limit type") 91 } 92 }) 93 na.AssembleEntry(selector.SelectorKey_Sequence).AssignNode(sequence.Node()) 94 }) 95 }), 96 } 97 } 98 99 func (ssb *selectorSpecBuilder) ExploreAll(next SelectorSpec) SelectorSpec { 100 return selectorSpec{ 101 fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) { 102 na.AssembleEntry(selector.SelectorKey_ExploreAll).CreateMap(1, func(na fluent.MapAssembler) { 103 na.AssembleEntry(selector.SelectorKey_Next).AssignNode(next.Node()) 104 }) 105 }), 106 } 107 } 108 func (ssb *selectorSpecBuilder) ExploreIndex(index int64, next SelectorSpec) SelectorSpec { 109 return selectorSpec{ 110 fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) { 111 na.AssembleEntry(selector.SelectorKey_ExploreIndex).CreateMap(2, func(na fluent.MapAssembler) { 112 na.AssembleEntry(selector.SelectorKey_Index).AssignInt(index) 113 na.AssembleEntry(selector.SelectorKey_Next).AssignNode(next.Node()) 114 }) 115 }), 116 } 117 } 118 119 func (ssb *selectorSpecBuilder) ExploreRange(start, end int64, next SelectorSpec) SelectorSpec { 120 return selectorSpec{ 121 fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) { 122 na.AssembleEntry(selector.SelectorKey_ExploreRange).CreateMap(3, func(na fluent.MapAssembler) { 123 na.AssembleEntry(selector.SelectorKey_Start).AssignInt(start) 124 na.AssembleEntry(selector.SelectorKey_End).AssignInt(end) 125 na.AssembleEntry(selector.SelectorKey_Next).AssignNode(next.Node()) 126 }) 127 }), 128 } 129 } 130 131 func (ssb *selectorSpecBuilder) ExploreUnion(members ...SelectorSpec) SelectorSpec { 132 return selectorSpec{ 133 fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) { 134 na.AssembleEntry(selector.SelectorKey_ExploreUnion).CreateList(int64(len(members)), func(na fluent.ListAssembler) { 135 for _, member := range members { 136 na.AssembleValue().AssignNode(member.Node()) 137 } 138 }) 139 }), 140 } 141 } 142 143 func (ssb *selectorSpecBuilder) ExploreFields(specBuilder ExploreFieldsSpecBuildingClosure) SelectorSpec { 144 return selectorSpec{ 145 fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) { 146 na.AssembleEntry(selector.SelectorKey_ExploreFields).CreateMap(1, func(na fluent.MapAssembler) { 147 na.AssembleEntry(selector.SelectorKey_Fields).CreateMap(-1, func(na fluent.MapAssembler) { 148 specBuilder(exploreFieldsSpecBuilder{na}) 149 }) 150 }) 151 }), 152 } 153 } 154 155 func (ssb *selectorSpecBuilder) ExploreInterpretAs(as string, next SelectorSpec) SelectorSpec { 156 return selectorSpec{ 157 fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) { 158 na.AssembleEntry(selector.SelectorKey_ExploreInterpretAs).CreateMap(1, func(na fluent.MapAssembler) { 159 na.AssembleEntry(selector.SelectorKey_As).AssignString(as) 160 na.AssembleEntry(selector.SelectorKey_Next).AssignNode(next.Node()) 161 }) 162 }), 163 } 164 } 165 166 func (ssb *selectorSpecBuilder) Matcher() SelectorSpec { 167 return selectorSpec{ 168 fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) { 169 na.AssembleEntry(selector.SelectorKey_Matcher).CreateMap(0, func(na fluent.MapAssembler) {}) 170 }), 171 } 172 } 173 174 func (ssb *selectorSpecBuilder) MatcherSubset(from, to int64) SelectorSpec { 175 return selectorSpec{ 176 fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) { 177 na.AssembleEntry(selector.SelectorKey_Matcher).CreateMap(1, func(na fluent.MapAssembler) { 178 na.AssembleEntry(selector.SelectorKey_Subset).CreateMap(2, func(na fluent.MapAssembler) { 179 na.AssembleEntry(selector.SelectorKey_From).AssignInt(from) 180 na.AssembleEntry(selector.SelectorKey_To).AssignInt(to) 181 }) 182 }) 183 }), 184 } 185 } 186 187 type exploreFieldsSpecBuilder struct { 188 na fluent.MapAssembler 189 } 190 191 func (efsb exploreFieldsSpecBuilder) Insert(field string, s SelectorSpec) { 192 efsb.na.AssembleEntry(field).AssignNode(s.Node()) 193 }