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 }