Я пытаюсь написать произвольный базовый и кусочек. Это отличается от математического энкодера, где весь буфер преобразуется в целое число, а затем это целое число преобразуется в число. Предполагается, что это так же, как базовая 64 считывает буфер в кусках 3 байтов и выходов 4 Chars Per Chunk. 0,683 бита, потому что 3 ** 61 = 96,68 и 12*8 = 96, поэтому 0,683 бита останутся неиспользованными. < /P>
Как это выглядит: < /p>
expect(base3encoder.encode([0,0,0,0,0,0,0,0,0,0,0,1])).toBe('0000000000000000000000000000000000000000000000000000000000001')
expect(base3encoder.encode([0,0,0,0,0,0,0,0,0,0,0,2])).toBe('0000000000000000000000000000000000000000000000000000000000002')
expect(base3encoder.encode([0,0,0,0,0,0,0,0,0,0,0,3])).toBe('0000000000000000000000000000000000000000000000000000000000010')
expect(base3encoder.encode([0,0,0,0,0,0,0,0,0,0,1,0]),"256 = 1*3**5 + 1*3**2 + 1*3**1 + 1*3**0").toBe('0000000000000000000000000000000000000000000000000000000100111')
< /code>
Когда ввод не равен 12 байтов, мы должны добавить немного прокладки. Я полагаю, что ошибка в chunkedbufferencoder.decode
, но это может быть в chunkedbufferencoder.encode . Я знаю, что Encode работает для входных байтов, которые имеют множество 12 (как показано выше), но для чего -либо еще он становится немного сумасшедшим. Это в настоящее время проходит все тесты и должно продолжать проходить. < /P>
Где ошибка?
function getView(buffer) {
if (ArrayBuffer.isView(buffer)) {
return new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
}
if (buffer instanceof ArrayBuffer) {
return new DataView(buffer, buffer.byteLength, buffer.byteLength);
}
return new DataView(Uint8Array.from(buffer).buffer);
}
function bufToInt(buffer) {
if (buffer.length = 8) {
let i = 0;
let result = 0n;
const view = getView(buffer);
const end = buffer.length - 8;
for (;;) {
result |= BigInt(view.getBigUint64(i, false));
i += 8;
if (i >= end) {
break;
}
result = 2 ** (8 * bytesPerChunk));
}
}
encode(arr) {
if (!arr?.length) {
return "";
}
const buf = Uint8Array.from(arr);
let i = 0;
let result = "";
do {
const chunk = buf.slice(i, i + this.bytesPerChunk);
let val = bufToInt(chunk);
if (chunk.length < this.bytesPerChunk) {
const missingBytes = this.bytesPerChunk - chunk.length;
val = 0; j--) {
out.push(Number(num >> BigInt(8 * j) & 0xffn));
}
} else {
const missing = this.charsPerChunk - chunk.length;
let num = this.arrToInt(this.padEnd(chunk));
num >>= BigInt(8 * missing);
const byteCount = this.bytesPerChunk - missing;
for (let j = byteCount - 1; j >= 0; --j) {
out.push(Number(num >> BigInt(8 * j) & 0xffn));
}
break;
}
i += chunk.length;
}
return new Uint8Array(out);
}
arrToInt(arr) {
let num = 0n;
for (const ch of arr) {
num = num * this.base + this.reverse.get(ch);
}
return num;
}
strToInt(str) {
return this.arrToInt(toArray(str));
}
intToStr(num) {
if (!num) {
return this.alphabet[0].repeat(this.charsPerChunk);
}
let n = BigInt(num);
let result = "";
do {
const rem = n % this.base;
result = this.alphabet[Number(rem)] + result;
n /= this.base;
} while (n > 0n);
return result.padStart(this.charsPerChunk, this.alphabet[0]);
}
intToArr(num) {
if (!num) {
return Array(this.charsPerChunk).fill(this.alphabet[0]);
}
let n = BigInt(num);
let result = [];
do {
const rem = n % this.base;
result.unshift(this.alphabet[Number(rem)]);
n /= this.base;
} while (n > 0n);
while (result.length < this.charsPerChunk) {
result.unshift(this.alphabet[0]);
}
return result;
}
}
// ---------- TEST ----------
function randomUint8Array(minLen, maxLen) {
return crypto.getRandomValues(new Uint8Array(Math.floor(Math.random() * (maxLen - minLen + 1)) + minLen))
}
const base64encoder = new ChunkedBufferEncoder('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',3)
const base3encoder = new ChunkedBufferEncoder('012', 12, 61)
const NUM_TESTS = 10000
const MIN_BYTES = 1
const MAX_BYTES = 17
function arrEq(a, b) {
if (a.length !== b.length) return false;
for (let i = 0; i < a.length; i++) {
if (a[i] !== b[i]) return false;
}
return true;
}
function uint8ArrayToHex(arr) {
return Array.from(arr, b => b.toString(16).toUpperCase().padStart(2, '0')).join(' ')
}
for(const encoder of [base64encoder,base3encoder]) {
for(let i = 0; i < NUM_TESTS; i++) {
const buf = randomUint8Array(MIN_BYTES, MAX_BYTES)
const encoded = encoder.encode(buf)
const decoded = encoder.decode(encoded)
if(!arrEq(buf, decoded)) throw new Error(
`Buf: ${uint8ArrayToHex(buf)} Encoded: ${encoded} Decoded: ${uint8ArrayToHex(decoded)}`
)
}
}< /code>
< /div>
< /div>
< /p>
Это может быть .slice (0, -MissingBytes) < /code>.[0,0,0,0,0,0,0,0,0,0,1]
(11 элементов) должны быть подготовлены таким образом, чтобы он становился [0,0,0,0,0,0,0,0,0,0,0,1,000] , который кодирует 000000000000000000000000000000000000000000000000010011 , но когда он снова выйдет [0,0,0,0,0,0,0,0,0,0,0,1,0] с добавлением «отсутствующего байта». Я этого не хочу. BASE64 использует = в качестве прокладки, но это не на самом деле необходимо, потому что вы можете выяснить, сколько байтов/ChARS он должен быть с небольшим количеством математики. Я на самом деле не позитивен, если можно сделать что -то подобное с неваты 2.
Я пытаюсь написать произвольный базовый и кусочек. Это отличается от математического энкодера, где весь буфер преобразуется в целое число, а затем это целое число преобразуется в число. Предполагается, что это так же, как базовая 64 считывает буфер в кусках 3 байтов и выходов 4 Chars Per Chunk. 0,683 бита, потому что 3 ** 61 = 96,68 и 12*8 = 96, поэтому 0,683 бита останутся неиспользованными. < /P> Как это выглядит: < /p> [code]expect(base3encoder.encode([0,0,0,0,0,0,0,0,0,0,0,1])).toBe('0000000000000000000000000000000000000000000000000000000000001') expect(base3encoder.encode([0,0,0,0,0,0,0,0,0,0,0,2])).toBe('0000000000000000000000000000000000000000000000000000000000002') expect(base3encoder.encode([0,0,0,0,0,0,0,0,0,0,0,3])).toBe('0000000000000000000000000000000000000000000000000000000000010') expect(base3encoder.encode([0,0,0,0,0,0,0,0,0,0,1,0]),"256 = 1*3**5 + 1*3**2 + 1*3**1 + 1*3**0").toBe('0000000000000000000000000000000000000000000000000000000100111') < /code> Когда ввод не равен 12 байтов, мы должны добавить немного прокладки. Я полагаю, что ошибка в chunkedbufferencoder.decode [/code], но это может быть в chunkedbufferencoder.encode . Я знаю, что Encode работает для входных байтов, которые имеют множество 12 (как показано выше), но для чего -либо еще он становится немного сумасшедшим. Это в настоящее время проходит все тесты и должно продолжать проходить. < /P> Где ошибка?[code]function getView(buffer) { if (ArrayBuffer.isView(buffer)) { return new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength); } if (buffer instanceof ArrayBuffer) { return new DataView(buffer, buffer.byteLength, buffer.byteLength); } return new DataView(Uint8Array.from(buffer).buffer); }
function bufToInt(buffer) { if (buffer.length = 8) { let i = 0; let result = 0n; const view = getView(buffer); const end = buffer.length - 8; for (;;) { result |= BigInt(view.getBigUint64(i, false)); i += 8; if (i >= end) { break; } result = 2 ** (8 * bytesPerChunk)); } } encode(arr) { if (!arr?.length) { return ""; } const buf = Uint8Array.from(arr); let i = 0; let result = ""; do { const chunk = buf.slice(i, i + this.bytesPerChunk); let val = bufToInt(chunk); if (chunk.length < this.bytesPerChunk) { const missingBytes = this.bytesPerChunk - chunk.length; val = 0; j--) { out.push(Number(num >> BigInt(8 * j) & 0xffn)); } } else { const missing = this.charsPerChunk - chunk.length; let num = this.arrToInt(this.padEnd(chunk)); num >>= BigInt(8 * missing); const byteCount = this.bytesPerChunk - missing; for (let j = byteCount - 1; j >= 0; --j) { out.push(Number(num >> BigInt(8 * j) & 0xffn)); } break; } i += chunk.length; } return new Uint8Array(out); } arrToInt(arr) { let num = 0n; for (const ch of arr) { num = num * this.base + this.reverse.get(ch); } return num; } strToInt(str) { return this.arrToInt(toArray(str)); } intToStr(num) { if (!num) { return this.alphabet[0].repeat(this.charsPerChunk); } let n = BigInt(num); let result = ""; do { const rem = n % this.base; result = this.alphabet[Number(rem)] + result; n /= this.base; } while (n > 0n); return result.padStart(this.charsPerChunk, this.alphabet[0]); } intToArr(num) { if (!num) { return Array(this.charsPerChunk).fill(this.alphabet[0]); } let n = BigInt(num); let result = []; do { const rem = n % this.base; result.unshift(this.alphabet[Number(rem)]); n /= this.base; } while (n > 0n); while (result.length < this.charsPerChunk) { result.unshift(this.alphabet[0]); } return result; } }
Это может быть .slice (0, -MissingBytes) < /code>.[0,0,0,0,0,0,0,0,0,0,1][/code] (11 элементов) должны быть подготовлены таким образом, чтобы он становился [0,0,0,0,0,0,0,0,0,0,0,1,000] , который кодирует 000000000000000000000000000000000000000000000000010011 , но когда он снова выйдет [0,0,0,0,0,0,0,0,0,0,0,1,0] с добавлением «отсутствующего байта». Я этого не хочу. BASE64 использует = в качестве прокладки, но это не на самом деле необходимо, потому что вы можете выяснить, сколько байтов/ChARS он должен быть с небольшим количеством математики. Я на самом деле не позитивен, если можно сделать что -то подобное с неваты 2.