(bytes, depth)
| 405 | }; |
| 406 | |
| 407 | let parseProtoMessage = function (bytes, depth) { |
| 408 | let fields = []; |
| 409 | let offset = 0; |
| 410 | |
| 411 | while (offset < bytes.length) { |
| 412 | let key = readProtoVarint(bytes, offset); |
| 413 | offset = key.next; |
| 414 | let fieldNumber = Number(key.value >> 3n); |
| 415 | let wireType = Number(key.value & 7n); |
| 416 | if (!fieldNumber) { |
| 417 | throw new Error('Protobuf 字段号无效'); |
| 418 | } |
| 419 | |
| 420 | let field = { |
| 421 | field: fieldNumber, |
| 422 | wireType, |
| 423 | offset: key.next - 1 |
| 424 | }; |
| 425 | |
| 426 | if (wireType === 0) { |
| 427 | let value = readProtoVarint(bytes, offset); |
| 428 | offset = value.next; |
| 429 | field.type = 'varint'; |
| 430 | field.value = formatProtoInteger(value.value); |
| 431 | } else if (wireType === 1) { |
| 432 | let value = readLittleEndianHex(bytes, offset, 8); |
| 433 | offset = value.next; |
| 434 | field.type = 'fixed64'; |
| 435 | field.rawHex = value.rawHex; |
| 436 | field.littleEndianHex = value.littleEndianHex; |
| 437 | } else if (wireType === 2) { |
| 438 | let lengthInfo = readProtoVarint(bytes, offset); |
| 439 | let length = Number(lengthInfo.value); |
| 440 | offset = lengthInfo.next; |
| 441 | if (!Number.isSafeInteger(length) || offset + length > bytes.length) { |
| 442 | throw new Error('Protobuf length-delimited 字段长度异常'); |
| 443 | } |
| 444 | let valueBytes = bytes.slice(offset, offset + length); |
| 445 | offset += length; |
| 446 | field.type = 'length-delimited'; |
| 447 | field.length = length; |
| 448 | field.rawHex = bytesToHex(valueBytes); |
| 449 | |
| 450 | let text = decodeUtf8Bytes(valueBytes); |
| 451 | if (text) { |
| 452 | field.valueType = 'string'; |
| 453 | field.value = text; |
| 454 | } else if (depth < 4 && valueBytes.length) { |
| 455 | try { |
| 456 | let nested = parseProtoMessage(valueBytes, depth + 1); |
| 457 | field.valueType = 'message'; |
| 458 | field.value = nested; |
| 459 | } catch (e) { |
| 460 | field.valueType = 'bytes'; |
| 461 | field.value = field.rawHex; |
| 462 | } |
| 463 | } else { |
| 464 | field.valueType = 'bytes'; |
no test coverage detected