-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathencoder.js
87 lines (66 loc) · 1.66 KB
/
encoder.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
const { Transform } = require('streamx')
const bint = require('bint8array')
class Encode extends Transform {
constructor () {
super()
}
error (msg) {
if (typeof msg === 'string') return this.error(bint.fromString(msg))
this.push(this.format(msg, true))
}
_transform (data, cb) {
cb(null, this.format(data))
}
_destroy (cb) {
cb()
}
format (data, error = false) {
const frame = new Uint8Array(3)
const view = new DataView(frame.buffer, frame.byteOffset)
// error flag
if (error) view.setUint8(0, 0xff)
view.setUint16(1, data.length, true)
return bint.concat([frame, data])
}
}
class Decode extends Transform {
constructor () {
super()
this._readingFrame = true
this._missing = 3 // 2 bytes
this._buffered = null
}
_transform (data, cb) {
let err = 0
while (data.byteLength > 0) {
if (this._buffered) {
data = bint.concat([this._buffered, data])
this._buffered = null
}
if (data.byteLength < this._missing) {
this._buffered = data
return cb()
}
if (this._readingFrame) {
this._readingFrame = false
const view = new DataView(data.buffer, data.byteOffset)
err |= view.getUint8(0)
this._missing = view.getUint16(1, true)
data = data.slice(3)
continue
}
const message = data.slice(0, this._missing)
data = data.slice(this._missing)
this._missing = 3
this._readingFrame = true
// handle error
if (err !== 0) return cb(new Error(bint.toString(message)))
this.push(message)
}
cb(null)
}
}
module.exports = {
Encode,
Decode
}