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

     1  package traversal
     2  
     3  import (
     4  	"github.com/ipld/go-ipld-prime/datamodel"
     5  )
     6  
     7  // SelectLinks walks a Node tree and returns a slice of all Links encountered.
     8  // SelectLinks will recurse down into any maps and lists,
     9  // but does not attempt to load any of the links it encounters nor recurse further through them
    10  // (in other words, it's confined to one "block").
    11  //
    12  // SelectLinks only returns the list of links; it does not return any other information
    13  // about them such as position in the tree, etc.
    14  //
    15  // An error may be returned if any of the nodes returns errors during iteration;
    16  // this is generally only possible if one of the Nodes is an ADL,
    17  // and unable to be fully walked because of the inability to load or process some data inside the ADL.
    18  // Nodes already fully in memory should not encounter such errors,
    19  // and it should be safe to ignore errors from this method when used in that situation.
    20  // In case of an error, a partial list will still be returned.
    21  //
    22  // If an identical link is found several times during the walk,
    23  // it is reported several times in the resulting list;
    24  // no deduplication is performed by this method.
    25  func SelectLinks(n datamodel.Node) ([]datamodel.Link, error) {
    26  	var answer []datamodel.Link
    27  	err := accumulateLinks(&answer, n)
    28  	return answer, err
    29  }
    30  
    31  func accumulateLinks(a *[]datamodel.Link, n datamodel.Node) error {
    32  	switch n.Kind() {
    33  	case datamodel.Kind_Map:
    34  		for itr := n.MapIterator(); !itr.Done(); {
    35  			_, v, err := itr.Next()
    36  			if err != nil {
    37  				return err
    38  			}
    39  			accumulateLinks(a, v)
    40  		}
    41  	case datamodel.Kind_List:
    42  		for itr := n.ListIterator(); !itr.Done(); {
    43  			_, v, err := itr.Next()
    44  			if err != nil {
    45  				return err
    46  			}
    47  			accumulateLinks(a, v)
    48  		}
    49  	case datamodel.Kind_Link:
    50  		lnk, _ := n.AsLink()
    51  		*a = append(*a, lnk)
    52  	}
    53  	return nil
    54  }