|
@ -1,8 +1,15 @@ |
|
|
|
|
|
// Package arbo > vt.go implements the Virtual Tree, which computes a tree
|
|
|
|
|
|
// without computing any hash. With the idea of once all the leafs are placed in
|
|
|
|
|
|
// their positions, the hashes can be computed, avoiding computing a node hash
|
|
|
|
|
|
// more than one time.
|
|
|
|
|
|
//nolint:unused,deadcode
|
|
|
package arbo |
|
|
package arbo |
|
|
|
|
|
|
|
|
import ( |
|
|
import ( |
|
|
"bytes" |
|
|
"bytes" |
|
|
|
|
|
"encoding/hex" |
|
|
"fmt" |
|
|
"fmt" |
|
|
|
|
|
"io" |
|
|
) |
|
|
) |
|
|
|
|
|
|
|
|
type node struct { |
|
|
type node struct { |
|
@ -11,7 +18,7 @@ type node struct { |
|
|
k []byte |
|
|
k []byte |
|
|
v []byte |
|
|
v []byte |
|
|
path []bool |
|
|
path []bool |
|
|
h []byte |
|
|
|
|
|
|
|
|
// h []byte
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
type params struct { |
|
|
type params struct { |
|
@ -177,3 +184,87 @@ func (n *node) downUntilDivergence(p *params, currLvl int, oldLeaf, newLeaf *nod |
|
|
func (n *node) computeHashes() ([]kv, error) { |
|
|
func (n *node) computeHashes() ([]kv, error) { |
|
|
return nil, nil |
|
|
return nil, nil |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (t *vt) graphviz(w io.Writer) error { |
|
|
|
|
|
fmt.Fprintf(w, `digraph hierarchy { |
|
|
|
|
|
node [fontname=Monospace,fontsize=10,shape=box] |
|
|
|
|
|
`) |
|
|
|
|
|
if _, err := t.root.graphviz(w, t.params, 0); err != nil { |
|
|
|
|
|
return err |
|
|
|
|
|
} |
|
|
|
|
|
fmt.Fprintf(w, "}\n") |
|
|
|
|
|
return nil |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (n *node) graphviz(w io.Writer, p *params, nEmpties int) (int, error) { |
|
|
|
|
|
nChars := 4 // TODO move to global constant
|
|
|
|
|
|
if n == nil { |
|
|
|
|
|
return nEmpties, nil |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
t := n.typ() |
|
|
|
|
|
switch t { |
|
|
|
|
|
case vtLeaf: |
|
|
|
|
|
leafKey, _, err := newLeafValue(p.hashFunction, n.k, n.v) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nEmpties, err |
|
|
|
|
|
} |
|
|
|
|
|
fmt.Fprintf(w, "\"%p\" [style=filled,label=\"%v\"];\n", n, hex.EncodeToString(leafKey[:nChars])) |
|
|
|
|
|
|
|
|
|
|
|
fmt.Fprintf(w, "\"%p\" -> {\"k:%v\\nv:%v\"}\n", n, |
|
|
|
|
|
hex.EncodeToString(n.k[:nChars]), |
|
|
|
|
|
hex.EncodeToString(n.v[:nChars])) |
|
|
|
|
|
fmt.Fprintf(w, "\"k:%v\\nv:%v\" [style=dashed]\n", |
|
|
|
|
|
hex.EncodeToString(n.k[:nChars]), |
|
|
|
|
|
hex.EncodeToString(n.v[:nChars])) |
|
|
|
|
|
case vtMid: |
|
|
|
|
|
fmt.Fprintf(w, "\"%p\" [label=\"\"];\n", n) |
|
|
|
|
|
|
|
|
|
|
|
lStr := fmt.Sprintf("%p", n.l) |
|
|
|
|
|
rStr := fmt.Sprintf("%p", n.r) |
|
|
|
|
|
eStr := "" |
|
|
|
|
|
if n.l == nil { |
|
|
|
|
|
lStr = fmt.Sprintf("empty%v", nEmpties) |
|
|
|
|
|
eStr += fmt.Sprintf("\"%v\" [style=dashed,label=0];\n", |
|
|
|
|
|
lStr) |
|
|
|
|
|
nEmpties++ |
|
|
|
|
|
} |
|
|
|
|
|
if n.r == nil { |
|
|
|
|
|
rStr = fmt.Sprintf("empty%v", nEmpties) |
|
|
|
|
|
eStr += fmt.Sprintf("\"%v\" [style=dashed,label=0];\n", |
|
|
|
|
|
rStr) |
|
|
|
|
|
nEmpties++ |
|
|
|
|
|
} |
|
|
|
|
|
fmt.Fprintf(w, "\"%p\" -> {\"%v\" \"%v\"}\n", n, lStr, rStr) |
|
|
|
|
|
fmt.Fprint(w, eStr) |
|
|
|
|
|
nEmpties, err := n.l.graphviz(w, p, nEmpties) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nEmpties, err |
|
|
|
|
|
} |
|
|
|
|
|
nEmpties, err = n.r.graphviz(w, p, nEmpties) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nEmpties, err |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
case vtEmpty: |
|
|
|
|
|
default: |
|
|
|
|
|
return nEmpties, fmt.Errorf("ERR") |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return nEmpties, nil |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (t *vt) printGraphviz() error { |
|
|
|
|
|
w := bytes.NewBufferString("") |
|
|
|
|
|
fmt.Fprintf(w, |
|
|
|
|
|
"--------\nGraphviz:\n") |
|
|
|
|
|
err := t.graphviz(w) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
fmt.Println(w) |
|
|
|
|
|
return err |
|
|
|
|
|
} |
|
|
|
|
|
fmt.Fprintf(w, |
|
|
|
|
|
"End of Graphviz --------\n") |
|
|
|
|
|
fmt.Println(w) |
|
|
|
|
|
return nil |
|
|
|
|
|
} |