hypercore-storage 0.0.26 → 0.0.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,105 @@
1
1
  const { ASSERTION } = require('hypercore-errors')
2
+ const { Readable, isEnded, getStreamError } = require('streamx')
2
3
 
3
4
  const TipList = require('./tip-list')
4
5
 
6
+ class OverlayStream extends Readable {
7
+ constructor (tip, storage, createStream, opts = {}) {
8
+ super()
9
+
10
+ this.tip = tip
11
+ this.storage = storage
12
+ this.options = opts
13
+
14
+ this._reverse = !!opts.reverse
15
+ this._active = null
16
+ this._position = this._reverse ? tip.length() - 1 : tip.offset
17
+
18
+ this._createStream = createStream
19
+ this._pendingDestroy = null
20
+
21
+ if (!opts.reverse) this._makeActiveStream()
22
+ }
23
+
24
+ _predestroy () {
25
+ if (this._active) this._active.destroy()
26
+ }
27
+
28
+ _read (cb) {
29
+ if (this._active === null) {
30
+ if (this._yield()) {
31
+ cb(null)
32
+ return
33
+ }
34
+ }
35
+
36
+ if (this._active) {
37
+ this._active.resume()
38
+ }
39
+
40
+ cb(null)
41
+ }
42
+
43
+ _yield () {
44
+ while (this._memoryRemaining()) {
45
+ const { valid, value } = this.tip.get(this._position)
46
+ const index = this._nextIndex()
47
+
48
+ if (!valid) continue
49
+ if (!this.push({ index, page: value })) break
50
+ }
51
+
52
+ return this._onmemorydrain()
53
+ }
54
+
55
+ _nextIndex () {
56
+ if (this._reverse) return this._position--
57
+ return this._position++
58
+ }
59
+
60
+ _memoryRemaining () {
61
+ if (this._reverse) return this._position >= this.tip.offset
62
+ return this._position < this.tip.length()
63
+ }
64
+
65
+ _onmemorydrain () {
66
+ if (!this._reverse) {
67
+ this.push(null)
68
+ return true
69
+ }
70
+
71
+ this._makeActiveStream()
72
+
73
+ return false
74
+ }
75
+
76
+ _makeActiveStream () {
77
+ this._active = this._createStream(this.storage, this.options)
78
+ this._active.on('error', noop) // handled in onclose
79
+ this._active.on('close', this._onclose.bind(this))
80
+ this._active.on('data', this._ondata.bind(this))
81
+ }
82
+
83
+ _ondata (data) {
84
+ if (!this.push(data)) this._active.pause()
85
+ }
86
+
87
+ _onclose () {
88
+ if (!isEnded(this._active)) {
89
+ const error = getStreamError(this._active)
90
+ this.destroy(error)
91
+ return
92
+ }
93
+
94
+ if (this._reverse) {
95
+ this.push(null)
96
+ return
97
+ }
98
+
99
+ this._yield()
100
+ }
101
+ }
102
+
5
103
  class MemoryOverlay {
6
104
  constructor (storage) {
7
105
  this.storage = storage
@@ -24,7 +122,27 @@ class MemoryOverlay {
24
122
  }
25
123
 
26
124
  snapshot () {
27
- todo()
125
+ const snap = new MemoryOverlay(this.storage.snapshot())
126
+ snap.merge(this)
127
+
128
+ if (this.userData !== null) snap.userData = new Map()
129
+ if (this.blocks !== null) snap.blocks = new TipList()
130
+ if (this.treeNodes !== null) snap.treeNodes = new Map()
131
+ if (this.bitfields !== null) snap.bitfields = new TipList()
132
+
133
+ // clone state
134
+ if (this.head !== null) snap.head = Object.assign(this.head)
135
+ if (this.auth !== null) snap.auth = Object.assign(this.auth)
136
+ if (this.localKeyPair !== null) snap.localKeyPair = Object.assign(this.localKeyPair)
137
+ if (this.encryptionKey !== null) snap.encryptionKey = Object.assign(this.encryptionKey)
138
+ if (this.dataDependency !== null) snap.dataDependency = Object.assign(this.dataDependency)
139
+ if (this.dataInfo !== null) snap.dataInfo = Object.assign(this.dataInfo)
140
+ if (this.userData !== null) snap.userData = mergeMap(snap.userData, this.userData)
141
+ if (this.blocks !== null) snap.blocks = mergeTip(snap.blocks, this.blocks)
142
+ if (this.treeNodes !== null) snap.treeNodes = mergeMap(snap.treeNodes, this.treeNodes)
143
+ if (this.bitfields !== null) snap.bitfields = mergeTip(snap.bitfields, this.bitfields)
144
+
145
+ return snap
28
146
  }
29
147
 
30
148
  get dependencies () {
@@ -56,8 +174,8 @@ class MemoryOverlay {
56
174
  todo()
57
175
  }
58
176
 
59
- createBitfieldPageStream () {
60
- todo()
177
+ createBitfieldPageStream (opts) {
178
+ return new OverlayStream(this.bitfields, this.storage, createBitfieldPageStream, opts)
61
179
  }
62
180
 
63
181
  async peekLastTreeNode () {
@@ -266,6 +384,10 @@ class MemoryOverlayWriteBatch {
266
384
  }
267
385
  }
268
386
 
387
+ function createBitfieldPageStream (storage, opts) {
388
+ return storage.createBitfieldPageStream(opts)
389
+ }
390
+
269
391
  function mergeMap (a, b) {
270
392
  if (a === null) return b
271
393
  for (const [key, value] of b) a.set(key, value)
@@ -278,6 +400,8 @@ function mergeTip (a, b) {
278
400
  return a
279
401
  }
280
402
 
403
+ function noop () {}
404
+
281
405
  function todo () {
282
406
  throw ASSERTION('Not supported yet, but will be')
283
407
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hypercore-storage",
3
- "version": "0.0.26",
3
+ "version": "0.0.28",
4
4
  "main": "index.js",
5
5
  "files": [
6
6
  "index.js",