git ssb

0+

wanderer🌟 / js-dfinity-radix-tree



Tree: 5f264a8c4fc01818ddcc4f9e65ff71122d7935d0

Files: 5f264a8c4fc01818ddcc4f9e65ff71122d7935d0 / treeNode.js

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

Built with git-ssb-web