Skip to main content

zsh/ported/zle/
compctl_h.rs

1//! `compctl.h` port — completion descriptor types + `CC_*` / `CCT_*`
2//! flag constants used by the legacy `compctl` builtin.
3//!
4//! Port of `Src/Zle/compctl.h`. Canonical home for the four typedefs
5//! (`Compctlp`/`Compctl`/`Compcond`/`Patcomp`) and the two flag-bit
6//! families: 30 `CC_*` primary completion-target flags (mask) and 7
7//! `CC_*` secondary flags (mask2), plus 14 `CCT_*` `-x` condition
8//! types.
9//!
10//! C source: 4 typedefs + 4 structs (`compctlp`, `patcomp`,
11//! `compcond`, `compctl`), 14 `CCT_*` constants (c:76-89), 30
12//! primary `CC_*` constants (c:118-149), 7 secondary `CC_*` constants
13//! (c:152-158). 0 functions.
14//!
15//! `compctl.rs` (the .c port) re-exports these via `pub use
16//! super::compctl_h::*;` so existing `cc_flags::FILES` / `cct::POS`
17//! call sites keep compiling alongside the C-canonical
18//! `CC_FILES` / `CCT_POS` names.
19
20// ---------------------------------------------------------------------------
21// `-x` condition type constants (c:76-89).
22// ---------------------------------------------------------------------------
23/// `CCT_UNUSED` constant.
24pub const CCT_UNUSED: i32 = 0; // c:76
25/// `CCT_POS` constant.
26pub const CCT_POS: i32 = 1; // c:77
27/// `CCT_CURSTR` constant.
28pub const CCT_CURSTR: i32 = 2; // c:78
29/// `CCT_CURPAT` constant.
30pub const CCT_CURPAT: i32 = 3; // c:79
31/// `CCT_WORDSTR` constant.
32pub const CCT_WORDSTR: i32 = 4; // c:80
33/// `CCT_WORDPAT` constant.
34pub const CCT_WORDPAT: i32 = 5; // c:81
35/// `CCT_CURSUF` constant.
36pub const CCT_CURSUF: i32 = 6; // c:82
37/// `CCT_CURPRE` constant.
38pub const CCT_CURPRE: i32 = 7; // c:83
39/// `CCT_CURSUB` constant.
40pub const CCT_CURSUB: i32 = 8; // c:84
41/// `CCT_CURSUBC` constant.
42pub const CCT_CURSUBC: i32 = 9; // c:85
43/// `CCT_NUMWORDS` constant.
44pub const CCT_NUMWORDS: i32 = 10; // c:86
45/// `CCT_RANGESTR` constant.
46pub const CCT_RANGESTR: i32 = 11; // c:87
47/// `CCT_RANGEPAT` constant.
48pub const CCT_RANGEPAT: i32 = 12; // c:88
49/// `CCT_QUOTE` constant.
50pub const CCT_QUOTE: i32 = 13; // c:89
51
52// ---------------------------------------------------------------------------
53// Primary completion-target flags (`mask`, c:118-149).
54// Each bit selects one completion-source kind (files, vars, jobs, ...)
55// the compctl spec expands.
56// ---------------------------------------------------------------------------
57/// `CC_FILES` constant.
58pub const CC_FILES: u64 = 1 << 0; // c:118
59/// `CC_COMMPATH` constant.
60pub const CC_COMMPATH: u64 = 1 << 1; // c:119
61/// `CC_REMOVE` constant.
62pub const CC_REMOVE: u64 = 1 << 2; // c:120
63/// `CC_OPTIONS` constant.
64pub const CC_OPTIONS: u64 = 1 << 3; // c:121
65/// `CC_VARS` constant.
66pub const CC_VARS: u64 = 1 << 4; // c:122
67/// `CC_BINDINGS` constant.
68pub const CC_BINDINGS: u64 = 1 << 5; // c:123
69/// `CC_ARRAYS` constant.
70pub const CC_ARRAYS: u64 = 1 << 6; // c:124
71/// `CC_INTVARS` constant.
72pub const CC_INTVARS: u64 = 1 << 7; // c:125
73/// `CC_SHFUNCS` constant.
74pub const CC_SHFUNCS: u64 = 1 << 8; // c:126
75/// `CC_PARAMS` constant.
76pub const CC_PARAMS: u64 = 1 << 9; // c:127
77/// `CC_ENVVARS` constant.
78pub const CC_ENVVARS: u64 = 1 << 10; // c:128
79/// `CC_JOBS` constant.
80pub const CC_JOBS: u64 = 1 << 11; // c:129
81/// `CC_RUNNING` constant.
82pub const CC_RUNNING: u64 = 1 << 12; // c:130
83/// `CC_STOPPED` constant.
84pub const CC_STOPPED: u64 = 1 << 13; // c:131
85/// `CC_BUILTINS` constant.
86pub const CC_BUILTINS: u64 = 1 << 14; // c:132
87/// `CC_ALREG` constant.
88pub const CC_ALREG: u64 = 1 << 15; // c:133
89/// `CC_ALGLOB` constant.
90pub const CC_ALGLOB: u64 = 1 << 16; // c:134
91/// `CC_USERS` constant.
92pub const CC_USERS: u64 = 1 << 17; // c:135
93/// `CC_DISCMDS` constant.
94pub const CC_DISCMDS: u64 = 1 << 18; // c:136
95/// `CC_EXCMDS` constant.
96pub const CC_EXCMDS: u64 = 1 << 19; // c:137
97/// `CC_SCALARS` constant.
98pub const CC_SCALARS: u64 = 1 << 20; // c:138
99/// `CC_READONLYS` constant.
100pub const CC_READONLYS: u64 = 1 << 21; // c:139
101/// `CC_SPECIALS` constant.
102pub const CC_SPECIALS: u64 = 1 << 22; // c:140
103/// `CC_DELETE` constant.
104pub const CC_DELETE: u64 = 1 << 23; // c:141
105/// `CC_NAMED` constant.
106pub const CC_NAMED: u64 = 1 << 24; // c:142
107/// `CC_QUOTEFLAG` constant.
108pub const CC_QUOTEFLAG: u64 = 1 << 25; // c:143
109/// `CC_EXTCMDS` constant.
110pub const CC_EXTCMDS: u64 = 1 << 26; // c:144
111/// `CC_RESWDS` constant.
112pub const CC_RESWDS: u64 = 1 << 27; // c:145
113/// `CC_DIRS` constant.
114pub const CC_DIRS: u64 = 1 << 28; // c:146
115/// `CC_EXPANDEXPL` constant.
116pub const CC_EXPANDEXPL: u64 = 1 << 30; // c:148
117/// `CC_RESERVED` constant.
118pub const CC_RESERVED: u64 = 1 << 31; // c:149
119
120// ---------------------------------------------------------------------------
121// Secondary completion-target flags (`mask2`, c:152-158).
122// ---------------------------------------------------------------------------
123/// `CC_NOSORT` constant.
124pub const CC_NOSORT: u64 = 1 << 0; // c:152
125/// `CC_XORCONT` constant.
126pub const CC_XORCONT: u64 = 1 << 1; // c:153
127/// `CC_CCCONT` constant.
128pub const CC_CCCONT: u64 = 1 << 2; // c:154
129/// `CC_PATCONT` constant.
130pub const CC_PATCONT: u64 = 1 << 3; // c:155
131/// `CC_DEFCONT` constant.
132pub const CC_DEFCONT: u64 = 1 << 4; // c:156
133/// `CC_UNIQCON` constant.
134pub const CC_UNIQCON: u64 = 1 << 5; // c:157
135/// `CC_UNIQALL` constant.
136pub const CC_UNIQALL: u64 = 1 << 6; // c:158
137
138// ---------------------------------------------------------------------------
139// Typedef structs (c:32-115).
140//
141// C uses linked lists threaded through `next` pointers. The Rust
142// port substitutes `Option<Box<...>>` for the same self-referential
143// chain; the linked-list semantics are preserved.
144// ---------------------------------------------------------------------------
145
146/// Port of `struct compctlp` from `Src/Zle/compctl.h:39-42`. Hash
147/// table node entry holding a pointer to the compctl descriptor.
148///
149/// C definition (c:39-42):
150/// ```c
151/// struct compctlp {
152///     struct hashnode node;
153///     Compctl cc;
154/// };
155/// ```
156///
157/// The Rust port omits the `hashnode` head (zshrs's hashtable
158/// machinery threads name+next through a separate scaffold) and
159/// keeps the semantic payload — a pointer to the compctl descriptor.
160#[derive(Debug, Clone)]
161#[allow(non_camel_case_types)]
162pub struct Compctlp {
163    // c:39
164    pub cc: std::sync::Arc<Compctl>, // c:41
165}
166
167/// Port of `struct patcomp` from `Src/Zle/compctl.h:46-50`. Linked-
168/// list node for the pattern-compctl registry (entries created by
169/// `compctl -p PATTERN ...`).
170///
171/// C definition (c:46-50):
172/// ```c
173/// struct patcomp {
174///     Patcomp next;
175///     char *pat;
176///     Compctl cc;
177/// };
178/// ```
179#[derive(Debug, Clone)]
180#[allow(non_camel_case_types)]
181pub struct Patcomp {
182    // c:46
183    pub next: Option<Box<Patcomp>>,  // c:47
184    pub pat: String,                 // c:48
185    pub cc: std::sync::Arc<Compctl>, // c:49
186}
187
188/// Port of `struct compcond` from `Src/Zle/compctl.h:54-74`. The
189/// per-condition descriptor for `compctl -x`.
190///
191/// C definition (c:54-74):
192/// ```c
193/// struct compcond {
194///     Compcond and, or;
195///     int type;            /* one of CCT_* */
196///     int n;               /* array length */
197///     union {
198///         struct { int *a, *b; } r;       /* CCT_POS, CCT_NUMWORDS */
199///         struct { int *p; char **s; } s;  /* CCT_CURSTR, CCT_CURPAT, ... */
200///         struct { char **a, **b; } l;     /* CCT_RANGESTR, ... */
201///     } u;
202/// };
203/// ```
204///
205/// The Rust port collapses C's `union` into an explicit enum
206/// (`CompcondData`) since Rust unions require unsafe; the dispatch
207/// is by `typ` per the C convention.
208#[derive(Debug, Clone, Default)]
209#[allow(non_camel_case_types)]
210pub struct Compcond {
211    // c:54
212    pub and: Option<Box<Compcond>>, // c:55
213    pub or: Option<Box<Compcond>>,  // c:55
214    pub typ: i32,                   // c:56  (Rust keyword `type`)
215    pub n: i32,                     // c:57
216    pub u: CompcondData,            // c:58 union
217}
218
219/// Port of the anonymous `union { struct r,s,l }` inside `compcond`
220/// at `Src/Zle/compctl.h:58-73`. The C union is dispatched by
221/// `typ` (one of the `CCT_*` constants).
222#[derive(Debug, Clone, Default)]
223#[allow(non_camel_case_types)]
224pub enum CompcondData {
225    // c:58
226    /// Port of `struct { int *a, *b; } r` (c:59-62) — used by
227    /// `CCT_POS`, `CCT_NUMWORDS`.
228    R { a: Vec<i32>, b: Vec<i32> },
229    /// Port of `struct { int *p; char **s; } s` (c:63-66) — used by
230    /// `CCT_CURSTR`, `CCT_CURPAT`, `CCT_CURSUF`, `CCT_CURPRE`,
231    /// `CCT_CURSUB`, `CCT_CURSUBC`, `CCT_WORDSTR`, `CCT_WORDPAT`,
232    /// `CCT_QUOTE`.
233    S { p: Vec<i32>, s: Vec<String> },
234    /// Port of `struct { char **a, **b; } l` (c:68-71) — used by
235    /// `CCT_RANGESTR`, `CCT_RANGEPAT`.
236    L {
237        a: Vec<String>,
238        b: Vec<Option<String>>, // c:70 — `None` is C's NULL (`r[a]`), `Some("")` is `r[a,]`
239    },
240    /// Empty (CCT_UNUSED).
241    #[default]
242    Unused,
243}
244
245/// Port of `struct compctl` from `Src/Zle/compctl.h:93-115`. The
246/// real per-command compctl descriptor — what `compctl name args`
247/// allocates and registers in the `compctltab` hashtable.
248///
249/// C definition (c:93-115) — 22 fields. Field names + types
250/// preserved verbatim; pointer types collapse to `Option<String>` /
251/// `Option<std::sync::Arc<Compctl>>` etc. as appropriate.
252#[derive(Debug, Clone, Default)]
253#[allow(non_camel_case_types)]
254pub struct Compctl {
255    // c:93
256    /// Reference count.
257    pub refc: i32, // c:94
258    /// Next compctl in a `-x` chain.
259    pub next: Option<std::sync::Arc<Compctl>>, // c:95
260    /// Mask of completion-target flags (`CC_*`).
261    pub mask: u64, // c:96
262    /// Secondary mask of completion-target flags (`CC_*`, mask2).
263    pub mask2: u64, // c:96
264    /// `-k` variable name.
265    pub keyvar: Option<String>, // c:97
266    /// `-g` glob pattern.
267    pub glob: Option<String>, // c:98
268    /// `-s` expansion string.
269    pub str: Option<String>, // c:99 (Rust keyword `str`)
270    /// `-K` function name.
271    pub func: Option<String>, // c:100
272    /// `-X` explanation.
273    pub explain: Option<String>, // c:101
274    /// `-y` user-defined description for listing.
275    pub ylist: Option<String>, // c:102
276    /// `-P` prefix.
277    pub prefix: Option<String>, // c:103
278    /// `-S` suffix.
279    pub suffix: Option<String>, // c:103
280    /// `-l` command name to use.
281    pub subcmd: Option<String>, // c:104
282    /// `-1` command name to use.
283    pub substr: Option<String>, // c:105
284    /// `-w` with-directory.
285    pub withd: Option<String>, // c:106
286    /// `-H` history pattern.
287    pub hpat: Option<String>, // c:107
288    /// `-H` number of events to search.
289    pub hnum: i32, // c:108
290    /// `-J`/`-V` group name.
291    pub gname: Option<String>, // c:109
292    /// `-x` first compctl in the chain.
293    pub ext: Option<std::sync::Arc<Compctl>>, // c:110
294    /// `-x` condition for this compctl.
295    pub cond: Option<Box<Compcond>>, // c:111
296    /// `+` xor'ed compctl chain.
297    pub xor: Option<std::sync::Arc<Compctl>>, // c:112
298    /// `-M` matcher control — head of the Cmatcher chain compiled
299    /// from this compctl's match-spec arg.
300    pub matcher: Option<Box<crate::ported::zle::comp_h::Cmatcher>>, // c:113
301    /// `-M` matcher string.
302    pub mstr: Option<String>, // c:114
303}
304
305#[cfg(test)]
306mod tests {
307    use super::*;
308    use crate::ported::zle::zle_main::zle_test_setup;
309
310    /// Verifies CCT_* values per c:76-89.
311    #[test]
312    fn cct_constants_correct() {
313        let _g = crate::test_util::global_state_lock();
314        let _g = zle_test_setup();
315        assert_eq!(CCT_UNUSED, 0);
316        assert_eq!(CCT_POS, 1);
317        assert_eq!(CCT_CURSTR, 2);
318        assert_eq!(CCT_QUOTE, 13);
319    }
320
321    /// Verifies CC_* primary mask values per c:118-149 — single-bit,
322    /// non-overlapping.
323    #[test]
324    fn cc_primary_mask_bits_distinct() {
325        let _g = crate::test_util::global_state_lock();
326        let _g = zle_test_setup();
327        let all = CC_FILES
328            | CC_COMMPATH
329            | CC_REMOVE
330            | CC_OPTIONS
331            | CC_VARS
332            | CC_BINDINGS
333            | CC_ARRAYS
334            | CC_INTVARS
335            | CC_SHFUNCS
336            | CC_PARAMS
337            | CC_ENVVARS
338            | CC_JOBS
339            | CC_RUNNING
340            | CC_STOPPED
341            | CC_BUILTINS
342            | CC_ALREG
343            | CC_ALGLOB
344            | CC_USERS
345            | CC_DISCMDS
346            | CC_EXCMDS
347            | CC_SCALARS
348            | CC_READONLYS
349            | CC_SPECIALS
350            | CC_DELETE
351            | CC_NAMED
352            | CC_QUOTEFLAG
353            | CC_EXTCMDS
354            | CC_RESWDS
355            | CC_DIRS
356            | CC_EXPANDEXPL
357            | CC_RESERVED;
358        assert_eq!(all.count_ones(), 31); // 30 sequential + 30 + 31 (skips bit 29)
359    }
360
361    /// Verifies the secondary mask values per c:152-158.
362    #[test]
363    fn cc_secondary_mask_values() {
364        let _g = crate::test_util::global_state_lock();
365        let _g = zle_test_setup();
366        assert_eq!(CC_NOSORT, 1);
367        assert_eq!(CC_XORCONT, 2);
368        assert_eq!(CC_UNIQALL, 1 << 6);
369    }
370
371    /// Verifies Compctl Default initialiser zeroes every field per
372    /// the C convention of `(Compctl) calloc(1, sizeof(...))`.
373    #[test]
374    fn compctl_default_zeros_fields() {
375        let _g = crate::test_util::global_state_lock();
376        let _g = zle_test_setup();
377        let cc = Compctl::default();
378        assert_eq!(cc.refc, 0);
379        assert!(cc.next.is_none());
380        assert_eq!(cc.mask, 0);
381        assert_eq!(cc.mask2, 0);
382        assert!(cc.keyvar.is_none());
383        assert!(cc.cond.is_none());
384        assert!(cc.xor.is_none());
385        assert_eq!(cc.hnum, 0);
386    }
387
388    /// Verifies Compcond Default starts in CCT_UNUSED state.
389    #[test]
390    fn compcond_default_is_unused() {
391        let _g = crate::test_util::global_state_lock();
392        let _g = zle_test_setup();
393        let c = Compcond::default();
394        assert_eq!(c.typ, CCT_UNUSED);
395        assert!(matches!(c.u, CompcondData::Unused));
396    }
397
398    /// Verifies the CompcondData variants align with the C union
399    /// dispatch per c:58-73.
400    #[test]
401    fn compcond_data_variants() {
402        let _g = crate::test_util::global_state_lock();
403        let _g = zle_test_setup();
404        let r = CompcondData::R {
405            a: vec![0, 1],
406            b: vec![2, 3],
407        };
408        if let CompcondData::R { a, b } = r {
409            assert_eq!(a, vec![0, 1]);
410            assert_eq!(b, vec![2, 3]);
411        } else {
412            panic!("expected R variant");
413        }
414        let s = CompcondData::S {
415            p: vec![1],
416            s: vec!["x".into()],
417        };
418        assert!(matches!(s, CompcondData::S { .. }));
419        let l = CompcondData::L {
420            a: vec!["lo".into()],
421            b: vec![Some("hi".into())],
422        };
423        assert!(matches!(l, CompcondData::L { .. }));
424    }
425
426    /// c:76-89 — Every CCT_* constant is a unique non-negative
427    /// integer. Pin uniqueness so a copy-paste regen doesn't double
428    /// up a tag (which would silently route two different
429    /// completion-condition kinds through the same dispatch arm).
430    #[test]
431    fn cct_constants_are_unique() {
432        let _g = crate::test_util::global_state_lock();
433        let _g = zle_test_setup();
434        let all = [
435            CCT_UNUSED,
436            CCT_POS,
437            CCT_CURSTR,
438            CCT_CURPAT,
439            CCT_WORDSTR,
440            CCT_WORDPAT,
441            CCT_CURSUF,
442            CCT_CURPRE,
443            CCT_CURSUB,
444            CCT_CURSUBC,
445            CCT_NUMWORDS,
446            CCT_RANGESTR,
447            CCT_RANGEPAT,
448            CCT_QUOTE,
449        ];
450        let unique: std::collections::HashSet<_> = all.iter().copied().collect();
451        assert_eq!(unique.len(), all.len(), "duplicate CCT_* constant detected");
452        for &v in &all {
453            assert!(v >= 0, "CCT_* constants must be non-negative");
454        }
455    }
456
457    /// c:76 — CCT_UNUSED MUST be 0. The C source uses zero-init as
458    /// the implicit "no condition" sentinel; a regression that sets
459    /// CCT_UNUSED = 1 would mark every just-allocated condition as
460    /// CCT_POS by accident.
461    #[test]
462    fn cct_unused_is_zero() {
463        let _g = crate::test_util::global_state_lock();
464        assert_eq!(CCT_UNUSED, 0, "CCT_UNUSED must be the zero-init sentinel");
465    }
466
467    /// c:118-127 — CC_* primary-mask bits are distinct singletons.
468    /// Pin the bit-packing because the c:152 "primary mask" vs
469    /// c:154-158 "secondary mask" distinction relies on the primary
470    /// bits all being non-overlapping.
471    #[test]
472    fn cc_primary_mask_bits_are_distinct_singletons() {
473        let _g = crate::test_util::global_state_lock();
474        let primary = [
475            CC_FILES,
476            CC_COMMPATH,
477            CC_REMOVE,
478            CC_OPTIONS,
479            CC_VARS,
480            CC_BINDINGS,
481            CC_ARRAYS,
482            CC_INTVARS,
483            CC_SHFUNCS,
484            CC_PARAMS,
485            CC_ENVVARS,
486        ];
487        for &m in &primary {
488            assert_eq!(
489                m.count_ones(),
490                1,
491                "primary CC_ mask {} has {} bits set",
492                m,
493                m.count_ones()
494            );
495        }
496        let mut all: u64 = 0;
497        for &m in &primary {
498            assert_eq!(all & m, 0, "primary CC_ mask {} overlaps", m);
499            all |= m;
500        }
501    }
502
503    /// c:108 — `Compctl::default()` Default impl produces an empty
504    /// struct ready for population. After a default + manual field
505    /// write, the other fields must remain at their zero-init values.
506    #[test]
507    fn compctl_default_partial_population_doesnt_clobber_other_fields() {
508        let _g = crate::test_util::global_state_lock();
509        let _g = zle_test_setup();
510        let mut cc = Compctl::default();
511        cc.mask = CC_FILES;
512        assert_eq!(cc.mask, CC_FILES);
513        // Every OTHER field must still be at default
514        assert_eq!(cc.refc, 0);
515        assert!(cc.next.is_none());
516        assert_eq!(cc.mask2, 0);
517        assert!(cc.keyvar.is_none());
518        assert!(cc.cond.is_none());
519        assert_eq!(cc.hnum, 0);
520    }
521
522    /// `Compcond::default()` produces a CCT_UNUSED node with the
523    /// `Unused` data variant. Pin the simultaneous shape so a
524    /// regression that picks one but not the other (e.g. CCT_POS
525    /// with Unused data) gets caught.
526    #[test]
527    fn compcond_default_typ_and_data_are_consistent() {
528        let _g = crate::test_util::global_state_lock();
529        let _g = zle_test_setup();
530        let c = Compcond::default();
531        assert_eq!(c.typ, CCT_UNUSED, "tag must be UNUSED");
532        assert!(
533            matches!(c.u, CompcondData::Unused),
534            "data must be CompcondData::Unused"
535        );
536    }
537
538    /// c:118-149 — Full sweep of CC_* primary-mask bits 0..31. Each
539    /// must occupy a distinct bit position. Catches a regen that
540    /// renumbers two flags to the same shift.
541    #[test]
542    fn cc_primary_mask_full_sweep_no_overlap() {
543        let _g = crate::test_util::global_state_lock();
544        let primary = [
545            CC_FILES,
546            CC_COMMPATH,
547            CC_REMOVE,
548            CC_OPTIONS,
549            CC_VARS,
550            CC_BINDINGS,
551            CC_ARRAYS,
552            CC_INTVARS,
553            CC_SHFUNCS,
554            CC_PARAMS,
555            CC_ENVVARS,
556            CC_STOPPED,
557            CC_BUILTINS,
558            CC_ALREG,
559            CC_ALGLOB,
560            CC_USERS,
561            CC_DISCMDS,
562            CC_EXCMDS,
563            CC_SCALARS,
564            CC_READONLYS,
565            CC_SPECIALS,
566            CC_DELETE,
567            CC_NAMED,
568            CC_QUOTEFLAG,
569            CC_EXTCMDS,
570            CC_RESWDS,
571            CC_DIRS,
572            CC_EXPANDEXPL,
573            CC_RESERVED,
574        ];
575        for &m in &primary {
576            assert_eq!(
577                m.count_ones(),
578                1,
579                "primary CC_ mask {:#x} must be single bit",
580                m
581            );
582        }
583        let mut all: u64 = 0;
584        for &m in &primary {
585            assert_eq!(all & m, 0, "CC_ mask {:#x} overlaps with previous flags", m);
586            all |= m;
587        }
588    }
589
590    /// c:148 — CC_EXPANDEXPL lives at bit 30 (NOT 29). Pin the
591    /// gap-at-bit-29 because the C source documents the bit-29
592    /// hole at c:147. A regen that "fills the gap" would shift
593    /// every subsequent flag.
594    #[test]
595    fn cc_expandexpl_at_bit_30_skips_bit_29() {
596        let _g = crate::test_util::global_state_lock();
597        assert_eq!(
598            CC_EXPANDEXPL,
599            1 << 30,
600            "c:148 — CC_EXPANDEXPL must be at bit 30 (bit 29 is the gap)"
601        );
602        // Verify nothing else IS bit 29
603        let all_primary = [
604            CC_FILES,
605            CC_COMMPATH,
606            CC_REMOVE,
607            CC_OPTIONS,
608            CC_VARS,
609            CC_BINDINGS,
610            CC_ARRAYS,
611            CC_INTVARS,
612            CC_SHFUNCS,
613            CC_PARAMS,
614            CC_ENVVARS,
615            CC_STOPPED,
616            CC_BUILTINS,
617            CC_ALREG,
618            CC_ALGLOB,
619            CC_USERS,
620            CC_DISCMDS,
621            CC_EXCMDS,
622            CC_SCALARS,
623            CC_READONLYS,
624            CC_SPECIALS,
625            CC_DELETE,
626            CC_NAMED,
627            CC_QUOTEFLAG,
628            CC_EXTCMDS,
629            CC_RESWDS,
630            CC_DIRS,
631            CC_EXPANDEXPL,
632            CC_RESERVED,
633        ];
634        let bit_29: u64 = 1 << 29;
635        for &m in &all_primary {
636            assert_ne!(
637                m, bit_29,
638                "no primary mask should occupy bit 29 (the documented gap)"
639            );
640        }
641    }
642
643    /// c:149 — CC_RESERVED is bit 31 (the high bit). Pin the
644    /// boundary so a regen that extends into bit 32 (u64 vs i32
645    /// confusion) gets caught.
646    #[test]
647    fn cc_reserved_is_bit_31() {
648        let _g = crate::test_util::global_state_lock();
649        assert_eq!(CC_RESERVED, 1u64 << 31);
650    }
651
652    /// c:152-158 — Secondary-mask (mask2) flags occupy bits 0-6 of
653    /// their OWN namespace. They DELIBERATELY collide with primary
654    /// mask values (CC_NOSORT = 1 = CC_FILES) — the dispatcher
655    /// routes via the mask vs mask2 field.
656    #[test]
657    fn secondary_mask_collides_with_primary_by_design() {
658        let _g = crate::test_util::global_state_lock();
659        // CC_NOSORT (mask2 bit 0) and CC_FILES (mask bit 0) both = 1
660        assert_eq!(
661            CC_NOSORT, CC_FILES,
662            "collision is intentional — different mask fields"
663        );
664        // CC_XORCONT (mask2 bit 1) and CC_COMMPATH (mask bit 1) both = 2
665        assert_eq!(CC_XORCONT, CC_COMMPATH);
666        // ... but mask2 has its own no-overlap structure
667        let secondary = [
668            CC_NOSORT, CC_XORCONT, CC_CCCONT, CC_PATCONT, CC_DEFCONT, CC_UNIQCON, CC_UNIQALL,
669        ];
670        let mut all: u64 = 0;
671        for &m in &secondary {
672            assert_eq!(
673                m.count_ones(),
674                1,
675                "secondary CC_ mask {:#x} must be single bit",
676                m
677            );
678            assert_eq!(
679                all & m,
680                0,
681                "secondary {:#x} overlaps within mask2 namespace",
682                m
683            );
684            all |= m;
685        }
686    }
687
688    /// c:76-89 — CCT_* values are sequential (0..13). Pin the
689    /// dense layout so a regen that introduces a gap silently
690    /// breaks the dispatcher's `(type - CCT_POS)` subtraction.
691    #[test]
692    fn cct_values_are_sequential_zero_through_thirteen() {
693        let _g = crate::test_util::global_state_lock();
694        let in_order = [
695            CCT_UNUSED,
696            CCT_POS,
697            CCT_CURSTR,
698            CCT_CURPAT,
699            CCT_WORDSTR,
700            CCT_WORDPAT,
701            CCT_CURSUF,
702            CCT_CURPRE,
703            CCT_CURSUB,
704            CCT_CURSUBC,
705            CCT_NUMWORDS,
706            CCT_RANGESTR,
707            CCT_RANGEPAT,
708            CCT_QUOTE,
709        ];
710        for (i, &v) in in_order.iter().enumerate() {
711            assert_eq!(
712                v, i as i32,
713                "CCT_ at position {} must be {}, got {}",
714                i, i, v
715            );
716        }
717    }
718
719    // ═══════════════════════════════════════════════════════════════════
720    // Additional C-parity tests for Src/Zle/compctl.h constants.
721    // ═══════════════════════════════════════════════════════════════════
722
723    /// c:76-89 — CCT_* values are sequential 0..14 (no holes).
724    #[test]
725    fn cct_values_pairwise_distinct() {
726        let all = [
727            CCT_UNUSED,
728            CCT_POS,
729            CCT_CURSTR,
730            CCT_CURPAT,
731            CCT_WORDSTR,
732            CCT_WORDPAT,
733            CCT_CURSUF,
734            CCT_CURPRE,
735            CCT_CURSUB,
736            CCT_CURSUBC,
737            CCT_NUMWORDS,
738            CCT_RANGESTR,
739            CCT_RANGEPAT,
740            CCT_QUOTE,
741        ];
742        let unique: std::collections::HashSet<_> = all.iter().copied().collect();
743        assert_eq!(unique.len(), all.len(), "CCT_* must be pairwise distinct");
744    }
745
746    /// c:76-89 — CCT_* canonical mid-table values (spot-check).
747    #[test]
748    fn cct_canonical_mid_values() {
749        assert_eq!(CCT_WORDSTR, 4);
750        assert_eq!(CCT_WORDPAT, 5);
751        assert_eq!(CCT_CURSUF, 6);
752        assert_eq!(CCT_CURPRE, 7);
753        assert_eq!(CCT_NUMWORDS, 10);
754        assert_eq!(CCT_RANGESTR, 11);
755        assert_eq!(CCT_RANGEPAT, 12);
756    }
757
758    /// c:118 — CC_FILES is bit 0 (the most common file-completion flag,
759    /// hot-path bit). Pin so a regen flipping bit assignments doesn't
760    /// silently break Tab completion of filenames.
761    #[test]
762    fn cc_files_is_bit_zero() {
763        assert_eq!(CC_FILES, 1);
764    }
765
766    /// c:118-128 — first 10 CC_* mask bits are pairwise disjoint
767    /// single-bit values.
768    #[test]
769    fn cc_first_10_flags_are_pairwise_disjoint_single_bits() {
770        let flags = [
771            CC_FILES,
772            CC_COMMPATH,
773            CC_REMOVE,
774            CC_OPTIONS,
775            CC_VARS,
776            CC_BINDINGS,
777            CC_ARRAYS,
778            CC_INTVARS,
779            CC_SHFUNCS,
780            CC_PARAMS,
781        ];
782        for (i, &a) in flags.iter().enumerate() {
783            assert!(a.is_power_of_two(), "CC_* flag {} must be single bit", a);
784            for &b in flags.iter().skip(i + 1) {
785                assert_eq!(a & b, 0, "{} and {} overlap", a, b);
786            }
787        }
788    }
789
790    /// c:118-128 — first 10 CC_* mask bits in canonical 1<<N positions.
791    #[test]
792    fn cc_first_10_flags_canonical_positions() {
793        assert_eq!(CC_FILES, 1 << 0);
794        assert_eq!(CC_COMMPATH, 1 << 1);
795        assert_eq!(CC_REMOVE, 1 << 2);
796        assert_eq!(CC_OPTIONS, 1 << 3);
797        assert_eq!(CC_VARS, 1 << 4);
798        assert_eq!(CC_BINDINGS, 1 << 5);
799        assert_eq!(CC_ARRAYS, 1 << 6);
800        assert_eq!(CC_INTVARS, 1 << 7);
801        assert_eq!(CC_SHFUNCS, 1 << 8);
802        assert_eq!(CC_PARAMS, 1 << 9);
803    }
804
805    /// c:152-158 — CC_NOSORT/XORCONT canonical positions in secondary
806    /// mask namespace (separate u64 from CC_FILES etc.).
807    #[test]
808    fn cc_secondary_low_bits_canonical() {
809        assert_eq!(CC_NOSORT, 1);
810        assert_eq!(CC_XORCONT, 2);
811    }
812
813    /// c:155 — CC_UNIQALL = 1 << 6.
814    #[test]
815    fn cc_uniqall_is_bit_6_in_secondary() {
816        assert_eq!(CC_UNIQALL, 1 << 6);
817    }
818
819    // ═══════════════════════════════════════════════════════════════════
820    // Additional C-parity tests for Src/Zle/compctl.h c:131-156 CC_*
821    // ═══════════════════════════════════════════════════════════════════
822
823    /// c:131-149 — every primary CC_* flag value is a power of two.
824    #[test]
825    fn cc_primary_flags_all_powers_of_two_full_sweep() {
826        for &v in &[
827            CC_STOPPED,
828            CC_BUILTINS,
829            CC_ALREG,
830            CC_ALGLOB,
831            CC_USERS,
832            CC_DISCMDS,
833            CC_EXCMDS,
834            CC_SCALARS,
835            CC_READONLYS,
836            CC_SPECIALS,
837            CC_DELETE,
838            CC_NAMED,
839            CC_QUOTEFLAG,
840            CC_EXTCMDS,
841            CC_RESWDS,
842            CC_DIRS,
843            CC_EXPANDEXPL,
844            CC_RESERVED,
845        ] {
846            assert!(
847                v.is_power_of_two(),
848                "CC_* primary {:#x} must be single bit",
849                v
850            );
851        }
852    }
853
854    /// c:148 — CC_EXPANDEXPL = bit 30 (skips bit 29 by design).
855    #[test]
856    fn cc_expandexpl_skips_bit_29() {
857        assert_eq!(CC_EXPANDEXPL, 1u64 << 30, "c:148 = bit 30");
858        // Bit 29 is reserved (intentionally unused per C source).
859    }
860
861    /// c:152-158 — secondary CC_* flags are powers of two.
862    #[test]
863    fn cc_secondary_flags_all_powers_of_two() {
864        for &v in &[
865            CC_NOSORT, CC_XORCONT, CC_CCCONT, CC_PATCONT, CC_DEFCONT, CC_UNIQCON, CC_UNIQALL,
866        ] {
867            assert!(
868                v.is_power_of_two(),
869                "CC_* secondary {:#x} must be single bit",
870                v
871            );
872        }
873    }
874
875    /// c:152-158 — secondary CC_* are pairwise distinct.
876    #[test]
877    fn cc_secondary_flags_pairwise_distinct() {
878        let codes = [
879            CC_NOSORT, CC_XORCONT, CC_CCCONT, CC_PATCONT, CC_DEFCONT, CC_UNIQCON, CC_UNIQALL,
880        ];
881        let unique: std::collections::HashSet<_> = codes.iter().copied().collect();
882        assert_eq!(unique.len(), codes.len(), "CC_* secondary must be distinct");
883    }
884
885    /// c:131-149 — primary CC_* canonical bit positions match c:113-149.
886    #[test]
887    fn cc_primary_canonical_high_bit_positions() {
888        assert_eq!(CC_DIRS, 1u64 << 28, "c:146");
889        assert_eq!(CC_RESERVED, 1u64 << 31, "c:149");
890        assert_eq!(CC_DELETE, 1u64 << 23, "c:141");
891        assert_eq!(CC_NAMED, 1u64 << 24, "c:142");
892        assert_eq!(CC_USERS, 1u64 << 17, "c:135");
893    }
894
895    /// c:131-149 + c:152-158 — every CC_* fits in u64 (compile-time
896    /// type pin).
897    #[test]
898    fn cc_all_flags_are_u64_type() {
899        let _: u64 = CC_STOPPED;
900        let _: u64 = CC_NOSORT;
901        let _: u64 = CC_RESERVED;
902    }
903
904    /// c:152-158 — CC_NOSORT through CC_UNIQALL form contiguous low-7 bits.
905    #[test]
906    fn cc_secondary_form_contiguous_low_bits() {
907        let mut bits: Vec<u64> = vec![
908            CC_NOSORT, CC_XORCONT, CC_CCCONT, CC_PATCONT, CC_DEFCONT, CC_UNIQCON, CC_UNIQALL,
909        ];
910        bits.sort();
911        for (i, &b) in bits.iter().enumerate() {
912            assert_eq!(b, 1u64 << i, "secondary bit {} must be 1<<{}", i, i);
913        }
914    }
915
916    /// c:131-149 — primary CC_* form mostly contiguous from bit 0 up
917    /// (with bit 29 reserved gap to bit 30 EXPANDEXPL).
918    #[test]
919    fn cc_primary_no_gaps_through_bit_28() {
920        // Bits 0..28 must all be claimed by primary CC_* flags.
921        let all = [
922            CC_FILES,
923            CC_COMMPATH,
924            CC_REMOVE,
925            CC_OPTIONS,
926            CC_VARS,
927            CC_BINDINGS,
928            CC_ARRAYS,
929            CC_INTVARS,
930            CC_SHFUNCS,
931            CC_PARAMS,
932            CC_ENVVARS,
933            CC_JOBS,
934            CC_RUNNING,
935            CC_STOPPED,
936            CC_BUILTINS,
937            CC_ALREG,
938            CC_ALGLOB,
939            CC_USERS,
940            CC_DISCMDS,
941            CC_EXCMDS,
942            CC_SCALARS,
943            CC_READONLYS,
944            CC_SPECIALS,
945            CC_DELETE,
946            CC_NAMED,
947            CC_QUOTEFLAG,
948            CC_EXTCMDS,
949            CC_RESWDS,
950            CC_DIRS,
951        ];
952        let or_all: u64 = all.iter().fold(0, |acc, &v| acc | v);
953        assert_eq!(or_all, (1u64 << 29) - 1, "bits 0..28 must all be set");
954    }
955
956    // ═══════════════════════════════════════════════════════════════════
957    // Additional C-parity tests for Src/Zle/compctl.h
958    // c:76-89 CCT_* / c:118-149 primary CC_* / c:152-158 secondary CC_*
959    // ═══════════════════════════════════════════════════════════════════
960
961    /// c:76 — `CCT_UNUSED` is the zero sentinel (slot 0).
962    #[test]
963    fn cct_unused_is_zero_sentinel() {
964        assert_eq!(CCT_UNUSED, 0, "c:76 — UNUSED is the slot-0 sentinel");
965    }
966
967    /// c:76-89 — all CCT_* codes are i32 (compile-time type pin).
968    #[test]
969    fn cct_codes_all_i32_type() {
970        let _: i32 = CCT_UNUSED;
971        let _: i32 = CCT_POS;
972        let _: i32 = CCT_QUOTE;
973    }
974
975    /// c:76-89 — CCT_* codes cover slots 0..=13 with no gaps/dups.
976    #[test]
977    fn cct_codes_dense_0_through_13() {
978        let mut codes = vec![
979            CCT_UNUSED,
980            CCT_POS,
981            CCT_CURSTR,
982            CCT_CURPAT,
983            CCT_WORDSTR,
984            CCT_WORDPAT,
985            CCT_CURSUF,
986            CCT_CURPRE,
987            CCT_CURSUB,
988            CCT_CURSUBC,
989            CCT_NUMWORDS,
990            CCT_RANGESTR,
991            CCT_RANGEPAT,
992            CCT_QUOTE,
993        ];
994        codes.sort();
995        let expected: Vec<i32> = (0..=13).collect();
996        assert_eq!(
997            codes, expected,
998            "CCT_* must cover slots 0..=13 with no gaps/dups"
999        );
1000    }
1001
1002    /// c:118 — `CC_FILES` is canonical bit 0 (alt name pin).
1003    #[test]
1004    fn cc_files_is_bit_zero_alt() {
1005        assert_eq!(CC_FILES, 1u64 << 0, "c:118 — FILES is bit 0");
1006    }
1007
1008    /// c:131-149 — primary CC_* form a complete bitset:
1009    /// (bits 0..28) | EXPANDEXPL(30) | RESERVED(31), with bit 29 gap.
1010    #[test]
1011    fn cc_primary_complete_bitset_with_bit29_gap() {
1012        let all = [
1013            CC_FILES,
1014            CC_COMMPATH,
1015            CC_REMOVE,
1016            CC_OPTIONS,
1017            CC_VARS,
1018            CC_BINDINGS,
1019            CC_ARRAYS,
1020            CC_INTVARS,
1021            CC_SHFUNCS,
1022            CC_PARAMS,
1023            CC_ENVVARS,
1024            CC_JOBS,
1025            CC_RUNNING,
1026            CC_STOPPED,
1027            CC_BUILTINS,
1028            CC_ALREG,
1029            CC_ALGLOB,
1030            CC_USERS,
1031            CC_DISCMDS,
1032            CC_EXCMDS,
1033            CC_SCALARS,
1034            CC_READONLYS,
1035            CC_SPECIALS,
1036            CC_DELETE,
1037            CC_NAMED,
1038            CC_QUOTEFLAG,
1039            CC_EXTCMDS,
1040            CC_RESWDS,
1041            CC_DIRS,
1042            CC_EXPANDEXPL,
1043            CC_RESERVED,
1044        ];
1045        let or_all: u64 = all.iter().fold(0, |acc, &v| acc | v);
1046        let expected = ((1u64 << 29) - 1) | (1u64 << 30) | (1u64 << 31);
1047        assert_eq!(
1048            or_all, expected,
1049            "primary CC_* must cover bits 0..28 + 30 + 31 (bit 29 reserved)"
1050        );
1051    }
1052
1053    /// c:131-149 — primary CC_* are pairwise distinct.
1054    #[test]
1055    fn cc_primary_flags_pairwise_distinct() {
1056        let codes = [
1057            CC_FILES,
1058            CC_COMMPATH,
1059            CC_REMOVE,
1060            CC_OPTIONS,
1061            CC_VARS,
1062            CC_BINDINGS,
1063            CC_ARRAYS,
1064            CC_INTVARS,
1065            CC_SHFUNCS,
1066            CC_PARAMS,
1067            CC_ENVVARS,
1068            CC_JOBS,
1069            CC_RUNNING,
1070            CC_STOPPED,
1071            CC_BUILTINS,
1072            CC_ALREG,
1073            CC_ALGLOB,
1074            CC_USERS,
1075            CC_DISCMDS,
1076            CC_EXCMDS,
1077            CC_SCALARS,
1078            CC_READONLYS,
1079            CC_SPECIALS,
1080            CC_DELETE,
1081            CC_NAMED,
1082            CC_QUOTEFLAG,
1083            CC_EXTCMDS,
1084            CC_RESWDS,
1085            CC_DIRS,
1086            CC_EXPANDEXPL,
1087            CC_RESERVED,
1088        ];
1089        let unique: std::collections::HashSet<_> = codes.iter().copied().collect();
1090        assert_eq!(
1091            unique.len(),
1092            codes.len(),
1093            "primary CC_* must be pairwise distinct"
1094        );
1095    }
1096
1097    /// c:118-149 — every primary CC_* is non-zero (no false sentinel).
1098    #[test]
1099    fn cc_primary_all_non_zero() {
1100        for &v in &[
1101            CC_FILES,
1102            CC_COMMPATH,
1103            CC_REMOVE,
1104            CC_OPTIONS,
1105            CC_DIRS,
1106            CC_EXPANDEXPL,
1107            CC_RESERVED,
1108        ] {
1109            assert!(v > 0, "CC_* primary must be > 0; got {}", v);
1110        }
1111    }
1112
1113    /// c:152-158 — every secondary CC_* is non-zero.
1114    #[test]
1115    fn cc_secondary_all_non_zero() {
1116        for &v in &[
1117            CC_NOSORT, CC_XORCONT, CC_CCCONT, CC_PATCONT, CC_DEFCONT, CC_UNIQCON, CC_UNIQALL,
1118        ] {
1119            assert!(v > 0, "CC_* secondary must be > 0; got {}", v);
1120        }
1121    }
1122
1123    // ═══════════════════════════════════════════════════════════════════
1124    // Additional C-parity pins for Src/Zle/compctl.h
1125    // c:76-89 CCT_* / c:118-149 CC_* / c:152-158 secondary CC_*
1126    // ═══════════════════════════════════════════════════════════════════
1127
1128    /// c:76-89 — every CCT_* is in 0..=13 (no out-of-range).
1129    #[test]
1130    fn cct_all_in_range_0_to_13() {
1131        for &v in &[
1132            CCT_UNUSED,
1133            CCT_POS,
1134            CCT_CURSTR,
1135            CCT_CURPAT,
1136            CCT_WORDSTR,
1137            CCT_WORDPAT,
1138            CCT_CURSUF,
1139            CCT_CURPRE,
1140            CCT_CURSUB,
1141            CCT_CURSUBC,
1142            CCT_NUMWORDS,
1143            CCT_RANGESTR,
1144            CCT_RANGEPAT,
1145            CCT_QUOTE,
1146        ] {
1147            assert!((0..=13).contains(&v), "CCT_* must be 0..=13, got {}", v);
1148        }
1149    }
1150
1151    /// c:76-89 — CCT_* values are pairwise distinct (sequential).
1152    #[test]
1153    fn cct_pairwise_distinct() {
1154        let codes = [
1155            CCT_UNUSED,
1156            CCT_POS,
1157            CCT_CURSTR,
1158            CCT_CURPAT,
1159            CCT_WORDSTR,
1160            CCT_WORDPAT,
1161            CCT_CURSUF,
1162            CCT_CURPRE,
1163            CCT_CURSUB,
1164            CCT_CURSUBC,
1165            CCT_NUMWORDS,
1166            CCT_RANGESTR,
1167            CCT_RANGEPAT,
1168            CCT_QUOTE,
1169        ];
1170        let unique: std::collections::HashSet<_> = codes.iter().copied().collect();
1171        assert_eq!(unique.len(), codes.len(), "CCT_* pairwise distinct");
1172    }
1173
1174    /// c:76 — `CCT_UNUSED` is sentinel zero (alt pin).
1175    #[test]
1176    fn cct_unused_is_zero_sentinel_alt() {
1177        assert_eq!(CCT_UNUSED, 0, "CCT_UNUSED must be 0 (sentinel)");
1178    }
1179
1180    /// c:148 — `CC_EXPANDEXPL` skips bit 29 (gap preserved from C).
1181    #[test]
1182    fn cc_expandexpl_uses_bit_30_not_29() {
1183        assert_eq!(
1184            CC_EXPANDEXPL,
1185            1u64 << 30,
1186            "CC_EXPANDEXPL must use bit 30 (bit 29 reserved)"
1187        );
1188    }
1189
1190    /// c:152-158 — every secondary CC_* is in low 7 bits (0..7).
1191    #[test]
1192    fn cc_secondary_in_low_7_bits() {
1193        for &v in &[
1194            CC_NOSORT, CC_XORCONT, CC_CCCONT, CC_PATCONT, CC_DEFCONT, CC_UNIQCON, CC_UNIQALL,
1195        ] {
1196            assert!(
1197                v < (1u64 << 7),
1198                "CC_* secondary must be < (1<<7), got 0x{:x}",
1199                v
1200            );
1201        }
1202    }
1203
1204    /// c:118-149 — bit 29 is the reserved gap; no primary CC_* uses it.
1205    #[test]
1206    fn cc_primary_bit_29_is_reserved_gap() {
1207        let codes = [
1208            CC_FILES,
1209            CC_COMMPATH,
1210            CC_REMOVE,
1211            CC_OPTIONS,
1212            CC_VARS,
1213            CC_BINDINGS,
1214            CC_ARRAYS,
1215            CC_INTVARS,
1216            CC_SHFUNCS,
1217            CC_PARAMS,
1218            CC_ENVVARS,
1219            CC_JOBS,
1220            CC_RUNNING,
1221            CC_STOPPED,
1222            CC_BUILTINS,
1223            CC_ALREG,
1224            CC_ALGLOB,
1225            CC_USERS,
1226            CC_DISCMDS,
1227            CC_EXCMDS,
1228            CC_SCALARS,
1229            CC_READONLYS,
1230            CC_SPECIALS,
1231            CC_DELETE,
1232            CC_NAMED,
1233            CC_QUOTEFLAG,
1234            CC_EXTCMDS,
1235            CC_RESWDS,
1236            CC_DIRS,
1237            CC_EXPANDEXPL,
1238            CC_RESERVED,
1239        ];
1240        for c in codes {
1241            assert_ne!(
1242                c,
1243                1u64 << 29,
1244                "no primary CC_* uses bit 29 (reserved); offending: 0x{:x}",
1245                c
1246            );
1247        }
1248    }
1249
1250    /// c:152-158 — secondary CC_* pairwise distinct.
1251    #[test]
1252    fn cc_secondary_pairwise_distinct() {
1253        let codes = [
1254            CC_NOSORT, CC_XORCONT, CC_CCCONT, CC_PATCONT, CC_DEFCONT, CC_UNIQCON, CC_UNIQALL,
1255        ];
1256        let unique: std::collections::HashSet<_> = codes.iter().copied().collect();
1257        assert_eq!(
1258            unique.len(),
1259            codes.len(),
1260            "secondary CC_* pairwise distinct"
1261        );
1262    }
1263
1264    /// c:152-158 — OR of all secondary CC_* covers bits 0..6.
1265    #[test]
1266    fn cc_secondary_or_covers_low_7_bits() {
1267        let or_all =
1268            CC_NOSORT | CC_XORCONT | CC_CCCONT | CC_PATCONT | CC_DEFCONT | CC_UNIQCON | CC_UNIQALL;
1269        assert_eq!(
1270            or_all,
1271            (1u64 << 7) - 1,
1272            "secondary CC_* must cover bits 0..6"
1273        );
1274    }
1275
1276    /// c:118 — `CC_FILES` is bit 0 (smallest primary, pin alt2).
1277    #[test]
1278    fn cc_files_is_bit_zero_pin_alt2() {
1279        assert_eq!(CC_FILES, 1u64, "CC_FILES must be bit 0");
1280    }
1281
1282    /// c:152 — `CC_NOSORT` is bit 0 (smallest secondary).
1283    #[test]
1284    fn cc_nosort_is_bit_zero() {
1285        assert_eq!(CC_NOSORT, 1u64, "CC_NOSORT must be bit 0 of secondary mask");
1286    }
1287
1288    /// c:149 — `CC_RESERVED` is the highest primary (bit 31).
1289    #[test]
1290    fn cc_reserved_is_highest_bit_31() {
1291        assert_eq!(CC_RESERVED, 1u64 << 31, "CC_RESERVED must be bit 31");
1292    }
1293
1294    /// c:158 — `CC_UNIQALL` is the highest secondary (bit 6).
1295    #[test]
1296    fn cc_uniqall_is_bit_six() {
1297        assert_eq!(CC_UNIQALL, 1u64 << 6, "CC_UNIQALL must be bit 6");
1298    }
1299
1300    /// c:78 — `CCT_CURSTR` = 2 (positional value pin).
1301    #[test]
1302    fn cct_curstr_is_two() {
1303        assert_eq!(CCT_CURSTR, 2);
1304    }
1305}