git ssb

0+

wanderer🌟 / js-dfinity-radix-tree



Tree: 6b34c4eb25f5a0d003d2f5a603b19ae91bf6b375

Files: 6b34c4eb25f5a0d003d2f5a603b19ae91bf6b375 / treeNode.js

2926 bytesRaw
1const leb128 = require('leb128').unsigned
2const LebStream = require('leb128/stream')
3const Uint1Array = require('uint1array')
4const HASH_LEN = 20
5
6function toTypedArray (array) {
7 return new Uint1Array(new Uint8Array(array).buffer)
8}
9
10// helper functions for nodes
11const EXTENSION = exports.EXTENSION = 0
12const LBRANCH = exports.LBRANCH = 1
13const RBRANCH = exports.RBRANCH = 2
14const VALUE = exports.VALUE = 3
15
16exports.setBranch = function (node, branch) {
17 node['/'][LBRANCH] = branch[0]
18 node['/'][RBRANCH] = branch[1]
19}
20
21exports.getBranch = function (node) {
22 return node['/'].slice(LBRANCH, LBRANCH + 2)
23}
24
25exports.getValue = function (node) {
26 return node['/'][VALUE]
27}
28
29exports.deleteValue = function (node) {
30 delete node['/'][VALUE]
31}
32
33exports.getExtension = function (node) {
34 if (node['/'][EXTENSION]) {
35 const len = node['/'][EXTENSION][0]
36 const extension = toTypedArray(node['/'][EXTENSION][1])
37 return extension.subarray(0, len)
38 } else {
39 return []
40 }
41}
42
43exports.setExtension = function (node, ex) {
44 if (ex && ex.length) {
45 node['/'][EXTENSION] = [ex.length, Buffer.from(ex.buffer)]
46 } else {
47 delete node['/'][EXTENSION]
48 }
49}
50
51exports.setValue = function (node, val) {
52 node['/'][VALUE] = val
53}
54
55exports.isEmpty = function (node) {
56 const branch = exports.getBranch(node)
57 return !node['/'][EXTENSION] && !branch[0] && !branch[1] && node['/'][VALUE] === undefined
58}
59
60// PREFIX := | LBP | RBP | EXT | LB | RB | VALUE |
61// NODE := | PREFIX | LEN | PAYLOAD
62const MASK = {
63 EXTENSION: 8,
64 LBRANCH: 4,
65 RBRANCH: 2,
66 VALUE: 1
67}
68
69exports.encode = function (node, prefix = 0, encodeLen = false) {
70 let encoded = []
71 const ext = node[EXTENSION]
72 if (ext) {
73 const len = leb128.encode(ext[0])
74 encoded.push(len)
75 encoded.push(ext[1])
76 prefix += MASK.EXTENSION
77 }
78
79 const lb = node[LBRANCH]
80 if (lb) {
81 encoded.push(lb['/'])
82 prefix += MASK.LBRANCH
83 }
84
85 const rb = node[RBRANCH]
86 if (rb) {
87 encoded.push(rb['/'])
88 prefix += MASK.RBRANCH
89 }
90
91 const val = node[VALUE]
92 if (val !== undefined) {
93 encoded.push(val)
94 prefix += MASK.VALUE
95 }
96
97 encoded.unshift(Buffer.from([prefix]))
98 encoded = Buffer.concat(encoded)
99 if (encodeLen) {
100 const len = leb128.encode(encoded.length)
101 encoded = Buffer.concat([len, encoded])
102 }
103 return encoded
104}
105
106exports.decode = function (val) {
107 const node = [null, null, null]
108 const prefix = val[0]
109 const lebStream = new LebStream(val.slice(1))
110
111 if (prefix & MASK.EXTENSION) {
112 const len = Number(leb128.read(lebStream))
113 const ext = lebStream.read(Math.ceil(len / 8))
114 node[EXTENSION] = [len, ext]
115 }
116
117 if (prefix & MASK.LBRANCH) {
118 node[LBRANCH] = {
119 '/': lebStream.read(HASH_LEN)
120 }
121 }
122
123 if (prefix & MASK.RBRANCH) {
124 node[RBRANCH] = {
125 '/': lebStream.read(HASH_LEN)
126 }
127 }
128
129 if (prefix & MASK.VALUE) {
130 node[VALUE] = lebStream.buffer
131 }
132 return node
133}
134

Built with git-ssb-web