github.com/ipld/go-ipld-prime@v0.21.0/traversal/selector/exploreFields.go (about) 1 package selector 2 3 import ( 4 "fmt" 5 6 "github.com/ipld/go-ipld-prime/datamodel" 7 ) 8 9 // ExploreFields traverses named fields in a map (or equivalently, struct, if 10 // traversing on typed/schema nodes) and applies a next selector to the 11 // reached nodes. 12 // 13 // Note that a concept of "ExplorePath" (e.g. "foo/bar/baz") can be represented 14 // as a set of three nexted ExploreFields selectors, each specifying one field. 15 // (For this reason, we don't have a special "ExplorePath" feature; use this.) 16 // 17 // ExploreFields also works for selecting specific elements out of a list; 18 // if a "field" is a base-10 int, it will be coerced and do the right thing. 19 // ExploreIndex or ExploreRange is more appropriate, however, and should be preferred. 20 type ExploreFields struct { 21 selections map[string]Selector 22 interests []datamodel.PathSegment // keys of above; already boxed as that's the only way we consume them 23 } 24 25 // Interests for ExploreFields are the fields listed in the selector node 26 func (s ExploreFields) Interests() []datamodel.PathSegment { 27 return s.interests 28 } 29 30 // Explore returns the selector for the given path if it is a field in 31 // the selector node or nil if not 32 func (s ExploreFields) Explore(n datamodel.Node, p datamodel.PathSegment) (Selector, error) { 33 return s.selections[p.String()], nil 34 } 35 36 // Decide always returns false because this is not a matcher 37 func (s ExploreFields) Decide(n datamodel.Node) bool { 38 return false 39 } 40 41 // Match always returns false because this is not a matcher 42 func (s ExploreFields) Match(node datamodel.Node) (datamodel.Node, error) { 43 return nil, nil 44 } 45 46 // ParseExploreFields assembles a Selector 47 // from a ExploreFields selector node 48 func (pc ParseContext) ParseExploreFields(n datamodel.Node) (Selector, error) { 49 if n.Kind() != datamodel.Kind_Map { 50 return nil, fmt.Errorf("selector spec parse rejected: selector body must be a map") 51 } 52 fields, err := n.LookupByString(SelectorKey_Fields) 53 if err != nil { 54 return nil, fmt.Errorf("selector spec parse rejected: fields in ExploreFields selector must be present") 55 } 56 if fields.Kind() != datamodel.Kind_Map { 57 return nil, fmt.Errorf("selector spec parse rejected: fields in ExploreFields selector must be a map") 58 } 59 x := ExploreFields{ 60 make(map[string]Selector, fields.Length()), 61 make([]datamodel.PathSegment, 0, fields.Length()), 62 } 63 for itr := fields.MapIterator(); !itr.Done(); { 64 kn, v, err := itr.Next() 65 if err != nil { 66 return nil, fmt.Errorf("error during selector spec parse: %w", err) 67 } 68 69 kstr, _ := kn.AsString() 70 x.interests = append(x.interests, datamodel.PathSegmentOfString(kstr)) 71 x.selections[kstr], err = pc.ParseSelector(v) 72 if err != nil { 73 return nil, err 74 } 75 } 76 return x, nil 77 }