@juit/qrcode 0.0.0
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.
- package/LICENSE.md +211 -0
- package/NOTICE.md +13 -0
- package/README.md +175 -0
- package/dist/encode.cjs +147 -0
- package/dist/encode.cjs.map +6 -0
- package/dist/encode.d.ts +11 -0
- package/dist/encode.mjs +122 -0
- package/dist/encode.mjs.map +6 -0
- package/dist/images/path.cjs +145 -0
- package/dist/images/path.cjs.map +6 -0
- package/dist/images/path.d.ts +6 -0
- package/dist/images/path.mjs +120 -0
- package/dist/images/path.mjs.map +6 -0
- package/dist/images/pdf.cjs +96 -0
- package/dist/images/pdf.cjs.map +6 -0
- package/dist/images/pdf.d.ts +3 -0
- package/dist/images/pdf.mjs +71 -0
- package/dist/images/pdf.mjs.map +6 -0
- package/dist/images/png.cjs +86 -0
- package/dist/images/png.cjs.map +6 -0
- package/dist/images/png.d.ts +3 -0
- package/dist/images/png.mjs +61 -0
- package/dist/images/png.mjs.map +6 -0
- package/dist/images/svg.cjs +64 -0
- package/dist/images/svg.cjs.map +6 -0
- package/dist/images/svg.d.ts +54 -0
- package/dist/images/svg.mjs +38 -0
- package/dist/images/svg.mjs.map +6 -0
- package/dist/index.cjs +110 -0
- package/dist/index.cjs.map +6 -0
- package/dist/index.d.ts +74 -0
- package/dist/index.mjs +74 -0
- package/dist/index.mjs.map +6 -0
- package/dist/matrix.cjs +360 -0
- package/dist/matrix.cjs.map +6 -0
- package/dist/matrix.d.ts +3 -0
- package/dist/matrix.mjs +335 -0
- package/dist/matrix.mjs.map +6 -0
- package/dist/qrcode.cjs +183 -0
- package/dist/qrcode.cjs.map +6 -0
- package/dist/qrcode.d.ts +20 -0
- package/dist/qrcode.mjs +158 -0
- package/dist/qrcode.mjs.map +6 -0
- package/dist/utils/crc32.cjs +53 -0
- package/dist/utils/crc32.cjs.map +6 -0
- package/dist/utils/crc32.d.ts +9 -0
- package/dist/utils/crc32.mjs +28 -0
- package/dist/utils/crc32.mjs.map +6 -0
- package/dist/utils/dataurl.cjs +35 -0
- package/dist/utils/dataurl.cjs.map +6 -0
- package/dist/utils/dataurl.d.ts +1 -0
- package/dist/utils/dataurl.mjs +10 -0
- package/dist/utils/dataurl.mjs.map +6 -0
- package/dist/utils/deflate.cjs +39 -0
- package/dist/utils/deflate.cjs.map +6 -0
- package/dist/utils/deflate.d.ts +2 -0
- package/dist/utils/deflate.mjs +14 -0
- package/dist/utils/deflate.mjs.map +6 -0
- package/dist/utils/ecc.cjs +93 -0
- package/dist/utils/ecc.cjs.map +6 -0
- package/dist/utils/ecc.d.ts +2 -0
- package/dist/utils/ecc.mjs +68 -0
- package/dist/utils/ecc.mjs.map +6 -0
- package/dist/utils/merge.cjs +41 -0
- package/dist/utils/merge.cjs.map +6 -0
- package/dist/utils/merge.d.ts +2 -0
- package/dist/utils/merge.mjs +16 -0
- package/dist/utils/merge.mjs.map +6 -0
- package/package.json +61 -0
- package/src/encode.ts +180 -0
- package/src/images/path.ts +131 -0
- package/src/images/pdf.ts +76 -0
- package/src/images/png.ts +105 -0
- package/src/images/svg.ts +102 -0
- package/src/index.ts +147 -0
- package/src/matrix.ts +392 -0
- package/src/qrcode.ts +217 -0
- package/src/utils/crc32.ts +50 -0
- package/src/utils/dataurl.ts +7 -0
- package/src/utils/deflate.ts +17 -0
- package/src/utils/ecc.ts +95 -0
- package/src/utils/merge.ts +13 -0
package/src/qrcode.ts
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { calculateEcc } from './utils/ecc'
|
|
2
|
+
|
|
3
|
+
import type { QrCodeMessage } from './encode'
|
|
4
|
+
import type { ECLevel } from './index'
|
|
5
|
+
|
|
6
|
+
/* ========================================================================== *
|
|
7
|
+
* TYPES *
|
|
8
|
+
* ========================================================================== */
|
|
9
|
+
|
|
10
|
+
interface Template {
|
|
11
|
+
readonly version: number,
|
|
12
|
+
readonly ecLevel: ECLevel,
|
|
13
|
+
readonly dataLen: number,
|
|
14
|
+
readonly ecLen: number,
|
|
15
|
+
readonly blockLengths: readonly number[],
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
type Version = {
|
|
19
|
+
readonly [ k in ECLevel ] : Template
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** The internal structure of a QR code */
|
|
23
|
+
export interface QrCodeData {
|
|
24
|
+
/** The version of the QR code (1...40) */
|
|
25
|
+
readonly version: number,
|
|
26
|
+
/** The error correction level for the QR code */
|
|
27
|
+
readonly ecLevel: ECLevel,
|
|
28
|
+
/** The data blocks of the QR code */
|
|
29
|
+
readonly blockData: number[][],
|
|
30
|
+
/** The ECC blocks of the QR code */
|
|
31
|
+
readonly ecData: number[][],
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* ========================================================================== *
|
|
35
|
+
* CONSTANTS *
|
|
36
|
+
* ========================================================================== */
|
|
37
|
+
|
|
38
|
+
// Error correction levels, in order
|
|
39
|
+
const EC_LEVELS = [ 'L', 'M', 'Q', 'H' ] as const
|
|
40
|
+
|
|
41
|
+
// Total number of codewords, (number of ec codewords, number of blocks) * ( L, M, Q, H )
|
|
42
|
+
const CODEWORDS = [
|
|
43
|
+
[ -1, -1, -1, -1, -1, -1, -1, -1, -1 ], // there is no version 0
|
|
44
|
+
[ 26, 7, 1, 10, 1, 13, 1, 17, 1 ],
|
|
45
|
+
[ 44, 10, 1, 16, 1, 22, 1, 28, 1 ],
|
|
46
|
+
[ 70, 15, 1, 26, 1, 36, 2, 44, 2 ],
|
|
47
|
+
[ 100, 20, 1, 36, 2, 52, 2, 64, 4 ],
|
|
48
|
+
[ 134, 26, 1, 48, 2, 72, 4, 88, 4 ], // 5
|
|
49
|
+
[ 172, 36, 2, 64, 4, 96, 4, 112, 4 ],
|
|
50
|
+
[ 196, 40, 2, 72, 4, 108, 6, 130, 5 ],
|
|
51
|
+
[ 242, 48, 2, 88, 4, 132, 6, 156, 6 ],
|
|
52
|
+
[ 292, 60, 2, 110, 5, 160, 8, 192, 8 ],
|
|
53
|
+
[ 346, 72, 4, 130, 5, 192, 8, 224, 8 ], // 10
|
|
54
|
+
[ 404, 80, 4, 150, 5, 224, 8, 264, 11 ],
|
|
55
|
+
[ 466, 96, 4, 176, 8, 260, 10, 308, 11 ],
|
|
56
|
+
[ 532, 104, 4, 198, 9, 288, 12, 352, 16 ],
|
|
57
|
+
[ 581, 120, 4, 216, 9, 320, 16, 384, 16 ],
|
|
58
|
+
[ 655, 132, 6, 240, 10, 360, 12, 432, 18 ], // 15
|
|
59
|
+
[ 733, 144, 6, 280, 10, 408, 17, 480, 16 ],
|
|
60
|
+
[ 815, 168, 6, 308, 11, 448, 16, 532, 19 ],
|
|
61
|
+
[ 901, 180, 6, 338, 13, 504, 18, 588, 21 ],
|
|
62
|
+
[ 991, 196, 7, 364, 14, 546, 21, 650, 25 ],
|
|
63
|
+
[ 1085, 224, 8, 416, 16, 600, 20, 700, 25 ], // 20
|
|
64
|
+
[ 1156, 224, 8, 442, 17, 644, 23, 750, 25 ],
|
|
65
|
+
[ 1258, 252, 9, 476, 17, 690, 23, 816, 34 ],
|
|
66
|
+
[ 1364, 270, 9, 504, 18, 750, 25, 900, 30 ],
|
|
67
|
+
[ 1474, 300, 10, 560, 20, 810, 27, 960, 32 ],
|
|
68
|
+
[ 1588, 312, 12, 588, 21, 870, 29, 1050, 35 ], // 25
|
|
69
|
+
[ 1706, 336, 12, 644, 23, 952, 34, 1110, 37 ],
|
|
70
|
+
[ 1828, 360, 12, 700, 25, 1020, 34, 1200, 40 ],
|
|
71
|
+
[ 1921, 390, 13, 728, 26, 1050, 35, 1260, 42 ],
|
|
72
|
+
[ 2051, 420, 14, 784, 28, 1140, 38, 1350, 45 ],
|
|
73
|
+
[ 2185, 450, 15, 812, 29, 1200, 40, 1440, 48 ], // 30
|
|
74
|
+
[ 2323, 480, 16, 868, 31, 1290, 43, 1530, 51 ],
|
|
75
|
+
[ 2465, 510, 17, 924, 33, 1350, 45, 1620, 54 ],
|
|
76
|
+
[ 2611, 540, 18, 980, 35, 1440, 48, 1710, 57 ],
|
|
77
|
+
[ 2761, 570, 19, 1036, 37, 1530, 51, 1800, 60 ],
|
|
78
|
+
[ 2876, 570, 19, 1064, 38, 1590, 53, 1890, 63 ], // 35
|
|
79
|
+
[ 3034, 600, 20, 1120, 40, 1680, 56, 1980, 66 ],
|
|
80
|
+
[ 3196, 630, 21, 1204, 43, 1770, 59, 2100, 70 ],
|
|
81
|
+
[ 3362, 660, 22, 1260, 45, 1860, 62, 2220, 74 ],
|
|
82
|
+
[ 3532, 720, 24, 1316, 47, 1950, 65, 2310, 77 ],
|
|
83
|
+
[ 3706, 750, 25, 1372, 49, 2040, 68, 2430, 81 ], // 40
|
|
84
|
+
]
|
|
85
|
+
|
|
86
|
+
const VERSIONS: Version[] = CODEWORDS.map((v: number[], index): Version => {
|
|
87
|
+
if (! index) return null as any
|
|
88
|
+
|
|
89
|
+
const res: Record<string, Template> = {}
|
|
90
|
+
for (let i = 1; i < 8; i += 2) {
|
|
91
|
+
const length = v[0]! - v[i]!
|
|
92
|
+
const template = v[i+1]!
|
|
93
|
+
const ecLevel = EC_LEVELS[(i/2)|0]!
|
|
94
|
+
const blocks: number[] = []
|
|
95
|
+
|
|
96
|
+
for (let k = template, n = length; k > 0; k--) {
|
|
97
|
+
const block = (n / k) | 0
|
|
98
|
+
blocks.push(block)
|
|
99
|
+
n -= block
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
res[ecLevel] = {
|
|
103
|
+
version: index,
|
|
104
|
+
ecLevel: ecLevel,
|
|
105
|
+
dataLen: length,
|
|
106
|
+
ecLen: v[i]! / template,
|
|
107
|
+
blockLengths: blocks,
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return res as Version
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
/* ========================================================================== *
|
|
114
|
+
* INTERNALS *
|
|
115
|
+
* ========================================================================== */
|
|
116
|
+
|
|
117
|
+
// Get the template for the specified message and error correction level
|
|
118
|
+
function getTemplate(message: QrCodeMessage, ecLevel: ECLevel): Template {
|
|
119
|
+
let len: number = NaN
|
|
120
|
+
let i = 1
|
|
121
|
+
|
|
122
|
+
if (message.data1) {
|
|
123
|
+
len = Math.ceil(message.data1.length / 8)
|
|
124
|
+
} else {
|
|
125
|
+
i = 10
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
for (/* i */; i < 10; i++) {
|
|
129
|
+
const version = VERSIONS[i]![ecLevel]
|
|
130
|
+
if (version.dataLen >= len) {
|
|
131
|
+
return structuredClone(version)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (message.data10) {
|
|
136
|
+
len = Math.ceil(message.data10.length / 8)
|
|
137
|
+
} else {
|
|
138
|
+
i = 27
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
for (/* i */; i < 27; i++) {
|
|
142
|
+
const version = VERSIONS[i]![ecLevel]
|
|
143
|
+
if (version.dataLen >= len) {
|
|
144
|
+
return structuredClone(version)
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
len = Math.ceil(message.data27.length / 8)
|
|
149
|
+
for (/* i */; i < 41; i++) {
|
|
150
|
+
const version = VERSIONS[i]![ecLevel]
|
|
151
|
+
if (version.dataLen >= len) {
|
|
152
|
+
return structuredClone(version)
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
throw new Error('Too much data to encode in QR code')
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Fill in a template and prepare a QR code
|
|
160
|
+
function fillTemplate(encoded: QrCodeMessage, template: Template): QrCodeData {
|
|
161
|
+
const blocks = new Array<number>(template.dataLen).fill(0)
|
|
162
|
+
|
|
163
|
+
let message: boolean[]
|
|
164
|
+
if (template.version < 10) {
|
|
165
|
+
message = encoded.data1!
|
|
166
|
+
} else if (template.version < 27) {
|
|
167
|
+
message = encoded.data10!
|
|
168
|
+
} else {
|
|
169
|
+
message = encoded.data27!
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const len = message.length
|
|
173
|
+
|
|
174
|
+
for (let i = 0; i < len; i += 8) {
|
|
175
|
+
let b = 0
|
|
176
|
+
for (let j = 0; j < 8; j++) {
|
|
177
|
+
b = (b << 1) | (message[i + j] ? 1 : 0)
|
|
178
|
+
}
|
|
179
|
+
blocks[i / 8] = b
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
let pad = 236
|
|
183
|
+
for (let i = Math.ceil((len + 4) / 8); i < blocks.length; i++) {
|
|
184
|
+
blocks[i] = pad
|
|
185
|
+
pad = (pad == 236) ? 17 : 236
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
let offset = 0
|
|
189
|
+
const ecData: number[][] = []
|
|
190
|
+
const blockData = template.blockLengths.map((n) => {
|
|
191
|
+
const b = blocks.slice(offset, offset + n)
|
|
192
|
+
offset += n
|
|
193
|
+
ecData.push(calculateEcc(b, template.ecLen))
|
|
194
|
+
return b
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
return {
|
|
198
|
+
version: template.version,
|
|
199
|
+
ecLevel: template.ecLevel,
|
|
200
|
+
ecData,
|
|
201
|
+
blockData,
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/* ========================================================================== *
|
|
206
|
+
* EXPORTED *
|
|
207
|
+
* ========================================================================== */
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Create the QR code structure for the given text or binary data.
|
|
211
|
+
*
|
|
212
|
+
* @param data The {@link QrCodeMessage} structure containing the message
|
|
213
|
+
* @param ecLevel The error correction level for the QR code
|
|
214
|
+
*/
|
|
215
|
+
export function generateQrCodeData(data: QrCodeMessage, ecLevel: ECLevel): QrCodeData {
|
|
216
|
+
return fillTemplate(data, getTemplate(data, ecLevel))
|
|
217
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/* ========================================================================== *
|
|
2
|
+
* CONSTANTS *
|
|
3
|
+
* ========================================================================== */
|
|
4
|
+
|
|
5
|
+
// Initialization table for CRC32
|
|
6
|
+
const CRC_TABLE: number[] = (() => {
|
|
7
|
+
const table: number[] = []
|
|
8
|
+
for (let n = 0; n < 256; n++) {
|
|
9
|
+
let c = n
|
|
10
|
+
for (let k = 0; k < 8; k++) {
|
|
11
|
+
if (c & 1) {
|
|
12
|
+
c = 0xedb88320 ^ (c >>> 1)
|
|
13
|
+
} else {
|
|
14
|
+
c = c >>> 1
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
table[n] = c >>> 0
|
|
18
|
+
}
|
|
19
|
+
return table
|
|
20
|
+
})()
|
|
21
|
+
|
|
22
|
+
/* ========================================================================== *
|
|
23
|
+
* EXPORTED *
|
|
24
|
+
* ========================================================================== */
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Calculate the CRC32 checksum for a given `Uint8Array`
|
|
28
|
+
*
|
|
29
|
+
* @param array The `Uint8Array` to use for checksum calculation
|
|
30
|
+
* @param offset The offset in the array to start calculating from
|
|
31
|
+
* @param length The number of bytes to use for calculation, if _negative_
|
|
32
|
+
* this be considered to be relative to the end of the array.
|
|
33
|
+
* */
|
|
34
|
+
export function crc32(
|
|
35
|
+
array: Uint8Array,
|
|
36
|
+
offset: number = 0,
|
|
37
|
+
length?: number,
|
|
38
|
+
): number {
|
|
39
|
+
let crc = -1
|
|
40
|
+
const end =
|
|
41
|
+
length === undefined ? array.length :
|
|
42
|
+
length > 0 ? offset + length :
|
|
43
|
+
array.length + length
|
|
44
|
+
|
|
45
|
+
for (let i = offset; i < end; i ++) {
|
|
46
|
+
crc = CRC_TABLE[(crc ^ array[i]!) & 0x0FF]! ^ (crc >>> 8)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return (crc ^ -1) >>> 0
|
|
50
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export function generateDataUrl(data: string | Uint8Array, mimeType: string): string {
|
|
2
|
+
// Do not use the text decoder here, otherwise UTF8 sequences will be
|
|
3
|
+
// represented in proper characters, and we might loose some data...
|
|
4
|
+
const string = typeof data === 'string' ? data : String.fromCharCode(...data)
|
|
5
|
+
const encoded = btoa(string)
|
|
6
|
+
return `data:${mimeType};base64,${encoded}`
|
|
7
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Compress a Uint8Array using "deflate" */
|
|
2
|
+
export function deflate(data: Uint8Array): Promise<Uint8Array> {
|
|
3
|
+
return new Promise<Uint8Array>((resolve, reject) => {
|
|
4
|
+
const chunks: Uint8Array[] = []
|
|
5
|
+
|
|
6
|
+
const writer = new WritableStream<Uint8Array>({
|
|
7
|
+
write: (chunk) => void chunks.push(chunk),
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
return new Blob([ data ]).stream() // stream the data
|
|
11
|
+
.pipeThrough(new CompressionStream('deflate')) // compress it
|
|
12
|
+
.pipeTo(writer) // write it to our "writer" collecting chungs
|
|
13
|
+
.then(() => new Blob(chunks).arrayBuffer()) // merge the chunks
|
|
14
|
+
.then((buffer) => new Uint8Array(buffer)) // make a new array
|
|
15
|
+
.then(resolve, reject) // resolve or reject
|
|
16
|
+
})
|
|
17
|
+
}
|
package/src/utils/ecc.ts
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/* ========================================================================== *
|
|
2
|
+
* CONSTANTS *
|
|
3
|
+
* ========================================================================== */
|
|
4
|
+
|
|
5
|
+
// Galois Field Math
|
|
6
|
+
const GF256_BASE = 285
|
|
7
|
+
const EXP_TABLE: number[] = [ 1 ]
|
|
8
|
+
const LOG_TABLE: number[] = []
|
|
9
|
+
|
|
10
|
+
// Generator Polynomials
|
|
11
|
+
const POLYNOMIALS = [
|
|
12
|
+
[ 0 ], // a^0 x^0
|
|
13
|
+
[ 0, 0 ], // a^0 x^1 + a^0 x^0
|
|
14
|
+
[ 0, 25, 1 ], // a^0 x^2 + a^25 x^1 + a^1 x^0
|
|
15
|
+
// and so on...
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
// Prepare the exp table
|
|
19
|
+
for (let i = 1; i < 256; i++) {
|
|
20
|
+
let n = EXP_TABLE[i - 1]! << 1
|
|
21
|
+
if (n > 255) n = n ^ GF256_BASE
|
|
22
|
+
EXP_TABLE[i] = n
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Prepare the log table
|
|
26
|
+
for (let i = 0; i < 255; i++) {
|
|
27
|
+
LOG_TABLE[EXP_TABLE[i]!] = i
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* ========================================================================== *
|
|
31
|
+
* INTERNALS *
|
|
32
|
+
* ========================================================================== */
|
|
33
|
+
|
|
34
|
+
// Get the exp for a number
|
|
35
|
+
function exp(k: number): number {
|
|
36
|
+
// coverage ignore next
|
|
37
|
+
while (k < 0) k += 255
|
|
38
|
+
while (k > 255) k -= 255
|
|
39
|
+
return EXP_TABLE[k]!
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Get the log for a number
|
|
43
|
+
function log(k: number): number {
|
|
44
|
+
// coverage ignore next
|
|
45
|
+
if ((k < 0) || (k > 255)) throw new Error(`Bad log(${k})`)
|
|
46
|
+
return LOG_TABLE[k]!
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
// Generate the polynomial up to N (recursively)
|
|
51
|
+
function generatePolynomial(num: number): number[] {
|
|
52
|
+
const poly = POLYNOMIALS[num]
|
|
53
|
+
if (poly) return poly
|
|
54
|
+
|
|
55
|
+
const prev = generatePolynomial(num - 1)
|
|
56
|
+
const res: number[] = []
|
|
57
|
+
|
|
58
|
+
res[0] = prev[0]!
|
|
59
|
+
for (let i = 1; i <= num; i++) {
|
|
60
|
+
res[i] = log(exp(prev[i]!) ^ exp(prev[i - 1]! + num - 1))
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return POLYNOMIALS[num] = res
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/* ========================================================================== *
|
|
67
|
+
* EXPORTED *
|
|
68
|
+
* ========================================================================== */
|
|
69
|
+
|
|
70
|
+
/** Calculate the Error Correction Code (Reed Solomon) for the given data */
|
|
71
|
+
export function calculateEcc(buf: number[], length: number): number[] {
|
|
72
|
+
// `msg` could be array or buffer
|
|
73
|
+
// convert `msg` to array
|
|
74
|
+
const msg = ([] as number[]).slice.call(buf)
|
|
75
|
+
|
|
76
|
+
// Generator Polynomial
|
|
77
|
+
const poly = generatePolynomial(length)
|
|
78
|
+
|
|
79
|
+
// Extend the array...
|
|
80
|
+
for (let i = 0; i < length; i++) msg.push(0)
|
|
81
|
+
|
|
82
|
+
while (msg.length > length) {
|
|
83
|
+
if (!msg[0]) {
|
|
84
|
+
msg.shift()
|
|
85
|
+
continue
|
|
86
|
+
}
|
|
87
|
+
const logK = log(msg[0])
|
|
88
|
+
for (let i = 0; i <= length; i++) {
|
|
89
|
+
msg[i] = msg[i]! ^ exp(poly[i]! + logK)
|
|
90
|
+
}
|
|
91
|
+
msg.shift()
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return msg
|
|
95
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Merge a number of different {@link Uint8Array}s */
|
|
2
|
+
export function mergeArrays(...arrays: Uint8Array[]): Uint8Array {
|
|
3
|
+
const chunks: [ offset: number, array: Uint8Array ][] = []
|
|
4
|
+
|
|
5
|
+
const size = arrays.reduce((size, array) => {
|
|
6
|
+
chunks.push([ size, array ])
|
|
7
|
+
return size + array.length
|
|
8
|
+
}, 0)
|
|
9
|
+
|
|
10
|
+
const result = new Uint8Array(size)
|
|
11
|
+
for (const [ offset, array ] of chunks) result.set(array, offset)
|
|
12
|
+
return result
|
|
13
|
+
}
|