Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 | 571x 571x 167335x 3x 160125x 2x 160123x 3x 160120x 160120x 1419395x 1419395x 1419395x 160120x 3483x 93906x 3482x | import { QRDecodeError } from "../errors";
/**
* Big-endian bit reader over the decoded data codewords.
*
* Bounds violations throw rather than returning zero-filled values: a QR bit
* stream that runs off its end is a corrupt symbol, and silently reading zeros
* turns that into a plausible-looking wrong payload — the exact failure mode
* this package refuses to produce (SPEC decision #11).
*/
export class BitReader {
private position = 0;
constructor(private readonly data: Readonly<Uint8Array>) {}
/** Bits not yet consumed. */
get available(): number {
return this.data.length * 8 - this.position;
}
/** Bits consumed so far — the terminator check needs to know where it is. */
get offset(): number {
return this.position;
}
/**
* Read `count` bits, most significant first.
*
* @throws {QRDecodeError} when fewer than `count` bits remain.
*/
read(count: number): number {
if (count < 0 || count > 32) {
throw new RangeError(`BitReader.read expects 0–32 bits, got ${count}`);
}
if (count > this.available) {
throw new QRDecodeError(
"parse",
`The bit stream ended early: ${count} more bits were requested but only ` +
`${this.available} remain. The symbol is truncated or misread.`,
);
}
let value = 0;
for (let i = 0; i < count; i++) {
const bit = (this.data[this.position >>> 3]! >>> (7 - (this.position & 7))) & 1;
value = (value << 1) | bit;
this.position++;
}
// `<<` is signed 32-bit; a 32-bit read would come back negative without this.
return value >>> 0;
}
/** Read `count` whole bytes. Faster than `read(8)` in a loop, and clearer. */
readBytes(count: number): Uint8Array {
const out = new Uint8Array(count);
for (let i = 0; i < count; i++) out[i] = this.read(8);
return out;
}
}
|