UNPKG

2.39 kBJavaScriptView Raw
1/*
2 prefix | delta | note | code
3 ----------|-------|---------------|--------------------------------------------------------------
4 0x00~0x7f | 127 | single buffer | <buffer[0]>
5 0x80~0xb7 | 55 | short buffer | <0x80+length(buffer)>, ...<buffer>
6 0xb8~0xbf | 7 | long buffer | <0xb8+length(length(buffer))>, ...<length(buffer)>, ...<buffer>
7 0xc0~0xf7 | 55 | short array | <0xc0+length(array.bytes)>, ...<array.bytes>
8 0xf8~0xff | 7 | long array | <0xf8+length(length(array.bytes))>, ...<length(array.bytes)>, ...<array.bytes>
9 */
10
11const { Hex } = require('./type');
12
13const SHORT_RANGE = 55;
14const BUFFER_OFFSET = 0x80;
15const ARRAY_OFFSET = 0xc0;
16
17function concat(...args) {
18 return Buffer.concat(args.map(value => {
19 if (Buffer.isBuffer(value)) {
20 return value;
21 }
22
23 if (Number.isInteger(value) && value >= 0) {
24 return Hex.toBuffer(Hex(value));
25 }
26
27 throw new Error(`invalid value, expect unsigned integer or buffer, got ${value}`);
28 }));
29}
30
31// ----------------------------------------------------------------------------
32/**
33 * @param value {Array|Buffer}
34 * @return {Buffer}
35 */
36function encode(value) {
37 if (Buffer.isBuffer(value)) {
38 return encodeBuffer(value);
39 }
40
41 if (Array.isArray(value)) {
42 return encodeArray(value);
43 }
44
45 throw new Error(`invalid value, expect buffer or array, got ${value}`);
46}
47
48/**
49 * @param length {number}
50 * @param offset {number} - Enum of [BUFFER_OFFSET=0x80, ARRAY_OFFSET=0xc0]
51 * @return {Buffer}
52 */
53function encodeLength(length, offset) {
54 if (length <= SHORT_RANGE) {
55 return concat(length + offset);
56 } else {
57 const lengthBuffer = concat(length);
58 return concat(offset + SHORT_RANGE + lengthBuffer.length, lengthBuffer);
59 }
60}
61
62/**
63 * @param buffer {Buffer}
64 * @return {Buffer}
65 */
66function encodeBuffer(buffer) {
67 if (buffer.length === 1 && buffer[0] === 0) {
68 buffer = Buffer.from('');
69 }
70
71 return buffer.length === 1 && buffer[0] < BUFFER_OFFSET
72 ? buffer
73 : concat(encodeLength(buffer.length, BUFFER_OFFSET), buffer);
74}
75
76/**
77 * @param array {Array}
78 * @return {Buffer}
79 */
80function encodeArray(array) {
81 const buffer = concat(...array.map(encode));
82 return concat(encodeLength(buffer.length, ARRAY_OFFSET), buffer);
83}
84
85module.exports = {
86 encode,
87};