arnaucube
arnaucube/arboPublic Self-hosted repository
Add Graphviz generation methods
arnaucube root@arnaucube.com
Sat, 17 Apr 2021 09:33:00 +0200
commit

8ede441191cf083ec847faf243964683ddb7a830

parent

c26b23c544d96eb1ed3a3c9d0e3a65c16fd32295

2 files changed, 83 insertions(+), 1 deletions(-)

jump to
M tree.go → tree.go

@@ -598,6 +598,12 @@ return false, nil

} func (t *Tree) dbGet(k []byte) ([]byte, error) { + // if key is empty, return empty as value + empty := make([]byte, t.hashFunction.Len()) + if bytes.Equal(k, empty) { + return empty, nil + } + v, err := t.db.Get(k) if err == nil { return v, nil

@@ -696,3 +702,76 @@ }

} return nil } + +// Graphviz iterates across the full tree to generate a string Graphviz +// representation of the tree and writes it to w +func (t *Tree) Graphviz(w io.Writer, rootKey []byte) error { + fmt.Fprintf(w, `digraph hierarchy { +node [fontname=Monospace,fontsize=10,shape=box] +`) + nChars := 4 + nEmpties := 0 + empty := make([]byte, t.hashFunction.Len()) + err := t.Iterate(func(k, v []byte) { + switch v[0] { + case PrefixValueEmpty: + case PrefixValueLeaf: + fmt.Fprintf(w, "\"%v\" [style=filled];\n", hex.EncodeToString(k[:nChars])) + // key & value from the leaf + kB, vB := readLeafValue(v) + fmt.Fprintf(w, "\"%v\" -> {\"k:%v\\nv:%v\"}\n", + hex.EncodeToString(k[:nChars]), hex.EncodeToString(kB[:nChars]), + hex.EncodeToString(vB[:nChars])) + fmt.Fprintf(w, "\"k:%v\\nv:%v\" [style=dashed]\n", + hex.EncodeToString(kB[:nChars]), hex.EncodeToString(vB[:nChars])) + case PrefixValueIntermediate: + l, r := readIntermediateChilds(v) + lStr := hex.EncodeToString(l[:nChars]) + rStr := hex.EncodeToString(r[:nChars]) + eStr := "" + if bytes.Equal(l, empty) { + lStr = fmt.Sprintf("empty%v", nEmpties) + eStr += fmt.Sprintf("\"%v\" [style=dashed,label=0];\n", + lStr) + nEmpties++ + } + if bytes.Equal(r, empty) { + rStr = fmt.Sprintf("empty%v", nEmpties) + eStr += fmt.Sprintf("\"%v\" [style=dashed,label=0];\n", + rStr) + nEmpties++ + } + fmt.Fprintf(w, "\"%v\" -> {\"%v\" \"%v\"}\n", hex.EncodeToString(k[:nChars]), + lStr, rStr) + fmt.Fprint(w, eStr) + default: + } + }) + fmt.Fprintf(w, "}\n") + return err +} + +// PrintGraphviz prints the output of Tree.Graphviz +func (t *Tree) PrintGraphviz(rootKey []byte) error { + if rootKey == nil { + rootKey = t.Root() + } + w := bytes.NewBufferString("") + fmt.Fprintf(w, + "--------\nGraphviz of the Tree with Root "+hex.EncodeToString(rootKey)+":\n") + err := t.Graphviz(w, nil) + if err != nil { + fmt.Println(w) + return err + } + fmt.Fprintf(w, + "End of Graphviz of the Tree with Root "+hex.EncodeToString(rootKey)+"\n--------\n") + + fmt.Println(w) + return nil +} + +// Purge WIP: unimplemented +func (t *Tree) Purge(keys [][]byte) error { + return nil +}
M tree_test.go → tree_test.go

@@ -195,7 +195,7 @@ c.Check(gettedValue, qt.DeepEquals, v)

c.Check(gettedValue, qt.DeepEquals, BigIntToBytes(big.NewInt(11))) } -func TestAux(t *testing.T) { // TMP +func TestAux(t *testing.T) { // TODO split in proper tests c := qt.New(t) tree, err := NewTree(memory.NewMemoryStorage(), 100, HashFunctionPoseidon) c.Assert(err, qt.IsNil)

@@ -219,6 +219,9 @@ c.Assert(err, qt.IsNil)

k = BigIntToBytes(big.NewInt(int64(770))) err = tree.Add(k, v) c.Assert(err, qt.IsNil) + // + // err = tree.PrintGraphviz(nil) + // c.Assert(err, qt.IsNil) } func TestGet(t *testing.T) {