# `range/range-strict-frame.ts` ## Purpose `parseRangeLine` is the per-line framer used by `streamParseRangeBody`. It enforces the documented Pwned Passwords line shape (`/^[0-9A-F]{35}:[0-9]+$/`) in strict mode, throwing `HIBP.MALFORMED_RESPONSE` with the offending line index on any deviation. In off-mode it accepts lowercase hex, defaults an unparseable count to `0`, and still rejects structurally broken lines (missing colon, wrong suffix length, non-hex characters). ## Features - Strict mode default — uppercase hex, single colon, decimal count. - Off mode tolerant of lowercase hex and unparseable counts (defaults to `0`), still rejecting non-hex suffixes or wrong lengths. - Throws carry `context.lineIndex` so callers can surface a precise diagnostic. - Pure synchronous function — no allocations beyond the returned `{ suffix, count }` record. ## Usage: Basic Example ```ts import { parseRangeLine } from "@suaveplan/hibp"; const { suffix, count } = parseRangeLine(rawLine, 0, true); ``` ## Usage: Advanced Example ```ts import { HibpError, parseRangeLine } from "@suaveplan/hibp"; function parseTolerant(lines: string[]): Array<{ suffix: string; count: number }> { const out: Array<{ suffix: string; count: number }> = []; for (let i = 0; i < lines.length; i++) { try { out.push(parseRangeLine(lines[i] as string, i, false)); } catch (err) { if (err instanceof HibpError) continue; throw err; } } return out; } ``` ## API Reference - `RangeLine` — `{ suffix: string; count: number }`. - `parseRangeLine(raw, lineIndex, strict): RangeLine` — throws `HibpError(HIBP.MALFORMED_RESPONSE)` on rejection. ## Implementation Notes The strict pattern uses a tight regex check before the colon split so mismatches are rejected before any allocation. Off-mode counts default to `0` rather than `NaN` so consumers can rely on integer semantics throughout. The function avoids `try`/`catch` internally — every branch is explicit so a future contributor can reason about the failure paths without tracing exception flow. Strict mode is the default because the documented Pwned Passwords contract is precise; opting out should be a deliberate operational decision, not the silent fallback.