-
Notifications
You must be signed in to change notification settings - Fork 1
/
base-256.js
94 lines (74 loc) · 1.95 KB
/
base-256.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
88
89
90
91
92
93
94
const { leftShift, rightShift } = require('./shift-operators')
const decode = ( buf, offset = 0 ) => {
if (!Buffer.isBuffer(buf)) {
throw new TypeError('decode only accepts buffer.')
}
var num = 0
if (buf.length > 0 && (buf[offset]&0x80) != 0) {
var byte = 0x00
if (!!(buf[0]&0x40) != 0) {
byte = 0xff
}
for (var i = 0; i < (buf.length-offset); i++) {
var c = buf[i + offset]
c ^= byte
if (i === 0) {
c &= 0x7f
}
if (Math.abs(num) > (Number.MAX_SAFE_INTEGER - Math.pow(2, 8))) {
throw new TypeError('Result out of range.')
}
num = (leftShift(num, 8)) + c
}
if (byte === 0xff) {
throwIfOutOfRange(num)
num += 1
return -num
}
throwIfOutOfRange(num)
return num
}
return num
}
const throwIfOutOfRange = n => {
if (n < Number.MIN_SAFE_INTEGER || n > Number.MAX_SAFE_INTEGER) {
throw new TypeError('Result out of range.')
}
}
const encode = (buf, num) => {
if (!Buffer.isBuffer(buf)) {
throw new TypeError('encode expects first parameter to be buffer.')
}
num = Number(num)
if (isNaN(num) || (!Number.isInteger(num))) {
throw new TypeError('encode expects second parameter to be integer.')
}
if (!isEncodable(num)) {
throw new TypeError('number should be between range -9007199254740991 to 9007199254740991.')
}
const buflen = buf.length
var bufPointer = buflen - 1
if (fitsInBase256(buflen, num)) {
for (var i = buflen - 1; i >= 0; i--) {
const byte = num & 0xFF
buf[bufPointer--] = byte
num = rightShift(num, 8)
}
buf[0] |= 0x80
}
}
const isEncodable = num => {
return (num > Number.MIN_SAFE_INTEGER && num < Number.MAX_SAFE_INTEGER)
}
const fitsInBase256 = (buflength, num) => {
var binBits = (buflength -1) * 8
return buflength >= 9 ||
(
(num >= (leftShift(-1, binBits))) &&
(num < (leftShift(1, binBits)))
)
}
module.exports = {
decode,
encode
}