This repository has been archived by the owner on Jun 29, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
BitByte.js
158 lines (138 loc) · 3.8 KB
/
BitByte.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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
const BitHelper = require('./BitHelper.js');
/** Class representing a byte. */
class BitByte {
/**
* Create a byte.
* @param {number|number[]|boolean[]} initialData Unsigned byte integer or bits array.
*/
constructor(initialData = [
0, 0, 0, 0, 0, 0, 0, 0,
]) {
if ('[object Number]' === Object.prototype.toString.call(initialData)) {
if (initialData < 0 || initialData > 255)
throw new Error('Argument with type of Number must be in the range of 0 to 255');
this.data = BitHelper.splitByteToBits(initialData);
} else if (
'[object Array]' === Object.prototype.toString.call(initialData)
) {
if (initialData.length > 8)
throw new Error('Argument with type of Array must not have more than 8 elements');
this.data = BitHelper.fitBits(
initialData.map(bit => {
let newBit = +bit;
if (isNaN(newBit))
throw new Error('One of bits you provided is invalid');
return newBit;
})
);
} else
throw new Error('Argument must be an Array of bits or 8-bit unsigned integer');
}
/**
* Change bit on a given offset.
* @param {number} offset Bit offset.
* @param {number|boolean} bit Bit.
* @returns {number} Bit.
*/
setBit(offset, bit) {
BitHelper.checkOffset(offset);
this.data[offset] = !bit ^ true;
return this.data[offset];
}
/**
* Get bit on a given offset.
* @param {number} offset Bit offset.
* @returns {number} Bit.
*/
getBit(offset) {
BitHelper.checkOffset(offset);
return this.data[offset];
}
/**
* Get local storage of bits as an unsigned byte integer.
* @returns {number} Unsigned byte integer.
*/
getByte() {
let { data, } = this,
byte = 0;
for (let i = 0; i < data.length; i++)
byte += data[i] && 2 ** (7 - i);
return byte;
}
/**
* Get local storage of bits as ASCII character.
* @returns {string} ASCII character.
*/
getChar() {
return String.fromCharCode(this);
}
/**
* Get local storage of bits as string.
* @returns {string} String representation of local storage of bits.
*/
toString() {
return this.data.join('');
}
/**
* Get local storage of bits an unsigned byte integer.
* @returns {string} Unsigned byte integer.
*/
valueOf() {
return this.getByte();
}
/**
* Assign array of bits to an instance.
* @param {number[]|boolean[]} bits Bits array.
* @param {number} Assign offset.
* @returns {boolean} Returns true if no errors found.
*/
assign(bits, offset = 0) {
if ('[object Array]' !== Object.prototype.toString.call(bits))
throw new Error('Bits must be an array');
if ('[object Number]' !== Object.prototype.toString.call(offset))
throw new Error('Offset must be a number');
bits.forEach((bit, index) => this.setBit(offset + index, bit));
return true;
}
/**
* Generate bits sequence.
* @yields {number} Next number in the sequence.
*/
*[Symbol.iterator]() {
for (let i = 0; i < 8; i++) {
yield this.getBit(i);
}
}
}
/**
* Get class representing an array of bits with index assign checks.
* @returns {BitByte}
*/
BitByte.safe = function (...args) {
return new Proxy(new BitByte(...args), {
get: function (obj, prop) {
let offset;
if (!((offset = BitHelper.castToInt(prop)) instanceof Error))
BitHelper.checkOffset(offset);
return obj[prop];
},
set: function (obj, prop, value) {
let offset;
if (!((offset = BitHelper.castToInt(prop)) instanceof Error))
BitHelper.checkOffset(offset);
return obj[prop] = value;
},
});
};
for (let i = 0; i < 8; i++) {
Object.defineProperty(BitByte.prototype, i, {
get: function () {
return this.getBit(i);
},
set: function (newBit) {
this.setBit(i, newBit);
},
enumerable: true,
});
}
module.exports = BitByte;