Базовый 3 кусочек энкодера от 1 ошибкиJavascript

Форум по Javascript
Ответить
Anonymous
 Базовый 3 кусочек энкодера от 1 ошибки

Сообщение Anonymous »

Я пытаюсь написать произвольный базовый и кусочек. Это отличается от математического энкодера, где весь буфер преобразуется в целое число, а затем это целое число преобразуется в число. Предполагается, что это так же, как базовая 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.

Подробнее здесь: https://stackoverflow.com/questions/795 ... f-by-1-bug
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Javascript»