github.com/ipld/go-ipld-prime@v0.21.0/traversal/selector/exploreRange.go (about)

     1  package selector
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/ipld/go-ipld-prime/datamodel"
     7  )
     8  
     9  // ExploreRange traverses a list, and for each element in the range specified,
    10  // will apply a next selector to those reached nodes.
    11  type ExploreRange struct {
    12  	next     Selector // selector for element we're interested in
    13  	start    int64
    14  	end      int64
    15  	interest []datamodel.PathSegment // index of element we're interested in
    16  }
    17  
    18  // Interests for ExploreRange are all path segments within the iteration range
    19  func (s ExploreRange) Interests() []datamodel.PathSegment {
    20  	return s.interest
    21  }
    22  
    23  // Explore returns the node's selector if
    24  // the path matches an index in the range of this selector
    25  func (s ExploreRange) Explore(n datamodel.Node, p datamodel.PathSegment) (Selector, error) {
    26  	if n.Kind() != datamodel.Kind_List {
    27  		return nil, nil
    28  	}
    29  	index, err := p.Index()
    30  	if err != nil {
    31  		return nil, nil
    32  	}
    33  	if index < s.start || index >= s.end {
    34  		return nil, nil
    35  	}
    36  	return s.next, nil
    37  }
    38  
    39  // Decide always returns false because this is not a matcher
    40  func (s ExploreRange) Decide(n datamodel.Node) bool {
    41  	return false
    42  }
    43  
    44  // Match always returns false because this is not a matcher
    45  func (s ExploreRange) Match(node datamodel.Node) (datamodel.Node, error) {
    46  	return nil, nil
    47  }
    48  
    49  // ParseExploreRange assembles a Selector
    50  // from a ExploreRange selector node
    51  func (pc ParseContext) ParseExploreRange(n datamodel.Node) (Selector, error) {
    52  	if n.Kind() != datamodel.Kind_Map {
    53  		return nil, fmt.Errorf("selector spec parse rejected: selector body must be a map")
    54  	}
    55  	startNode, err := n.LookupByString(SelectorKey_Start)
    56  	if err != nil {
    57  		return nil, fmt.Errorf("selector spec parse rejected: start field must be present in ExploreRange selector")
    58  	}
    59  	startValue, err := startNode.AsInt()
    60  	if err != nil {
    61  		return nil, fmt.Errorf("selector spec parse rejected: start field must be a number in ExploreRange selector")
    62  	}
    63  	endNode, err := n.LookupByString(SelectorKey_End)
    64  	if err != nil {
    65  		return nil, fmt.Errorf("selector spec parse rejected: end field must be present in ExploreRange selector")
    66  	}
    67  	endValue, err := endNode.AsInt()
    68  	if err != nil {
    69  		return nil, fmt.Errorf("selector spec parse rejected: end field must be a number in ExploreRange selector")
    70  	}
    71  	if startValue >= endValue {
    72  		return nil, fmt.Errorf("selector spec parse rejected: end field must be greater than start field in ExploreRange selector")
    73  	}
    74  	next, err := n.LookupByString(SelectorKey_Next)
    75  	if err != nil {
    76  		return nil, fmt.Errorf("selector spec parse rejected: next field must be present in ExploreRange selector")
    77  	}
    78  	selector, err := pc.ParseSelector(next)
    79  	if err != nil {
    80  		return nil, err
    81  	}
    82  	x := ExploreRange{
    83  		selector,
    84  		startValue,
    85  		endValue,
    86  		make([]datamodel.PathSegment, 0, endValue-startValue),
    87  	}
    88  	for i := startValue; i < endValue; i++ {
    89  		x.interest = append(x.interest, datamodel.PathSegmentOfInt(i))
    90  	}
    91  	return x, nil
    92  }