(state: ParserState)
| 951 | } |
| 952 | |
| 953 | function parseBinary(state: ParserState): BareItem { |
| 954 | if (consume(state) !== ":") { |
| 955 | throw new SyntaxError( |
| 956 | `Invalid structured field: expected ':' at position ${state.pos - 1}`, |
| 957 | ); |
| 958 | } |
| 959 | |
| 960 | const { input } = state; |
| 961 | const startPos = state.pos; |
| 962 | |
| 963 | // Find the closing colon while validating base64 characters |
| 964 | while (state.pos < input.length && input[state.pos] !== ":") { |
| 965 | if (!isBase64Char(input[state.pos]!)) { |
| 966 | throw new SyntaxError( |
| 967 | `Invalid structured field: invalid base64 character at position ${state.pos}`, |
| 968 | ); |
| 969 | } |
| 970 | state.pos++; |
| 971 | } |
| 972 | |
| 973 | if (state.pos >= input.length) { |
| 974 | throw new SyntaxError( |
| 975 | "Invalid structured field: unterminated binary", |
| 976 | ); |
| 977 | } |
| 978 | |
| 979 | const base64 = input.slice(startPos, state.pos); |
| 980 | state.pos++; // consume closing ':' |
| 981 | |
| 982 | try { |
| 983 | const value = decodeBase64(base64); |
| 984 | return { type: "binary", value }; |
| 985 | } catch { |
| 986 | throw new SyntaxError( |
| 987 | "Invalid structured field: invalid base64 encoding", |
| 988 | ); |
| 989 | } |
| 990 | } |
| 991 | |
| 992 | function parseBoolean(state: ParserState): BareItem { |
| 993 | if (consume(state) !== "?") { |
no test coverage detected