(tag, b, len)
| 365 | return res; |
| 366 | } |
| 367 | static decodeTag(tag, b, len) { |
| 368 | let res; |
| 369 | if ((tag >> 6) == 2) { // context specific class |
| 370 | // just get a content |
| 371 | return b.getChunk(len); |
| 372 | } |
| 373 | if (tag & 0x20) { // construct type |
| 374 | let seq = [], r; |
| 375 | if (len < 0) { |
| 376 | while (r = this._decode(b)) |
| 377 | seq.push(r); |
| 378 | } |
| 379 | else { |
| 380 | let endOffset = b.i + len; |
| 381 | while (b.i < endOffset && (r = this._decode(b))) |
| 382 | seq.push(r); |
| 383 | } |
| 384 | return seq; |
| 385 | } |
| 386 | // universal class |
| 387 | if (len < 0) |
| 388 | throw new Error("BER: no unspecific length"); |
| 389 | switch (tag) { |
| 390 | case 0x01: // boolean |
| 391 | if (len != 1) |
| 392 | throw new Error(); |
| 393 | res = b.getc() != 0; |
| 394 | break; |
| 395 | case 0x02: // integer |
| 396 | if (b.peek() & 0x80) { |
| 397 | const c = b.getChunk(len).slice(); // copy. cannot modify source data. |
| 398 | for (let i = 0; i < c.length; i++) // could use Logical.not |
| 399 | c[i] = ~c[i]; |
| 400 | res = BigInt.fromArrayBuffer(c.buffer) + 1n; |
| 401 | res = -res; |
| 402 | } |
| 403 | else { |
| 404 | let chunk = b.getChunk(len); |
| 405 | const offset = chunk.byteOffset; |
| 406 | chunk = chunk.buffer.slice(offset, offset + chunk.byteLength); |
| 407 | res = BigInt.fromArrayBuffer(chunk); |
| 408 | } |
| 409 | break; |
| 410 | case 0x03: {// bit string |
| 411 | let pad = b.getc(); |
| 412 | if (pad == 0) { |
| 413 | res = [b.getChunk(len - 1), (len - 1) * 8]; |
| 414 | } |
| 415 | else { |
| 416 | let c = Uint8Array(len - 1); |
| 417 | for (let i = 0; i < len - 1; i++) |
| 418 | c[i] = b.getc() >>> pad; |
| 419 | res = [c, (len - 1) * 8 - pad]; |
| 420 | } |
| 421 | } |
| 422 | break; |
| 423 | case 0x04: // octet string |
| 424 | res = b.getChunk(len); |
no test coverage detected