1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//! Autodetects the rule-file format and parses it into engine-ready patterns.
//!
//! A leading UTF-8 BOM is stripped once. The first significant line (after blank
//! and `#`-comment lines) then selects the format: a strict `==> name <==` header
//! routes the whole file through the tail-format parser in the sibling `sections`
//! module, and any other shape routes the whole file through the legacy line-based
//! path here, which parses byte-for-byte as before. One file never mixes formats.
//!
//! The legacy path treats a blank or `#`-comment line as a skip, a `/PATTERN/FLAGS`
//! line whose trailing run is all ASCII-lowercase as a regex rule (with `m`/`x`
//! accepted as no-ops and any other flag a hard fail-closed error), and every other
//! non-blank line as a bare literal escaped into the verbose dialect, short ones
//! gated behind word boundaries. That single-line classification is shared with a
//! one-significant-line tail-format section, so both keep the incumbent two forms.
/// Imports the redacted load-error type reported on a bad flag or empty source.
use LoadError;
/// Imports the literal-to-dialect compiler (escaping plus short-literal boundary
/// gating) for bare literal lines.
use literal_pattern;
/// Imports the tail-format detector, parser, and the shared parsed-rule type.
use ;
/// The UTF-8 byte-order-mark code point, stripped from the start of a source.
const BOM: char = '\u{FEFF}';
/// Strips a leading UTF-8 BOM, returning the remaining source unchanged.
/// Reports whether a line contributes a rule: non-blank and not a `#`-comment.
///
/// Shared by the legacy line scan, tail-format autodetection, and tail-format body
/// significance counting, so every layer agrees on which lines are meaningful. The
/// test trims first, so an indented `#` line counts as a comment too, matching the
/// engine's always-verbose comment handling.
pub
/// Reports the first flag letter outside the `{m, x}` no-op set, if any.
///
/// `m` (multiline) and `x` (verbose) are always on in the engine, so they are
/// dropped as no-ops. Any other letter would change match semantics if silently
/// dropped (an `i` or `s`), so the caller fails the load closed on it.
/// Compiles one significant line into its engine pattern by the incumbent two forms.
///
/// A regex line needs at least two delimiting slashes, a closing slash past the
/// opening one, and a trailing run that is entirely ASCII-lowercase (an empty run
/// counts); its `m`/`x` flags drop as no-ops and any other flag fails closed with a
/// redacted error at `index`. Any other shape, including a slashed line whose
/// trailing run is not all-lowercase, is a bare literal escaped into the verbose
/// dialect and short-literal boundary-gated. The caller guarantees `line` is
/// significant, so there is no skip case here.
pub
/// Parses a legacy line-based source into unnamed, engine-ready rules.
///
/// Each significant line is classified by the two-form rule, its 0-based position
/// among the kept rules becoming the opaque index a bad flag reports. Returns
/// `NoRules` when no rule line survives, and carries `None` as every rule's name
/// because the legacy format has no section identity.
/// Parses a rule source into named, engine-ready rules, autodetecting the format.
///
/// Strips a leading BOM, then routes on the first significant line: a strict header
/// parses the whole file as tail-format sections (every rule named), otherwise the
/// whole file parses as the legacy line-based format unchanged (every rule unnamed).
/// The names drive finding identity (`rule=<name>`); the patterns feed the engine.
/// Every error is redacted, carrying only an opaque index or a source line number,
/// never rule text.
pub
/// Parses a rule source into the engine-ready pattern list, dropping rule names.
///
/// A projection over [`parse_rules`] for the format and compile tests, which
/// assert against the bare `Vec<String>` pattern shape; production callers all
/// need the names, so this exists only in test builds.
pub
/// Registers the format, flags-policy, and BOM-strip tests (sidecar, lint-exempt).