github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/dt/walk.go (about)

     1  // Copyright 2020 the u-root Authors. All rights reserved
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package dt
     6  
     7  import (
     8  	"fmt"
     9  )
    10  
    11  // NodeWalk is used to contain state for walking
    12  // the FDT, such as an error. A Walk with a non-nil
    13  // error value can not proceed. Many walks will start
    14  // with a root, but it is possible to Walk to a node,
    15  // make a copy of the Walk, and in that way do multiple
    16  // Walks from that one node. This is very similar to how
    17  // 9p clients walk 9p servers.
    18  type NodeWalk struct {
    19  	n   *Node
    20  	err error
    21  }
    22  
    23  // AsString returns the NodeWalk Name and error as a string.
    24  func (nq *NodeWalk) AsString() (string, error) {
    25  	if nq.err != nil {
    26  		return "", nq.err
    27  	}
    28  	return nq.n.Name, nil
    29  }
    30  
    31  // ListChildNodes returns a string array with the Names of each child Node
    32  func (nq *NodeWalk) ListChildNodes() ([]string, error) {
    33  	if nq.err != nil {
    34  		return nil, nq.err
    35  	}
    36  
    37  	cs := make([]string, len(nq.n.Children))
    38  	for i := range nq.n.Children {
    39  		cs[i] = nq.n.Children[i].Name
    40  	}
    41  	return cs, nil
    42  }
    43  
    44  // Root returns the Root node from an FDT to start the walk.
    45  func (fdt *FDT) Root() *NodeWalk {
    46  	return &NodeWalk{n: fdt.RootNode}
    47  }
    48  
    49  // Walk walks from a node to a named Node, returning a NodeWalk.
    50  func (nq *NodeWalk) Walk(name string) *NodeWalk {
    51  	if nq.err != nil {
    52  		return nq
    53  	}
    54  	for _, n := range nq.n.Children {
    55  		if n.Name == name {
    56  			return &NodeWalk{n: n}
    57  		}
    58  	}
    59  	return &NodeWalk{err: fmt.Errorf("cannot find node name %q", name)}
    60  }
    61  
    62  // Find returns a Node given a matching function starting at the current
    63  // NodeWalk.
    64  func (nq *NodeWalk) Find(f func(*Node) bool) (*Node, error) {
    65  	if nq.err != nil {
    66  		return nil, nq.err
    67  	}
    68  	if matching, ok := nq.n.Find(f); ok {
    69  		return matching, nil
    70  	}
    71  	return nil, fmt.Errorf("cannot find node with matching pattern")
    72  }
    73  
    74  // FindAll returns all Nodes given a matching function starting at the current
    75  // NodeWalk.
    76  func (nq *NodeWalk) FindAll(f func(*Node) bool) ([]*Node, error) {
    77  	if nq.err != nil {
    78  		return nil, nq.err
    79  	}
    80  	if matching, ok := nq.n.FindAll(f); ok {
    81  		return matching, nil
    82  	}
    83  	return nil, fmt.Errorf("cannot find nodes with matching pattern")
    84  }
    85  
    86  // Property walks from a Node to a Property of that Node, returning a PropertyWalk.
    87  func (nq *NodeWalk) Property(name string) *PropertyWalk {
    88  	if nq.err != nil {
    89  		return &PropertyWalk{err: nq.err}
    90  	}
    91  	for _, p := range nq.n.Properties {
    92  		if p.Name == name {
    93  			return &PropertyWalk{p: &p}
    94  		}
    95  	}
    96  	return &PropertyWalk{err: fmt.Errorf("cannot find property name %q", name)}
    97  }
    98  
    99  // PropertyWalk contains the state from a Walk
   100  // to a Property.
   101  type PropertyWalk struct {
   102  	p   *Property
   103  	err error
   104  }
   105  
   106  // AsU64 returns the PropertyWalk value as a uint64.
   107  func (pq *PropertyWalk) AsU64() (uint64, error) {
   108  	if pq.err != nil {
   109  		return 0, pq.err
   110  	}
   111  	return pq.p.AsU64()
   112  }
   113  
   114  // AsString returns the PropertyWalk value as a string.
   115  func (pq *PropertyWalk) AsString() (string, error) {
   116  	if pq.err != nil {
   117  		return "", pq.err
   118  	}
   119  	return pq.p.AsString()
   120  }
   121  
   122  // AsBytes returns the PropertyWalk value as a []byte.
   123  func (pq *PropertyWalk) AsBytes() ([]byte, error) {
   124  	if pq.err != nil {
   125  		return nil, pq.err
   126  	}
   127  	return pq.p.Value, nil
   128  }