Commit cbedbe9a authored by hannahhoward's avatar hannahhoward

refactor(selector): Move parse context to receiver

Rename SelectorContext to ParsedParent (more accurate) and put in a ParseContext state object which
is tracked w/o var args
parent 8101125e
...@@ -28,7 +28,7 @@ func (s ExploreAll) Decide(n ipld.Node) bool { ...@@ -28,7 +28,7 @@ func (s ExploreAll) Decide(n ipld.Node) bool {
} }
// ParseExploreAll assembles a Selector from a ExploreAll selector node // ParseExploreAll assembles a Selector from a ExploreAll selector node
func ParseExploreAll(n ipld.Node, selectorContexts ...SelectorContext) (Selector, error) { func (pc ParseContext) ParseExploreAll(n ipld.Node) (Selector, error) {
if n.ReprKind() != ipld.ReprKind_Map { if n.ReprKind() != ipld.ReprKind_Map {
return nil, fmt.Errorf("selector spec parse rejected: selector body must be a map") return nil, fmt.Errorf("selector spec parse rejected: selector body must be a map")
} }
...@@ -36,7 +36,7 @@ func ParseExploreAll(n ipld.Node, selectorContexts ...SelectorContext) (Selector ...@@ -36,7 +36,7 @@ func ParseExploreAll(n ipld.Node, selectorContexts ...SelectorContext) (Selector
if err != nil { if err != nil {
return nil, fmt.Errorf("selector spec parse rejected: next field must be present in ExploreAll selector") return nil, fmt.Errorf("selector spec parse rejected: next field must be present in ExploreAll selector")
} }
selector, err := ParseSelector(next, selectorContexts...) selector, err := pc.ParseSelector(next)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -13,12 +13,12 @@ func TestParseExploreAll(t *testing.T) { ...@@ -13,12 +13,12 @@ func TestParseExploreAll(t *testing.T) {
fnb := fluent.WrapNodeBuilder(ipldfree.NodeBuilder()) // just for the other fixture building fnb := fluent.WrapNodeBuilder(ipldfree.NodeBuilder()) // just for the other fixture building
t.Run("parsing non map node should error", func(t *testing.T) { t.Run("parsing non map node should error", func(t *testing.T) {
sn := fnb.CreateInt(0) sn := fnb.CreateInt(0)
_, err := ParseExploreAll(sn) _, err := ParseContext{}.ParseExploreAll(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: selector body must be a map")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: selector body must be a map"))
}) })
t.Run("parsing map node without next field should error", func(t *testing.T) { t.Run("parsing map node without next field should error", func(t *testing.T) {
sn := fnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {}) sn := fnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {})
_, err := ParseExploreAll(sn) _, err := ParseContext{}.ParseExploreAll(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: next field must be present in ExploreAll selector")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: next field must be present in ExploreAll selector"))
}) })
...@@ -26,7 +26,7 @@ func TestParseExploreAll(t *testing.T) { ...@@ -26,7 +26,7 @@ func TestParseExploreAll(t *testing.T) {
sn := fnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) { sn := fnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {
mb.Insert(knb.CreateString(nextSelectorKey), vnb.CreateInt(0)) mb.Insert(knb.CreateString(nextSelectorKey), vnb.CreateInt(0))
}) })
_, err := ParseExploreAll(sn) _, err := ParseContext{}.ParseExploreAll(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: selector is a keyed union and thus must be a map")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: selector is a keyed union and thus must be a map"))
}) })
t.Run("parsing map node with next field with valid selector node should parse", func(t *testing.T) { t.Run("parsing map node with next field with valid selector node should parse", func(t *testing.T) {
...@@ -35,7 +35,7 @@ func TestParseExploreAll(t *testing.T) { ...@@ -35,7 +35,7 @@ func TestParseExploreAll(t *testing.T) {
mb.Insert(knb.CreateString(matcherKey), vnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {})) mb.Insert(knb.CreateString(matcherKey), vnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {}))
})) }))
}) })
s, err := ParseExploreAll(sn) s, err := ParseContext{}.ParseExploreAll(sn)
Wish(t, err, ShouldEqual, nil) Wish(t, err, ShouldEqual, nil)
Wish(t, s, ShouldEqual, ExploreAll{Matcher{}}) Wish(t, s, ShouldEqual, ExploreAll{Matcher{}})
}) })
......
...@@ -40,7 +40,7 @@ func (s ExploreFields) Decide(n ipld.Node) bool { ...@@ -40,7 +40,7 @@ func (s ExploreFields) Decide(n ipld.Node) bool {
// ParseExploreFields assembles a Selector // ParseExploreFields assembles a Selector
// from a ExploreFields selector node // from a ExploreFields selector node
func ParseExploreFields(n ipld.Node, selectorContexts ...SelectorContext) (Selector, error) { func (pc ParseContext) ParseExploreFields(n ipld.Node) (Selector, error) {
if n.ReprKind() != ipld.ReprKind_Map { if n.ReprKind() != ipld.ReprKind_Map {
return nil, fmt.Errorf("selector spec parse rejected: selector body must be a map") return nil, fmt.Errorf("selector spec parse rejected: selector body must be a map")
} }
...@@ -63,7 +63,7 @@ func ParseExploreFields(n ipld.Node, selectorContexts ...SelectorContext) (Selec ...@@ -63,7 +63,7 @@ func ParseExploreFields(n ipld.Node, selectorContexts ...SelectorContext) (Selec
kstr, _ := kn.AsString() kstr, _ := kn.AsString()
x.interests = append(x.interests, PathSegmentString{kstr}) x.interests = append(x.interests, PathSegmentString{kstr})
x.selections[kstr], err = ParseSelector(v, selectorContexts...) x.selections[kstr], err = pc.ParseSelector(v)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -13,19 +13,19 @@ func TestParseExploreFields(t *testing.T) { ...@@ -13,19 +13,19 @@ func TestParseExploreFields(t *testing.T) {
fnb := fluent.WrapNodeBuilder(ipldfree.NodeBuilder()) // just for the other fixture building fnb := fluent.WrapNodeBuilder(ipldfree.NodeBuilder()) // just for the other fixture building
t.Run("parsing non map node should error", func(t *testing.T) { t.Run("parsing non map node should error", func(t *testing.T) {
sn := fnb.CreateInt(0) sn := fnb.CreateInt(0)
_, err := ParseExploreFields(sn) _, err := ParseContext{}.ParseExploreFields(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: selector body must be a map")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: selector body must be a map"))
}) })
t.Run("parsing map node without fields value should error", func(t *testing.T) { t.Run("parsing map node without fields value should error", func(t *testing.T) {
sn := fnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {}) sn := fnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {})
_, err := ParseExploreFields(sn) _, err := ParseContext{}.ParseExploreFields(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: fields in ExploreFields selector must be present")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: fields in ExploreFields selector must be present"))
}) })
t.Run("parsing map node with fields value that is not a map should error", func(t *testing.T) { t.Run("parsing map node with fields value that is not a map should error", func(t *testing.T) {
sn := fnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) { sn := fnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {
mb.Insert(knb.CreateString(fieldsKey), vnb.CreateString("cheese")) mb.Insert(knb.CreateString(fieldsKey), vnb.CreateString("cheese"))
}) })
_, err := ParseExploreFields(sn) _, err := ParseContext{}.ParseExploreFields(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: fields in ExploreFields selector must be a map")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: fields in ExploreFields selector must be a map"))
}) })
t.Run("parsing map node with selector node in fields that is invalid should return child's error", func(t *testing.T) { t.Run("parsing map node with selector node in fields that is invalid should return child's error", func(t *testing.T) {
...@@ -34,7 +34,7 @@ func TestParseExploreFields(t *testing.T) { ...@@ -34,7 +34,7 @@ func TestParseExploreFields(t *testing.T) {
mb.Insert(knb.CreateString("applesauce"), vnb.CreateInt(0)) mb.Insert(knb.CreateString("applesauce"), vnb.CreateInt(0))
})) }))
}) })
_, err := ParseExploreFields(sn) _, err := ParseContext{}.ParseExploreFields(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: selector is a keyed union and thus must be a map")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: selector is a keyed union and thus must be a map"))
}) })
t.Run("parsing map node with fields value that is map of only valid selector node should parse", func(t *testing.T) { t.Run("parsing map node with fields value that is map of only valid selector node should parse", func(t *testing.T) {
...@@ -45,7 +45,7 @@ func TestParseExploreFields(t *testing.T) { ...@@ -45,7 +45,7 @@ func TestParseExploreFields(t *testing.T) {
})) }))
})) }))
}) })
s, err := ParseExploreFields(sn) s, err := ParseContext{}.ParseExploreFields(sn)
Wish(t, err, ShouldEqual, nil) Wish(t, err, ShouldEqual, nil)
Wish(t, s, ShouldEqual, ExploreFields{map[string]Selector{"applesauce": Matcher{}}, []PathSegment{PathSegmentString{S: "applesauce"}}}) Wish(t, s, ShouldEqual, ExploreFields{map[string]Selector{"applesauce": Matcher{}}, []PathSegment{PathSegmentString{S: "applesauce"}}})
}) })
......
...@@ -39,7 +39,7 @@ func (s ExploreIndex) Decide(n ipld.Node) bool { ...@@ -39,7 +39,7 @@ func (s ExploreIndex) Decide(n ipld.Node) bool {
// ParseExploreIndex assembles a Selector // ParseExploreIndex assembles a Selector
// from a ExploreIndex selector node // from a ExploreIndex selector node
func ParseExploreIndex(n ipld.Node, selectorContexts ...SelectorContext) (Selector, error) { func (pc ParseContext) ParseExploreIndex(n ipld.Node) (Selector, error) {
if n.ReprKind() != ipld.ReprKind_Map { if n.ReprKind() != ipld.ReprKind_Map {
return nil, fmt.Errorf("selector spec parse rejected: selector body must be a map") return nil, fmt.Errorf("selector spec parse rejected: selector body must be a map")
} }
...@@ -55,7 +55,7 @@ func ParseExploreIndex(n ipld.Node, selectorContexts ...SelectorContext) (Select ...@@ -55,7 +55,7 @@ func ParseExploreIndex(n ipld.Node, selectorContexts ...SelectorContext) (Select
if err != nil { if err != nil {
return nil, fmt.Errorf("selector spec parse rejected: next field must be present in ExploreIndex selector") return nil, fmt.Errorf("selector spec parse rejected: next field must be present in ExploreIndex selector")
} }
selector, err := ParseSelector(next, selectorContexts...) selector, err := pc.ParseSelector(next)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -14,14 +14,14 @@ func TestParseExploreIndex(t *testing.T) { ...@@ -14,14 +14,14 @@ func TestParseExploreIndex(t *testing.T) {
fnb := fluent.WrapNodeBuilder(ipldfree.NodeBuilder()) // just for the other fixture building fnb := fluent.WrapNodeBuilder(ipldfree.NodeBuilder()) // just for the other fixture building
t.Run("parsing non map node should error", func(t *testing.T) { t.Run("parsing non map node should error", func(t *testing.T) {
sn := fnb.CreateInt(0) sn := fnb.CreateInt(0)
_, err := ParseExploreIndex(sn) _, err := ParseContext{}.ParseExploreIndex(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: selector body must be a map")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: selector body must be a map"))
}) })
t.Run("parsing map node without next field should error", func(t *testing.T) { t.Run("parsing map node without next field should error", func(t *testing.T) {
sn := fnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) { sn := fnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {
mb.Insert(knb.CreateString(indexKey), vnb.CreateInt(2)) mb.Insert(knb.CreateString(indexKey), vnb.CreateInt(2))
}) })
_, err := ParseExploreIndex(sn) _, err := ParseContext{}.ParseExploreIndex(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: next field must be present in ExploreIndex selector")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: next field must be present in ExploreIndex selector"))
}) })
t.Run("parsing map node without index field should error", func(t *testing.T) { t.Run("parsing map node without index field should error", func(t *testing.T) {
...@@ -30,7 +30,7 @@ func TestParseExploreIndex(t *testing.T) { ...@@ -30,7 +30,7 @@ func TestParseExploreIndex(t *testing.T) {
mb.Insert(knb.CreateString(matcherKey), vnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {})) mb.Insert(knb.CreateString(matcherKey), vnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {}))
})) }))
}) })
_, err := ParseExploreIndex(sn) _, err := ParseContext{}.ParseExploreIndex(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: index field must be present in ExploreIndex selector")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: index field must be present in ExploreIndex selector"))
}) })
t.Run("parsing map node with index field that is not an int should error", func(t *testing.T) { t.Run("parsing map node with index field that is not an int should error", func(t *testing.T) {
...@@ -40,7 +40,7 @@ func TestParseExploreIndex(t *testing.T) { ...@@ -40,7 +40,7 @@ func TestParseExploreIndex(t *testing.T) {
mb.Insert(knb.CreateString(matcherKey), vnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {})) mb.Insert(knb.CreateString(matcherKey), vnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {}))
})) }))
}) })
_, err := ParseExploreIndex(sn) _, err := ParseContext{}.ParseExploreIndex(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: index field must be a number in ExploreIndex selector")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: index field must be a number in ExploreIndex selector"))
}) })
t.Run("parsing map node with next field with invalid selector node should return child's error", func(t *testing.T) { t.Run("parsing map node with next field with invalid selector node should return child's error", func(t *testing.T) {
...@@ -48,7 +48,7 @@ func TestParseExploreIndex(t *testing.T) { ...@@ -48,7 +48,7 @@ func TestParseExploreIndex(t *testing.T) {
mb.Insert(knb.CreateString(indexKey), vnb.CreateInt(2)) mb.Insert(knb.CreateString(indexKey), vnb.CreateInt(2))
mb.Insert(knb.CreateString(nextSelectorKey), vnb.CreateInt(0)) mb.Insert(knb.CreateString(nextSelectorKey), vnb.CreateInt(0))
}) })
_, err := ParseExploreIndex(sn) _, err := ParseContext{}.ParseExploreIndex(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: selector is a keyed union and thus must be a map")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: selector is a keyed union and thus must be a map"))
}) })
t.Run("parsing map node with next field with valid selector node should parse", func(t *testing.T) { t.Run("parsing map node with next field with valid selector node should parse", func(t *testing.T) {
...@@ -58,7 +58,7 @@ func TestParseExploreIndex(t *testing.T) { ...@@ -58,7 +58,7 @@ func TestParseExploreIndex(t *testing.T) {
mb.Insert(knb.CreateString(matcherKey), vnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {})) mb.Insert(knb.CreateString(matcherKey), vnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {}))
})) }))
}) })
s, err := ParseExploreIndex(sn) s, err := ParseContext{}.ParseExploreIndex(sn)
Wish(t, err, ShouldEqual, nil) Wish(t, err, ShouldEqual, nil)
Wish(t, s, ShouldEqual, ExploreIndex{Matcher{}, [1]PathSegment{PathSegmentInt{I: 2}}}) Wish(t, s, ShouldEqual, ExploreIndex{Matcher{}, [1]PathSegment{PathSegmentInt{I: 2}}})
}) })
......
...@@ -43,7 +43,7 @@ func (s ExploreRange) Decide(n ipld.Node) bool { ...@@ -43,7 +43,7 @@ func (s ExploreRange) Decide(n ipld.Node) bool {
// ParseExploreRange assembles a Selector // ParseExploreRange assembles a Selector
// from a ExploreRange selector node // from a ExploreRange selector node
func ParseExploreRange(n ipld.Node, selectorContexts ...SelectorContext) (Selector, error) { func (pc ParseContext) ParseExploreRange(n ipld.Node) (Selector, error) {
if n.ReprKind() != ipld.ReprKind_Map { if n.ReprKind() != ipld.ReprKind_Map {
return nil, fmt.Errorf("selector spec parse rejected: selector body must be a map") return nil, fmt.Errorf("selector spec parse rejected: selector body must be a map")
} }
...@@ -70,7 +70,7 @@ func ParseExploreRange(n ipld.Node, selectorContexts ...SelectorContext) (Select ...@@ -70,7 +70,7 @@ func ParseExploreRange(n ipld.Node, selectorContexts ...SelectorContext) (Select
if err != nil { if err != nil {
return nil, fmt.Errorf("selector spec parse rejected: next field must be present in ExploreRange selector") return nil, fmt.Errorf("selector spec parse rejected: next field must be present in ExploreRange selector")
} }
selector, err := ParseSelector(next, selectorContexts...) selector, err := pc.ParseSelector(next)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -14,7 +14,7 @@ func TestParseExploreRange(t *testing.T) { ...@@ -14,7 +14,7 @@ func TestParseExploreRange(t *testing.T) {
fnb := fluent.WrapNodeBuilder(ipldfree.NodeBuilder()) // just for the other fixture building fnb := fluent.WrapNodeBuilder(ipldfree.NodeBuilder()) // just for the other fixture building
t.Run("parsing non map node should error", func(t *testing.T) { t.Run("parsing non map node should error", func(t *testing.T) {
sn := fnb.CreateInt(0) sn := fnb.CreateInt(0)
_, err := ParseExploreRange(sn) _, err := ParseContext{}.ParseExploreRange(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: selector body must be a map")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: selector body must be a map"))
}) })
t.Run("parsing map node without next field should error", func(t *testing.T) { t.Run("parsing map node without next field should error", func(t *testing.T) {
...@@ -22,7 +22,7 @@ func TestParseExploreRange(t *testing.T) { ...@@ -22,7 +22,7 @@ func TestParseExploreRange(t *testing.T) {
mb.Insert(knb.CreateString(startKey), vnb.CreateInt(2)) mb.Insert(knb.CreateString(startKey), vnb.CreateInt(2))
mb.Insert(knb.CreateString(endKey), vnb.CreateInt(3)) mb.Insert(knb.CreateString(endKey), vnb.CreateInt(3))
}) })
_, err := ParseExploreRange(sn) _, err := ParseContext{}.ParseExploreRange(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: next field must be present in ExploreRange selector")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: next field must be present in ExploreRange selector"))
}) })
t.Run("parsing map node without start field should error", func(t *testing.T) { t.Run("parsing map node without start field should error", func(t *testing.T) {
...@@ -32,7 +32,7 @@ func TestParseExploreRange(t *testing.T) { ...@@ -32,7 +32,7 @@ func TestParseExploreRange(t *testing.T) {
mb.Insert(knb.CreateString(matcherKey), vnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {})) mb.Insert(knb.CreateString(matcherKey), vnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {}))
})) }))
}) })
_, err := ParseExploreRange(sn) _, err := ParseContext{}.ParseExploreRange(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: start field must be present in ExploreRange selector")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: start field must be present in ExploreRange selector"))
}) })
t.Run("parsing map node with start field that is not an int should error", func(t *testing.T) { t.Run("parsing map node with start field that is not an int should error", func(t *testing.T) {
...@@ -43,7 +43,7 @@ func TestParseExploreRange(t *testing.T) { ...@@ -43,7 +43,7 @@ func TestParseExploreRange(t *testing.T) {
mb.Insert(knb.CreateString(matcherKey), vnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {})) mb.Insert(knb.CreateString(matcherKey), vnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {}))
})) }))
}) })
_, err := ParseExploreRange(sn) _, err := ParseContext{}.ParseExploreRange(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: start field must be a number in ExploreRange selector")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: start field must be a number in ExploreRange selector"))
}) })
t.Run("parsing map node without end field should error", func(t *testing.T) { t.Run("parsing map node without end field should error", func(t *testing.T) {
...@@ -53,7 +53,7 @@ func TestParseExploreRange(t *testing.T) { ...@@ -53,7 +53,7 @@ func TestParseExploreRange(t *testing.T) {
mb.Insert(knb.CreateString(matcherKey), vnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {})) mb.Insert(knb.CreateString(matcherKey), vnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {}))
})) }))
}) })
_, err := ParseExploreRange(sn) _, err := ParseContext{}.ParseExploreRange(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: end field must be present in ExploreRange selector")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: end field must be present in ExploreRange selector"))
}) })
t.Run("parsing map node with end field that is not an int should error", func(t *testing.T) { t.Run("parsing map node with end field that is not an int should error", func(t *testing.T) {
...@@ -64,7 +64,7 @@ func TestParseExploreRange(t *testing.T) { ...@@ -64,7 +64,7 @@ func TestParseExploreRange(t *testing.T) {
mb.Insert(knb.CreateString(matcherKey), vnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {})) mb.Insert(knb.CreateString(matcherKey), vnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {}))
})) }))
}) })
_, err := ParseExploreRange(sn) _, err := ParseContext{}.ParseExploreRange(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: end field must be a number in ExploreRange selector")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: end field must be a number in ExploreRange selector"))
}) })
t.Run("parsing map node where end is not greater than start should error", func(t *testing.T) { t.Run("parsing map node where end is not greater than start should error", func(t *testing.T) {
...@@ -75,7 +75,7 @@ func TestParseExploreRange(t *testing.T) { ...@@ -75,7 +75,7 @@ func TestParseExploreRange(t *testing.T) {
mb.Insert(knb.CreateString(matcherKey), vnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {})) mb.Insert(knb.CreateString(matcherKey), vnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {}))
})) }))
}) })
_, err := ParseExploreRange(sn) _, err := ParseContext{}.ParseExploreRange(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: end field must be greater than start field in ExploreRange selector")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: end field must be greater than start field in ExploreRange selector"))
}) })
t.Run("parsing map node with next field with invalid selector node should return child's error", func(t *testing.T) { t.Run("parsing map node with next field with invalid selector node should return child's error", func(t *testing.T) {
...@@ -84,7 +84,7 @@ func TestParseExploreRange(t *testing.T) { ...@@ -84,7 +84,7 @@ func TestParseExploreRange(t *testing.T) {
mb.Insert(knb.CreateString(endKey), vnb.CreateInt(3)) mb.Insert(knb.CreateString(endKey), vnb.CreateInt(3))
mb.Insert(knb.CreateString(nextSelectorKey), vnb.CreateInt(0)) mb.Insert(knb.CreateString(nextSelectorKey), vnb.CreateInt(0))
}) })
_, err := ParseExploreRange(sn) _, err := ParseContext{}.ParseExploreRange(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: selector is a keyed union and thus must be a map")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: selector is a keyed union and thus must be a map"))
}) })
...@@ -96,7 +96,7 @@ func TestParseExploreRange(t *testing.T) { ...@@ -96,7 +96,7 @@ func TestParseExploreRange(t *testing.T) {
mb.Insert(knb.CreateString(matcherKey), vnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {})) mb.Insert(knb.CreateString(matcherKey), vnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {}))
})) }))
}) })
s, err := ParseExploreRange(sn) s, err := ParseContext{}.ParseExploreRange(sn)
Wish(t, err, ShouldEqual, nil) Wish(t, err, ShouldEqual, nil)
Wish(t, s, ShouldEqual, ExploreRange{Matcher{}, 2, 3, []PathSegment{PathSegmentInt{I: 2}}}) Wish(t, s, ShouldEqual, ExploreRange{Matcher{}, 2, 3, []PathSegment{PathSegmentInt{I: 2}}})
}) })
......
...@@ -76,7 +76,7 @@ func (erc *exploreRecursiveContext) Link(s Selector) bool { ...@@ -76,7 +76,7 @@ func (erc *exploreRecursiveContext) Link(s Selector) bool {
} }
// ParseExploreRecursive assembles a Selector from a ExploreRecursive selector node // ParseExploreRecursive assembles a Selector from a ExploreRecursive selector node
func ParseExploreRecursive(n ipld.Node, selectorContexts ...SelectorContext) (Selector, error) { func (pc ParseContext) ParseExploreRecursive(n ipld.Node) (Selector, error) {
if n.ReprKind() != ipld.ReprKind_Map { if n.ReprKind() != ipld.ReprKind_Map {
return nil, fmt.Errorf("selector spec parse rejected: selector body must be a map") return nil, fmt.Errorf("selector spec parse rejected: selector body must be a map")
} }
...@@ -94,7 +94,7 @@ func ParseExploreRecursive(n ipld.Node, selectorContexts ...SelectorContext) (Se ...@@ -94,7 +94,7 @@ func ParseExploreRecursive(n ipld.Node, selectorContexts ...SelectorContext) (Se
return nil, fmt.Errorf("selector spec parse rejected: sequence field must be present in ExploreRecursive selector") return nil, fmt.Errorf("selector spec parse rejected: sequence field must be present in ExploreRecursive selector")
} }
erc := &exploreRecursiveContext{} erc := &exploreRecursiveContext{}
selector, err := ParseSelector(sequence, append([]SelectorContext{erc}, selectorContexts...)...) selector, err := pc.PushParent(erc).ParseSelector(sequence)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -33,13 +33,13 @@ func (s ExploreRecursiveEdge) Decide(n ipld.Node) bool { ...@@ -33,13 +33,13 @@ func (s ExploreRecursiveEdge) Decide(n ipld.Node) bool {
// ParseExploreRecursiveEdge assembles a Selector // ParseExploreRecursiveEdge assembles a Selector
// from a exploreRecursiveEdge selector node // from a exploreRecursiveEdge selector node
func ParseExploreRecursiveEdge(n ipld.Node, selectorContexts ...SelectorContext) (Selector, error) { func (pc ParseContext) ParseExploreRecursiveEdge(n ipld.Node) (Selector, error) {
if n.ReprKind() != ipld.ReprKind_Map { if n.ReprKind() != ipld.ReprKind_Map {
return nil, fmt.Errorf("selector spec parse rejected: selector body must be a map") return nil, fmt.Errorf("selector spec parse rejected: selector body must be a map")
} }
s := ExploreRecursiveEdge{} s := ExploreRecursiveEdge{}
for _, selectorContext := range selectorContexts { for _, parent := range pc.parentStack {
if selectorContext.Link(s) { if parent.Link(s) {
return s, nil return s, nil
} }
} }
......
...@@ -15,14 +15,14 @@ func TestParseExploreRecursive(t *testing.T) { ...@@ -15,14 +15,14 @@ func TestParseExploreRecursive(t *testing.T) {
fnb := fluent.WrapNodeBuilder(ipldfree.NodeBuilder()) // just for the other fixture building fnb := fluent.WrapNodeBuilder(ipldfree.NodeBuilder()) // just for the other fixture building
t.Run("parsing non map node should error", func(t *testing.T) { t.Run("parsing non map node should error", func(t *testing.T) {
sn := fnb.CreateInt(0) sn := fnb.CreateInt(0)
_, err := ParseExploreRecursive(sn) _, err := ParseContext{}.ParseExploreRecursive(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: selector body must be a map")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: selector body must be a map"))
}) })
t.Run("parsing map node without sequence field should error", func(t *testing.T) { t.Run("parsing map node without sequence field should error", func(t *testing.T) {
sn := fnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) { sn := fnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {
mb.Insert(knb.CreateString(maxDepthKey), vnb.CreateInt(2)) mb.Insert(knb.CreateString(maxDepthKey), vnb.CreateInt(2))
}) })
_, err := ParseExploreRecursive(sn) _, err := ParseContext{}.ParseExploreRecursive(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: sequence field must be present in ExploreRecursive selector")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: sequence field must be present in ExploreRecursive selector"))
}) })
t.Run("parsing map node without maxDepth field should error", func(t *testing.T) { t.Run("parsing map node without maxDepth field should error", func(t *testing.T) {
...@@ -31,7 +31,7 @@ func TestParseExploreRecursive(t *testing.T) { ...@@ -31,7 +31,7 @@ func TestParseExploreRecursive(t *testing.T) {
mb.Insert(knb.CreateString(matcherKey), vnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {})) mb.Insert(knb.CreateString(matcherKey), vnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {}))
})) }))
}) })
_, err := ParseExploreRecursive(sn) _, err := ParseContext{}.ParseExploreRecursive(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: maxDepth field must be present in ExploreRecursive selector")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: maxDepth field must be present in ExploreRecursive selector"))
}) })
t.Run("parsing map node with maxDepth field that is not an int should error", func(t *testing.T) { t.Run("parsing map node with maxDepth field that is not an int should error", func(t *testing.T) {
...@@ -41,7 +41,7 @@ func TestParseExploreRecursive(t *testing.T) { ...@@ -41,7 +41,7 @@ func TestParseExploreRecursive(t *testing.T) {
mb.Insert(knb.CreateString(matcherKey), vnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {})) mb.Insert(knb.CreateString(matcherKey), vnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {}))
})) }))
}) })
_, err := ParseExploreRecursive(sn) _, err := ParseContext{}.ParseExploreRecursive(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: maxDepth field must be a number in ExploreRecursive selector")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: maxDepth field must be a number in ExploreRecursive selector"))
}) })
t.Run("parsing map node with sequence field with invalid selector node should return child's error", func(t *testing.T) { t.Run("parsing map node with sequence field with invalid selector node should return child's error", func(t *testing.T) {
...@@ -49,7 +49,7 @@ func TestParseExploreRecursive(t *testing.T) { ...@@ -49,7 +49,7 @@ func TestParseExploreRecursive(t *testing.T) {
mb.Insert(knb.CreateString(maxDepthKey), vnb.CreateInt(2)) mb.Insert(knb.CreateString(maxDepthKey), vnb.CreateInt(2))
mb.Insert(knb.CreateString(sequenceKey), vnb.CreateInt(0)) mb.Insert(knb.CreateString(sequenceKey), vnb.CreateInt(0))
}) })
_, err := ParseExploreRecursive(sn) _, err := ParseContext{}.ParseExploreRecursive(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: selector is a keyed union and thus must be a map")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: selector is a keyed union and thus must be a map"))
}) })
t.Run("parsing map node with sequence field with valid selector w/o ExploreRecursiveEdge should not parse", func(t *testing.T) { t.Run("parsing map node with sequence field with valid selector w/o ExploreRecursiveEdge should not parse", func(t *testing.T) {
...@@ -63,12 +63,12 @@ func TestParseExploreRecursive(t *testing.T) { ...@@ -63,12 +63,12 @@ func TestParseExploreRecursive(t *testing.T) {
})) }))
})) }))
}) })
_, err := ParseExploreRecursive(sn) _, err := ParseContext{}.ParseExploreRecursive(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: ExploreRecursive must have at least one ExploreRecursiveEdge")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: ExploreRecursive must have at least one ExploreRecursiveEdge"))
}) })
t.Run("parsing map node that is ExploreRecursiveEdge without ExploreRecursive parent should not parse", func(t *testing.T) { t.Run("parsing map node that is ExploreRecursiveEdge without ExploreRecursive parent should not parse", func(t *testing.T) {
sn := fnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {}) sn := fnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {})
_, err := ParseExploreRecursiveEdge(sn) _, err := ParseContext{}.ParseExploreRecursiveEdge(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: ExploreRecursiveEdge must be beneath ExploreRecursive")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: ExploreRecursiveEdge must be beneath ExploreRecursive"))
}) })
t.Run("parsing map node with sequence field with valid selector node should parse", func(t *testing.T) { t.Run("parsing map node with sequence field with valid selector node should parse", func(t *testing.T) {
...@@ -82,7 +82,7 @@ func TestParseExploreRecursive(t *testing.T) { ...@@ -82,7 +82,7 @@ func TestParseExploreRecursive(t *testing.T) {
})) }))
})) }))
}) })
s, err := ParseExploreRecursive(sn) s, err := ParseContext{}.ParseExploreRecursive(sn)
Wish(t, err, ShouldEqual, nil) Wish(t, err, ShouldEqual, nil)
Wish(t, s, ShouldEqual, ExploreRecursive{ExploreAll{ExploreRecursiveEdge{}}, ExploreAll{ExploreRecursiveEdge{}}, 2}) Wish(t, s, ShouldEqual, ExploreRecursive{ExploreAll{ExploreRecursiveEdge{}}, ExploreAll{ExploreRecursiveEdge{}}, 2})
}) })
......
...@@ -73,7 +73,7 @@ func (s ExploreUnion) Decide(n ipld.Node) bool { ...@@ -73,7 +73,7 @@ func (s ExploreUnion) Decide(n ipld.Node) bool {
// ParseExploreUnion assembles a Selector // ParseExploreUnion assembles a Selector
// from an ExploreUnion selector node // from an ExploreUnion selector node
func ParseExploreUnion(n ipld.Node, selectorContexts ...SelectorContext) (Selector, error) { func (pc ParseContext) ParseExploreUnion(n ipld.Node) (Selector, error) {
if n.ReprKind() != ipld.ReprKind_List { if n.ReprKind() != ipld.ReprKind_List {
return nil, fmt.Errorf("selector spec parse rejected: explore union selector must be a list") return nil, fmt.Errorf("selector spec parse rejected: explore union selector must be a list")
} }
...@@ -85,7 +85,7 @@ func ParseExploreUnion(n ipld.Node, selectorContexts ...SelectorContext) (Select ...@@ -85,7 +85,7 @@ func ParseExploreUnion(n ipld.Node, selectorContexts ...SelectorContext) (Select
if err != nil { if err != nil {
return nil, fmt.Errorf("error during selector spec parse: %s", err) return nil, fmt.Errorf("error during selector spec parse: %s", err)
} }
member, err := ParseSelector(v, selectorContexts...) member, err := pc.ParseSelector(v)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -14,7 +14,7 @@ func TestParseExploreUnion(t *testing.T) { ...@@ -14,7 +14,7 @@ func TestParseExploreUnion(t *testing.T) {
fnb := fluent.WrapNodeBuilder(ipldfree.NodeBuilder()) // just for the other fixture building fnb := fluent.WrapNodeBuilder(ipldfree.NodeBuilder()) // just for the other fixture building
t.Run("parsing non list node should error", func(t *testing.T) { t.Run("parsing non list node should error", func(t *testing.T) {
sn := fnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {}) sn := fnb.CreateMap(func(mb fluent.MapBuilder, knb fluent.NodeBuilder, vnb fluent.NodeBuilder) {})
_, err := ParseExploreUnion(sn) _, err := ParseContext{}.ParseExploreUnion(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: explore union selector must be a list")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: explore union selector must be a list"))
}) })
t.Run("parsing list node where one node is invalid should return child's error", func(t *testing.T) { t.Run("parsing list node where one node is invalid should return child's error", func(t *testing.T) {
...@@ -24,7 +24,7 @@ func TestParseExploreUnion(t *testing.T) { ...@@ -24,7 +24,7 @@ func TestParseExploreUnion(t *testing.T) {
})) }))
lb.Append(vnb.CreateInt(2)) lb.Append(vnb.CreateInt(2))
}) })
_, err := ParseExploreUnion(sn) _, err := ParseContext{}.ParseExploreUnion(sn)
Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: selector is a keyed union and thus must be a map")) Wish(t, err, ShouldEqual, fmt.Errorf("selector spec parse rejected: selector is a keyed union and thus must be a map"))
}) })
...@@ -42,7 +42,7 @@ func TestParseExploreUnion(t *testing.T) { ...@@ -42,7 +42,7 @@ func TestParseExploreUnion(t *testing.T) {
})) }))
})) }))
}) })
s, err := ParseExploreUnion(sn) s, err := ParseContext{}.ParseExploreUnion(sn)
Wish(t, err, ShouldEqual, nil) Wish(t, err, ShouldEqual, nil)
Wish(t, s, ShouldEqual, ExploreUnion{[]Selector{Matcher{}, ExploreIndex{Matcher{}, [1]PathSegment{PathSegmentInt{I: 2}}}}}) Wish(t, s, ShouldEqual, ExploreUnion{[]Selector{Matcher{}, ExploreIndex{Matcher{}, [1]PathSegment{PathSegmentInt{I: 2}}}}})
}) })
......
...@@ -38,7 +38,7 @@ func (s Matcher) Decide(n ipld.Node) bool { ...@@ -38,7 +38,7 @@ func (s Matcher) Decide(n ipld.Node) bool {
// ParseMatcher assembles a Selector // ParseMatcher assembles a Selector
// from a matcher selector node // from a matcher selector node
// TODO: Parse labels and conditions // TODO: Parse labels and conditions
func ParseMatcher(n ipld.Node, selectorContexts ...SelectorContext) (Selector, error) { func (pc ParseContext) ParseMatcher(n ipld.Node) (Selector, error) {
if n.ReprKind() != ipld.ReprKind_Map { if n.ReprKind() != ipld.ReprKind_Map {
return nil, fmt.Errorf("selector spec parse rejected: selector body must be a map") return nil, fmt.Errorf("selector spec parse rejected: selector body must be a map")
} }
......
...@@ -15,12 +15,24 @@ type Selector interface { ...@@ -15,12 +15,24 @@ type Selector interface {
Decide(ipld.Node) bool Decide(ipld.Node) bool
} }
type SelectorContext interface { // ParsedParent is created whenever you are parsing a selector node that may have
// child selectors nodes that need to know it
type ParsedParent interface {
Link(s Selector) bool Link(s Selector) bool
} }
// ParseContext tracks the progress when parsing a selector
type ParseContext struct {
parentStack []ParsedParent
}
// ParseSelector creates a Selector that can be traversed from an IPLD Selector node // ParseSelector creates a Selector that can be traversed from an IPLD Selector node
func ParseSelector(n ipld.Node, selectorContexts ...SelectorContext) (Selector, error) { func ParseSelector(n ipld.Node) (Selector, error) {
return ParseContext{}.ParseSelector(n)
}
// ParseSelector creates a Selector from an IPLD Selector Node with the given context
func (pc ParseContext) ParseSelector(n ipld.Node) (Selector, error) {
if n.ReprKind() != ipld.ReprKind_Map { if n.ReprKind() != ipld.ReprKind_Map {
return nil, fmt.Errorf("selector spec parse rejected: selector is a keyed union and thus must be a map") return nil, fmt.Errorf("selector spec parse rejected: selector is a keyed union and thus must be a map")
} }
...@@ -33,26 +45,35 @@ func ParseSelector(n ipld.Node, selectorContexts ...SelectorContext) (Selector, ...@@ -33,26 +45,35 @@ func ParseSelector(n ipld.Node, selectorContexts ...SelectorContext) (Selector,
// (This switch is where the keyed union discriminators concretely happen.) // (This switch is where the keyed union discriminators concretely happen.)
switch kstr { switch kstr {
case exploreFieldsKey: case exploreFieldsKey:
return ParseExploreFields(v, selectorContexts...) return pc.ParseExploreFields(v)
case exploreAllKey: case exploreAllKey:
return ParseExploreAll(v, selectorContexts...) return pc.ParseExploreAll(v)
case exploreIndexKey: case exploreIndexKey:
return ParseExploreIndex(v, selectorContexts...) return pc.ParseExploreIndex(v)
case exploreRangeKey: case exploreRangeKey:
return ParseExploreRange(v, selectorContexts...) return pc.ParseExploreRange(v)
case exploreUnionKey: case exploreUnionKey:
return ParseExploreUnion(v, selectorContexts...) return pc.ParseExploreUnion(v)
case exploreRecursiveKey: case exploreRecursiveKey:
return ParseExploreRecursive(v, selectorContexts...) return pc.ParseExploreRecursive(v)
case exploreRecursiveEdgeKey: case exploreRecursiveEdgeKey:
return ParseExploreRecursiveEdge(v, selectorContexts...) return pc.ParseExploreRecursiveEdge(v)
case matcherKey: case matcherKey:
return ParseMatcher(v, selectorContexts...) return pc.ParseMatcher(v)
default: default:
return nil, fmt.Errorf("selector spec parse rejected: %q is not a known member of the selector union", kstr) return nil, fmt.Errorf("selector spec parse rejected: %q is not a known member of the selector union", kstr)
} }
} }
// PushParent puts a parent onto the stack of parents for a parse context
func (pc ParseContext) PushParent(parent ParsedParent) ParseContext {
l := len(pc.parentStack)
parents := make([]ParsedParent, 0, l+1)
parents = append(parents, parent)
parents = append(parents, pc.parentStack...)
return ParseContext{parents}
}
// PathSegment can describe either an index in a list or a key in a map, as either int or a string // PathSegment can describe either an index in a list or a key in a map, as either int or a string
type PathSegment interface { type PathSegment interface {
String() string String() string
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment