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