(state: ParserState)
| 790 | } |
| 791 | |
| 792 | function parseIntegerOrDecimal(state: ParserState): BareItem { |
| 793 | const { input } = state; |
| 794 | let sign = 1; |
| 795 | if (peek(state) === "-") { |
| 796 | state.pos++; |
| 797 | sign = -1; |
| 798 | } |
| 799 | |
| 800 | if (!isDigit(peek(state))) { |
| 801 | throw new SyntaxError( |
| 802 | `Invalid structured field: expected digit at position ${state.pos}`, |
| 803 | ); |
| 804 | } |
| 805 | |
| 806 | const intStart = state.pos; |
| 807 | while (isDigit(peek(state))) { |
| 808 | state.pos++; |
| 809 | } |
| 810 | const intLen = state.pos - intStart; |
| 811 | if (intLen > MAX_INTEGER_DIGITS) { |
| 812 | throw new SyntaxError( |
| 813 | "Invalid structured field: integer too long", |
| 814 | ); |
| 815 | } |
| 816 | |
| 817 | if (peek(state) === ".") { |
| 818 | state.pos++; // consume '.' |
| 819 | if (intLen > MAX_DECIMAL_INTEGER_DIGITS) { |
| 820 | throw new SyntaxError( |
| 821 | "Invalid structured field: decimal integer part too long", |
| 822 | ); |
| 823 | } |
| 824 | |
| 825 | const fracStart = state.pos; |
| 826 | while (isDigit(peek(state))) { |
| 827 | state.pos++; |
| 828 | } |
| 829 | const fracLen = state.pos - fracStart; |
| 830 | if (fracLen > MAX_DECIMAL_FRACTIONAL_DIGITS) { |
| 831 | throw new SyntaxError( |
| 832 | "Invalid structured field: decimal fractional part too long", |
| 833 | ); |
| 834 | } |
| 835 | |
| 836 | if (fracLen === 0) { |
| 837 | throw new SyntaxError( |
| 838 | "Invalid structured field: decimal requires fractional digits", |
| 839 | ); |
| 840 | } |
| 841 | |
| 842 | const value = sign * parseFloat(input.slice(intStart, state.pos)); |
| 843 | return { type: "decimal", value }; |
| 844 | } |
| 845 | |
| 846 | const value = sign * parseInt(input.slice(intStart, state.pos), 10); |
| 847 | |
| 848 | if (value < -MAX_INTEGER || value > MAX_INTEGER) { |
| 849 | throw new SyntaxError( |
no test coverage detected