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
//! Escapes a bare literal line into the engine's always-verbose dialect.
//!
//! The forbidden-regex engine is always in verbose mode, so unescaped whitespace
//! is swallowed and a `#` at a line start begins a comment. A literal rule must
//! therefore be rewritten so every byte matches itself and nothing else: the
//! escapable metacharacters and every whitespace byte gain a leading backslash,
//! and every other byte passes through as a one-byte literal. This is a
//! syntax-boundary transformer (literal text into pattern syntax), so its one job
//! is that the compiled pattern matches exactly the input literal.
/// Reports whether a character must be backslash-escaped in the verbose dialect.
///
/// The set is exactly the bytes the engine's escape parser accepts as a literal
/// byte (`parse_escape`): the metacharacters below plus every ASCII whitespace
/// byte. Every other byte is a plain literal in atom position, so escaping it is
/// unnecessary and (for non-listed bytes) would be an "unsupported escape". The
/// whitespace test uses `is_ascii_whitespace`, matching the engine's own cursor
/// and escape parser (space, tab, newline, form feed, carriage return; not the
/// vertical tab, which the engine treats as a plain literal byte).
/// Escapes one literal line into a verbose-dialect pattern matching it exactly.
///
/// Each escapable metacharacter and whitespace byte gains a leading backslash;
/// every other character (ordinary ASCII, and every byte of a multi-byte UTF-8
/// character, all of which are non-ASCII and never in the escape set) is emitted
/// unchanged. Only ASCII backslashes are inserted, always before an ASCII byte,
/// so the result stays valid UTF-8 without a fallible reassembly step.
///
/// Declared `pub` (not `pub(super)`) so the frx module can re-export it under the
/// `fuzzing` feature for the `fuzz_literal_roundtrip` target; the `rule` module is
/// private, so this never widens the production public surface.
/// Exclusive byte-length ceiling below which a bare literal is matched only at word
/// boundaries.
///
/// A short run of word bytes collides with substrings of longer tokens far more
/// often than a long one: a three-byte run like `ABC` turns up inside base64 blobs,
/// hex dumps, and identifiers by chance, and a bare literal otherwise matches every
/// such coincidence. Gating a short literal on a word boundary at each word-byte end
/// confines it to whole-token matches, while longer literals, which rarely collide,
/// stay plain substring rules. Eight is the smallest ceiling that still treats the
/// common short acronyms as whole words.
const WORD_BOUNDARY_MAX_LEN: usize = 8;
/// The `\b` word-boundary assertion inserted at a word-byte end of a short literal.
const WORD_BOUNDARY: &str = "\\b";
/// Reports whether a byte is an ASCII word byte (`[0-9A-Za-z_]`).
///
/// A `\b` boundary is defined only between a word byte and a non-word byte, so it is
/// meaningful only next to one of these. Every byte of a multi-byte UTF-8 character
/// is non-word, which is why a CJK literal takes no boundary: a `\b` there would
/// assert an ASCII boundary the surrounding CJK text never provides, silencing the
/// rule.
/// Escapes a bare literal, gating a short one behind word boundaries.
///
/// Delegates to [`escape_literal`] for the exact-match body, then, when the literal
/// is under [`WORD_BOUNDARY_MAX_LEN`] bytes, prepends a boundary when its first byte
/// is a word byte and appends one when its last byte is a word byte. So `ABC`
/// compiles to `\bABC\b` and no longer matches inside a base64 run, while a literal
/// ending in a non-word byte (trailing punctuation, or any byte of a CJK character)
/// keeps a plain end there. A literal at or above the ceiling is escaped unchanged.
pub
/// Registers the round-trip and adversarial escaping tests (sidecar, lint-exempt).