Module drag_file

Module drag_file 

Source
Expand description

Cleanroom parser for the .drg drag-curve text file format (MBA-1409).

.drg is a small vendor text format used to distribute Doppler-radar-measured drag-coefficient-vs-Mach curves for individual bullets (e.g. Lapua’s free downloads for QuickTARGET Unlimited). This module was written from publicly observable file structure only — line layout, field separators, and column semantics inferred by inspecting one real vendor sample locally for grammar-pinning purposes (see the task report for structural findings). No vendor drag-coefficient data is embedded here: every fixture in this module’s tests is synthetic, invented content.

Shared by the CLI (main.rs) and the WASM terminal (wasm.rs); lives in the library crate — not gated behind any feature — so it compiles for wasm32-unknown-unknown. This module is fs-free: it parses an in-memory &str, never touches std::fs. File I/O (reading the path the user gave --drag-table, or the WASM text-ingestion glue) stays in the caller.

§Grammar (tolerant superset covering the vendor layout and plain two-column CSV)

  • Zero or more leading non-data lines (title/header/blank/comment) are skipped until the first line that parses as exactly two finite numbers. The first non-empty skipped line (trimmed) is captured as ParsedDragCurve::name; if the very first line in the file is itself a data row (headerless CSV), name is None.
  • From that point on, every non-blank line must parse as exactly two finite numbers — garbage after data has started is a hard error, not silently skipped.
  • Fields are separated by a run of whitespace (space or tab — real vendor files use tab) or by a single ,/; delimiter.
  • Columns may appear as (mach, cd) or (cd, mach). Column detection: if exactly one column is strictly ascending across every row, that column is mach (this is not merely a defensive fallback — some real vendor files use (cd, mach) column order, so this detection is load-bearing). If both columns ascend — e.g. a (cd, mach) file whose cd happens to be monotonic across a subsonic-only deck — the column with the larger maximum value is mach: mach spans past 1.0 in real decks, while cd stays well under 1.5. If the two maxima are within 20% of each other, that’s too close to call, and parsing fails with a dedicated “ambiguous columns” error rather than silently guessing. If neither column ascends, parsing fails with a dedicated error naming the problem.
  • The decimal separator is . only. A line is only flagged as the decimal-comma error if it splits into exactly two tokens and both look like decimal-comma numbers (e.g. "0,5 0,3"); this produces a dedicated error naming the problem, rather than a generic parse failure or a comma-CSV misread. A line where only one token looks like a decimal-comma number — e.g. a header line mixing prose and a comma-formatted number such as "Density 1,225" — is not treated as this error; it is simply skipped like ordinary header text.
  • Row count must be in 2..=4096 (4096 matches ffi::MAX_FFI_DRAG_TABLE_LEN, the cap already enforced on the array-based FFI drag-table entry point).
  • mach must be finite and >= 0 (the real vendor sample’s first row is exactly mach = 0); cd must be finite and > 0.

Structs§

ParsedDragCurve
A drag curve parsed from .drg text: an optional vendor-supplied name/description and the (mach, cd) points in ascending-mach order.

Functions§

looks_like_drg
Cheap sniff: does text look like .drg (or headerless two-column CSV of the same shape)? Finds the first two data rows and checks that one of the two columns is ascending between them — a bounded scan that does not allocate the full points vector (unlike calling parse_drg and checking is_ok()), so it’s cheap to use as a pre-check before committing to a full parse.
parse_drg
Parses .drg drag-curve text into a ParsedDragCurve. See the module docs for the full tolerance contract. On any violation, returns Err(String) naming the offending line number (1-indexed) and the problem.