pub const CCT_UNUSED: i32 = 0; pub const CCT_POS: i32 = 1; pub const CCT_CURSTR: i32 = 2; pub const CCT_CURPAT: i32 = 3; pub const CCT_WORDSTR: i32 = 4; pub const CCT_WORDPAT: i32 = 5; pub const CCT_CURSUF: i32 = 6; pub const CCT_CURPRE: i32 = 7; pub const CCT_CURSUB: i32 = 8; pub const CCT_CURSUBC: i32 = 9; pub const CCT_NUMWORDS: i32 = 10; pub const CCT_RANGESTR: i32 = 11; pub const CCT_RANGEPAT: i32 = 12; pub const CCT_QUOTE: i32 = 13;
pub const CC_FILES: u64 = 1 << 0; pub const CC_COMMPATH: u64 = 1 << 1; pub const CC_REMOVE: u64 = 1 << 2; pub const CC_OPTIONS: u64 = 1 << 3; pub const CC_VARS: u64 = 1 << 4; pub const CC_BINDINGS: u64 = 1 << 5; pub const CC_ARRAYS: u64 = 1 << 6; pub const CC_INTVARS: u64 = 1 << 7; pub const CC_SHFUNCS: u64 = 1 << 8; pub const CC_PARAMS: u64 = 1 << 9; pub const CC_ENVVARS: u64 = 1 << 10; pub const CC_JOBS: u64 = 1 << 11; pub const CC_RUNNING: u64 = 1 << 12; pub const CC_STOPPED: u64 = 1 << 13; pub const CC_BUILTINS: u64 = 1 << 14; pub const CC_ALREG: u64 = 1 << 15; pub const CC_ALGLOB: u64 = 1 << 16; pub const CC_USERS: u64 = 1 << 17; pub const CC_DISCMDS: u64 = 1 << 18; pub const CC_EXCMDS: u64 = 1 << 19; pub const CC_SCALARS: u64 = 1 << 20; pub const CC_READONLYS: u64 = 1 << 21; pub const CC_SPECIALS: u64 = 1 << 22; pub const CC_DELETE: u64 = 1 << 23; pub const CC_NAMED: u64 = 1 << 24; pub const CC_QUOTEFLAG: u64 = 1 << 25; pub const CC_EXTCMDS: u64 = 1 << 26; pub const CC_RESWDS: u64 = 1 << 27; pub const CC_DIRS: u64 = 1 << 28; pub const CC_EXPANDEXPL: u64 = 1 << 30; pub const CC_RESERVED: u64 = 1 << 31;
pub const CC_NOSORT: u64 = 1 << 0; pub const CC_XORCONT: u64 = 1 << 1; pub const CC_CCCONT: u64 = 1 << 2; pub const CC_PATCONT: u64 = 1 << 3; pub const CC_DEFCONT: u64 = 1 << 4; pub const CC_UNIQCON: u64 = 1 << 5; pub const CC_UNIQALL: u64 = 1 << 6;
#[derive(Debug, Clone)]
#[allow(non_camel_case_types)]
pub struct Compctlp {
pub cc: std::sync::Arc<Compctl>, }
#[derive(Debug, Clone)]
#[allow(non_camel_case_types)]
pub struct Patcomp {
pub next: Option<Box<Patcomp>>, pub pat: String, pub cc: std::sync::Arc<Compctl>, }
#[derive(Debug, Clone, Default)]
#[allow(non_camel_case_types)]
pub struct Compcond {
pub and: Option<Box<Compcond>>, pub or: Option<Box<Compcond>>, pub typ: i32, pub n: i32, pub u: CompcondData, }
#[derive(Debug, Clone, Default)]
#[allow(non_camel_case_types)]
pub enum CompcondData {
R { a: Vec<i32>, b: Vec<i32> },
S { p: Vec<i32>, s: Vec<String> },
L { a: Vec<String>, b: Vec<String> },
#[default]
Unused,
}
#[derive(Debug, Clone, Default)]
#[allow(non_camel_case_types)]
pub struct Compctl {
pub refc: i32, pub next: Option<std::sync::Arc<Compctl>>, pub mask: u64, pub mask2: u64, pub keyvar: Option<String>, pub glob: Option<String>, pub str: Option<String>, pub func: Option<String>, pub explain: Option<String>, pub ylist: Option<String>, pub prefix: Option<String>, pub suffix: Option<String>, pub subcmd: Option<String>, pub substr: Option<String>, pub withd: Option<String>, pub hpat: Option<String>, pub hnum: i32, pub gname: Option<String>, pub ext: Option<std::sync::Arc<Compctl>>, pub cond: Option<Box<Compcond>>, pub xor: Option<std::sync::Arc<Compctl>>, pub matcher: Option<Box<crate::ported::zle::comp_h::Cmatcher>>, pub mstr: Option<String>, }
#[cfg(test)]
mod tests {
use super::*;
use crate::ported::zle::zle_main::zle_test_setup;
#[test]
fn cct_constants_correct() {
let _g = crate::test_util::global_state_lock();
let _g = zle_test_setup();
assert_eq!(CCT_UNUSED, 0);
assert_eq!(CCT_POS, 1);
assert_eq!(CCT_CURSTR, 2);
assert_eq!(CCT_QUOTE, 13);
}
#[test]
fn cc_primary_mask_bits_distinct() {
let _g = crate::test_util::global_state_lock();
let _g = zle_test_setup();
let all = CC_FILES
| CC_COMMPATH
| CC_REMOVE
| CC_OPTIONS
| CC_VARS
| CC_BINDINGS
| CC_ARRAYS
| CC_INTVARS
| CC_SHFUNCS
| CC_PARAMS
| CC_ENVVARS
| CC_JOBS
| CC_RUNNING
| CC_STOPPED
| CC_BUILTINS
| CC_ALREG
| CC_ALGLOB
| CC_USERS
| CC_DISCMDS
| CC_EXCMDS
| CC_SCALARS
| CC_READONLYS
| CC_SPECIALS
| CC_DELETE
| CC_NAMED
| CC_QUOTEFLAG
| CC_EXTCMDS
| CC_RESWDS
| CC_DIRS
| CC_EXPANDEXPL
| CC_RESERVED;
assert_eq!(all.count_ones(), 31); }
#[test]
fn cc_secondary_mask_values() {
let _g = crate::test_util::global_state_lock();
let _g = zle_test_setup();
assert_eq!(CC_NOSORT, 1);
assert_eq!(CC_XORCONT, 2);
assert_eq!(CC_UNIQALL, 1 << 6);
}
#[test]
fn compctl_default_zeros_fields() {
let _g = crate::test_util::global_state_lock();
let _g = zle_test_setup();
let cc = Compctl::default();
assert_eq!(cc.refc, 0);
assert!(cc.next.is_none());
assert_eq!(cc.mask, 0);
assert_eq!(cc.mask2, 0);
assert!(cc.keyvar.is_none());
assert!(cc.cond.is_none());
assert!(cc.xor.is_none());
assert_eq!(cc.hnum, 0);
}
#[test]
fn compcond_default_is_unused() {
let _g = crate::test_util::global_state_lock();
let _g = zle_test_setup();
let c = Compcond::default();
assert_eq!(c.typ, CCT_UNUSED);
assert!(matches!(c.u, CompcondData::Unused));
}
#[test]
fn compcond_data_variants() {
let _g = crate::test_util::global_state_lock();
let _g = zle_test_setup();
let r = CompcondData::R {
a: vec![0, 1],
b: vec![2, 3],
};
if let CompcondData::R { a, b } = r {
assert_eq!(a, vec![0, 1]);
assert_eq!(b, vec![2, 3]);
} else {
panic!("expected R variant");
}
let s = CompcondData::S {
p: vec![1],
s: vec!["x".into()],
};
assert!(matches!(s, CompcondData::S { .. }));
let l = CompcondData::L {
a: vec!["lo".into()],
b: vec!["hi".into()],
};
assert!(matches!(l, CompcondData::L { .. }));
}
#[test]
fn cct_constants_are_unique() {
let _g = crate::test_util::global_state_lock();
let _g = zle_test_setup();
let all = [
CCT_UNUSED,
CCT_POS,
CCT_CURSTR,
CCT_CURPAT,
CCT_WORDSTR,
CCT_WORDPAT,
CCT_CURSUF,
CCT_CURPRE,
CCT_CURSUB,
CCT_CURSUBC,
CCT_NUMWORDS,
CCT_RANGESTR,
CCT_RANGEPAT,
CCT_QUOTE,
];
let unique: std::collections::HashSet<_> = all.iter().copied().collect();
assert_eq!(unique.len(), all.len(), "duplicate CCT_* constant detected");
for &v in &all {
assert!(v >= 0, "CCT_* constants must be non-negative");
}
}
#[test]
fn cct_unused_is_zero() {
let _g = crate::test_util::global_state_lock();
assert_eq!(CCT_UNUSED, 0, "CCT_UNUSED must be the zero-init sentinel");
}
#[test]
fn cc_primary_mask_bits_are_distinct_singletons() {
let _g = crate::test_util::global_state_lock();
let primary = [
CC_FILES,
CC_COMMPATH,
CC_REMOVE,
CC_OPTIONS,
CC_VARS,
CC_BINDINGS,
CC_ARRAYS,
CC_INTVARS,
CC_SHFUNCS,
CC_PARAMS,
CC_ENVVARS,
];
for &m in &primary {
assert_eq!(
m.count_ones(),
1,
"primary CC_ mask {} has {} bits set",
m,
m.count_ones()
);
}
let mut all: u64 = 0;
for &m in &primary {
assert_eq!(all & m, 0, "primary CC_ mask {} overlaps", m);
all |= m;
}
}
#[test]
fn compctl_default_partial_population_doesnt_clobber_other_fields() {
let _g = crate::test_util::global_state_lock();
let _g = zle_test_setup();
let mut cc = Compctl::default();
cc.mask = CC_FILES;
assert_eq!(cc.mask, CC_FILES);
assert_eq!(cc.refc, 0);
assert!(cc.next.is_none());
assert_eq!(cc.mask2, 0);
assert!(cc.keyvar.is_none());
assert!(cc.cond.is_none());
assert_eq!(cc.hnum, 0);
}
#[test]
fn compcond_default_typ_and_data_are_consistent() {
let _g = crate::test_util::global_state_lock();
let _g = zle_test_setup();
let c = Compcond::default();
assert_eq!(c.typ, CCT_UNUSED, "tag must be UNUSED");
assert!(
matches!(c.u, CompcondData::Unused),
"data must be CompcondData::Unused"
);
}
#[test]
fn cc_primary_mask_full_sweep_no_overlap() {
let _g = crate::test_util::global_state_lock();
let primary = [
CC_FILES,
CC_COMMPATH,
CC_REMOVE,
CC_OPTIONS,
CC_VARS,
CC_BINDINGS,
CC_ARRAYS,
CC_INTVARS,
CC_SHFUNCS,
CC_PARAMS,
CC_ENVVARS,
CC_STOPPED,
CC_BUILTINS,
CC_ALREG,
CC_ALGLOB,
CC_USERS,
CC_DISCMDS,
CC_EXCMDS,
CC_SCALARS,
CC_READONLYS,
CC_SPECIALS,
CC_DELETE,
CC_NAMED,
CC_QUOTEFLAG,
CC_EXTCMDS,
CC_RESWDS,
CC_DIRS,
CC_EXPANDEXPL,
CC_RESERVED,
];
for &m in &primary {
assert_eq!(
m.count_ones(),
1,
"primary CC_ mask {:#x} must be single bit",
m
);
}
let mut all: u64 = 0;
for &m in &primary {
assert_eq!(all & m, 0, "CC_ mask {:#x} overlaps with previous flags", m);
all |= m;
}
}
#[test]
fn cc_expandexpl_at_bit_30_skips_bit_29() {
let _g = crate::test_util::global_state_lock();
assert_eq!(
CC_EXPANDEXPL,
1 << 30,
"c:148 — CC_EXPANDEXPL must be at bit 30 (bit 29 is the gap)"
);
let all_primary = [
CC_FILES,
CC_COMMPATH,
CC_REMOVE,
CC_OPTIONS,
CC_VARS,
CC_BINDINGS,
CC_ARRAYS,
CC_INTVARS,
CC_SHFUNCS,
CC_PARAMS,
CC_ENVVARS,
CC_STOPPED,
CC_BUILTINS,
CC_ALREG,
CC_ALGLOB,
CC_USERS,
CC_DISCMDS,
CC_EXCMDS,
CC_SCALARS,
CC_READONLYS,
CC_SPECIALS,
CC_DELETE,
CC_NAMED,
CC_QUOTEFLAG,
CC_EXTCMDS,
CC_RESWDS,
CC_DIRS,
CC_EXPANDEXPL,
CC_RESERVED,
];
let bit_29: u64 = 1 << 29;
for &m in &all_primary {
assert_ne!(
m, bit_29,
"no primary mask should occupy bit 29 (the documented gap)"
);
}
}
#[test]
fn cc_reserved_is_bit_31() {
let _g = crate::test_util::global_state_lock();
assert_eq!(CC_RESERVED, 1u64 << 31);
}
#[test]
fn secondary_mask_collides_with_primary_by_design() {
let _g = crate::test_util::global_state_lock();
assert_eq!(
CC_NOSORT, CC_FILES,
"collision is intentional — different mask fields"
);
assert_eq!(CC_XORCONT, CC_COMMPATH);
let secondary = [
CC_NOSORT, CC_XORCONT, CC_CCCONT, CC_PATCONT, CC_DEFCONT, CC_UNIQCON, CC_UNIQALL,
];
let mut all: u64 = 0;
for &m in &secondary {
assert_eq!(
m.count_ones(),
1,
"secondary CC_ mask {:#x} must be single bit",
m
);
assert_eq!(
all & m,
0,
"secondary {:#x} overlaps within mask2 namespace",
m
);
all |= m;
}
}
#[test]
fn cct_values_are_sequential_zero_through_thirteen() {
let _g = crate::test_util::global_state_lock();
let in_order = [
CCT_UNUSED,
CCT_POS,
CCT_CURSTR,
CCT_CURPAT,
CCT_WORDSTR,
CCT_WORDPAT,
CCT_CURSUF,
CCT_CURPRE,
CCT_CURSUB,
CCT_CURSUBC,
CCT_NUMWORDS,
CCT_RANGESTR,
CCT_RANGEPAT,
CCT_QUOTE,
];
for (i, &v) in in_order.iter().enumerate() {
assert_eq!(
v, i as i32,
"CCT_ at position {} must be {}, got {}",
i, i, v
);
}
}
#[test]
fn cct_values_pairwise_distinct() {
let all = [
CCT_UNUSED,
CCT_POS,
CCT_CURSTR,
CCT_CURPAT,
CCT_WORDSTR,
CCT_WORDPAT,
CCT_CURSUF,
CCT_CURPRE,
CCT_CURSUB,
CCT_CURSUBC,
CCT_NUMWORDS,
CCT_RANGESTR,
CCT_RANGEPAT,
CCT_QUOTE,
];
let unique: std::collections::HashSet<_> = all.iter().copied().collect();
assert_eq!(unique.len(), all.len(), "CCT_* must be pairwise distinct");
}
#[test]
fn cct_canonical_mid_values() {
assert_eq!(CCT_WORDSTR, 4);
assert_eq!(CCT_WORDPAT, 5);
assert_eq!(CCT_CURSUF, 6);
assert_eq!(CCT_CURPRE, 7);
assert_eq!(CCT_NUMWORDS, 10);
assert_eq!(CCT_RANGESTR, 11);
assert_eq!(CCT_RANGEPAT, 12);
}
#[test]
fn cc_files_is_bit_zero() {
assert_eq!(CC_FILES, 1);
}
#[test]
fn cc_first_10_flags_are_pairwise_disjoint_single_bits() {
let flags = [
CC_FILES,
CC_COMMPATH,
CC_REMOVE,
CC_OPTIONS,
CC_VARS,
CC_BINDINGS,
CC_ARRAYS,
CC_INTVARS,
CC_SHFUNCS,
CC_PARAMS,
];
for (i, &a) in flags.iter().enumerate() {
assert!(a.is_power_of_two(), "CC_* flag {} must be single bit", a);
for &b in flags.iter().skip(i + 1) {
assert_eq!(a & b, 0, "{} and {} overlap", a, b);
}
}
}
#[test]
fn cc_first_10_flags_canonical_positions() {
assert_eq!(CC_FILES, 1 << 0);
assert_eq!(CC_COMMPATH, 1 << 1);
assert_eq!(CC_REMOVE, 1 << 2);
assert_eq!(CC_OPTIONS, 1 << 3);
assert_eq!(CC_VARS, 1 << 4);
assert_eq!(CC_BINDINGS, 1 << 5);
assert_eq!(CC_ARRAYS, 1 << 6);
assert_eq!(CC_INTVARS, 1 << 7);
assert_eq!(CC_SHFUNCS, 1 << 8);
assert_eq!(CC_PARAMS, 1 << 9);
}
#[test]
fn cc_secondary_low_bits_canonical() {
assert_eq!(CC_NOSORT, 1);
assert_eq!(CC_XORCONT, 2);
}
#[test]
fn cc_uniqall_is_bit_6_in_secondary() {
assert_eq!(CC_UNIQALL, 1 << 6);
}
#[test]
fn cc_primary_flags_all_powers_of_two_full_sweep() {
for &v in &[
CC_STOPPED,
CC_BUILTINS,
CC_ALREG,
CC_ALGLOB,
CC_USERS,
CC_DISCMDS,
CC_EXCMDS,
CC_SCALARS,
CC_READONLYS,
CC_SPECIALS,
CC_DELETE,
CC_NAMED,
CC_QUOTEFLAG,
CC_EXTCMDS,
CC_RESWDS,
CC_DIRS,
CC_EXPANDEXPL,
CC_RESERVED,
] {
assert!(
v.is_power_of_two(),
"CC_* primary {:#x} must be single bit",
v
);
}
}
#[test]
fn cc_expandexpl_skips_bit_29() {
assert_eq!(CC_EXPANDEXPL, 1u64 << 30, "c:148 = bit 30");
}
#[test]
fn cc_secondary_flags_all_powers_of_two() {
for &v in &[
CC_NOSORT, CC_XORCONT, CC_CCCONT, CC_PATCONT, CC_DEFCONT, CC_UNIQCON, CC_UNIQALL,
] {
assert!(
v.is_power_of_two(),
"CC_* secondary {:#x} must be single bit",
v
);
}
}
#[test]
fn cc_secondary_flags_pairwise_distinct() {
let codes = [
CC_NOSORT, CC_XORCONT, CC_CCCONT, CC_PATCONT, CC_DEFCONT, CC_UNIQCON, CC_UNIQALL,
];
let unique: std::collections::HashSet<_> = codes.iter().copied().collect();
assert_eq!(unique.len(), codes.len(), "CC_* secondary must be distinct");
}
#[test]
fn cc_primary_canonical_high_bit_positions() {
assert_eq!(CC_DIRS, 1u64 << 28, "c:146");
assert_eq!(CC_RESERVED, 1u64 << 31, "c:149");
assert_eq!(CC_DELETE, 1u64 << 23, "c:141");
assert_eq!(CC_NAMED, 1u64 << 24, "c:142");
assert_eq!(CC_USERS, 1u64 << 17, "c:135");
}
#[test]
fn cc_all_flags_are_u64_type() {
let _: u64 = CC_STOPPED;
let _: u64 = CC_NOSORT;
let _: u64 = CC_RESERVED;
}
#[test]
fn cc_secondary_form_contiguous_low_bits() {
let mut bits: Vec<u64> = vec![
CC_NOSORT, CC_XORCONT, CC_CCCONT, CC_PATCONT, CC_DEFCONT, CC_UNIQCON, CC_UNIQALL,
];
bits.sort();
for (i, &b) in bits.iter().enumerate() {
assert_eq!(b, 1u64 << i, "secondary bit {} must be 1<<{}", i, i);
}
}
#[test]
fn cc_primary_no_gaps_through_bit_28() {
let all = [
CC_FILES,
CC_COMMPATH,
CC_REMOVE,
CC_OPTIONS,
CC_VARS,
CC_BINDINGS,
CC_ARRAYS,
CC_INTVARS,
CC_SHFUNCS,
CC_PARAMS,
CC_ENVVARS,
CC_JOBS,
CC_RUNNING,
CC_STOPPED,
CC_BUILTINS,
CC_ALREG,
CC_ALGLOB,
CC_USERS,
CC_DISCMDS,
CC_EXCMDS,
CC_SCALARS,
CC_READONLYS,
CC_SPECIALS,
CC_DELETE,
CC_NAMED,
CC_QUOTEFLAG,
CC_EXTCMDS,
CC_RESWDS,
CC_DIRS,
];
let or_all: u64 = all.iter().fold(0, |acc, &v| acc | v);
assert_eq!(or_all, (1u64 << 29) - 1, "bits 0..28 must all be set");
}
#[test]
fn cct_unused_is_zero_sentinel() {
assert_eq!(CCT_UNUSED, 0, "c:76 — UNUSED is the slot-0 sentinel");
}
#[test]
fn cct_codes_all_i32_type() {
let _: i32 = CCT_UNUSED;
let _: i32 = CCT_POS;
let _: i32 = CCT_QUOTE;
}
#[test]
fn cct_codes_dense_0_through_13() {
let mut codes = vec![
CCT_UNUSED,
CCT_POS,
CCT_CURSTR,
CCT_CURPAT,
CCT_WORDSTR,
CCT_WORDPAT,
CCT_CURSUF,
CCT_CURPRE,
CCT_CURSUB,
CCT_CURSUBC,
CCT_NUMWORDS,
CCT_RANGESTR,
CCT_RANGEPAT,
CCT_QUOTE,
];
codes.sort();
let expected: Vec<i32> = (0..=13).collect();
assert_eq!(
codes, expected,
"CCT_* must cover slots 0..=13 with no gaps/dups"
);
}
#[test]
fn cc_files_is_bit_zero_alt() {
assert_eq!(CC_FILES, 1u64 << 0, "c:118 — FILES is bit 0");
}
#[test]
fn cc_primary_complete_bitset_with_bit29_gap() {
let all = [
CC_FILES,
CC_COMMPATH,
CC_REMOVE,
CC_OPTIONS,
CC_VARS,
CC_BINDINGS,
CC_ARRAYS,
CC_INTVARS,
CC_SHFUNCS,
CC_PARAMS,
CC_ENVVARS,
CC_JOBS,
CC_RUNNING,
CC_STOPPED,
CC_BUILTINS,
CC_ALREG,
CC_ALGLOB,
CC_USERS,
CC_DISCMDS,
CC_EXCMDS,
CC_SCALARS,
CC_READONLYS,
CC_SPECIALS,
CC_DELETE,
CC_NAMED,
CC_QUOTEFLAG,
CC_EXTCMDS,
CC_RESWDS,
CC_DIRS,
CC_EXPANDEXPL,
CC_RESERVED,
];
let or_all: u64 = all.iter().fold(0, |acc, &v| acc | v);
let expected = ((1u64 << 29) - 1) | (1u64 << 30) | (1u64 << 31);
assert_eq!(
or_all, expected,
"primary CC_* must cover bits 0..28 + 30 + 31 (bit 29 reserved)"
);
}
#[test]
fn cc_primary_flags_pairwise_distinct() {
let codes = [
CC_FILES,
CC_COMMPATH,
CC_REMOVE,
CC_OPTIONS,
CC_VARS,
CC_BINDINGS,
CC_ARRAYS,
CC_INTVARS,
CC_SHFUNCS,
CC_PARAMS,
CC_ENVVARS,
CC_JOBS,
CC_RUNNING,
CC_STOPPED,
CC_BUILTINS,
CC_ALREG,
CC_ALGLOB,
CC_USERS,
CC_DISCMDS,
CC_EXCMDS,
CC_SCALARS,
CC_READONLYS,
CC_SPECIALS,
CC_DELETE,
CC_NAMED,
CC_QUOTEFLAG,
CC_EXTCMDS,
CC_RESWDS,
CC_DIRS,
CC_EXPANDEXPL,
CC_RESERVED,
];
let unique: std::collections::HashSet<_> = codes.iter().copied().collect();
assert_eq!(
unique.len(),
codes.len(),
"primary CC_* must be pairwise distinct"
);
}
#[test]
fn cc_primary_all_non_zero() {
for &v in &[
CC_FILES,
CC_COMMPATH,
CC_REMOVE,
CC_OPTIONS,
CC_DIRS,
CC_EXPANDEXPL,
CC_RESERVED,
] {
assert!(v > 0, "CC_* primary must be > 0; got {}", v);
}
}
#[test]
fn cc_secondary_all_non_zero() {
for &v in &[
CC_NOSORT, CC_XORCONT, CC_CCCONT, CC_PATCONT, CC_DEFCONT, CC_UNIQCON, CC_UNIQALL,
] {
assert!(v > 0, "CC_* secondary must be > 0; got {}", v);
}
}
#[test]
fn cct_all_in_range_0_to_13() {
for &v in &[
CCT_UNUSED,
CCT_POS,
CCT_CURSTR,
CCT_CURPAT,
CCT_WORDSTR,
CCT_WORDPAT,
CCT_CURSUF,
CCT_CURPRE,
CCT_CURSUB,
CCT_CURSUBC,
CCT_NUMWORDS,
CCT_RANGESTR,
CCT_RANGEPAT,
CCT_QUOTE,
] {
assert!((0..=13).contains(&v), "CCT_* must be 0..=13, got {}", v);
}
}
#[test]
fn cct_pairwise_distinct() {
let codes = [
CCT_UNUSED,
CCT_POS,
CCT_CURSTR,
CCT_CURPAT,
CCT_WORDSTR,
CCT_WORDPAT,
CCT_CURSUF,
CCT_CURPRE,
CCT_CURSUB,
CCT_CURSUBC,
CCT_NUMWORDS,
CCT_RANGESTR,
CCT_RANGEPAT,
CCT_QUOTE,
];
let unique: std::collections::HashSet<_> = codes.iter().copied().collect();
assert_eq!(unique.len(), codes.len(), "CCT_* pairwise distinct");
}
#[test]
fn cct_unused_is_zero_sentinel_alt() {
assert_eq!(CCT_UNUSED, 0, "CCT_UNUSED must be 0 (sentinel)");
}
#[test]
fn cc_expandexpl_uses_bit_30_not_29() {
assert_eq!(
CC_EXPANDEXPL,
1u64 << 30,
"CC_EXPANDEXPL must use bit 30 (bit 29 reserved)"
);
}
#[test]
fn cc_secondary_in_low_7_bits() {
for &v in &[
CC_NOSORT, CC_XORCONT, CC_CCCONT, CC_PATCONT, CC_DEFCONT, CC_UNIQCON, CC_UNIQALL,
] {
assert!(
v < (1u64 << 7),
"CC_* secondary must be < (1<<7), got 0x{:x}",
v
);
}
}
#[test]
fn cc_primary_bit_29_is_reserved_gap() {
let codes = [
CC_FILES,
CC_COMMPATH,
CC_REMOVE,
CC_OPTIONS,
CC_VARS,
CC_BINDINGS,
CC_ARRAYS,
CC_INTVARS,
CC_SHFUNCS,
CC_PARAMS,
CC_ENVVARS,
CC_JOBS,
CC_RUNNING,
CC_STOPPED,
CC_BUILTINS,
CC_ALREG,
CC_ALGLOB,
CC_USERS,
CC_DISCMDS,
CC_EXCMDS,
CC_SCALARS,
CC_READONLYS,
CC_SPECIALS,
CC_DELETE,
CC_NAMED,
CC_QUOTEFLAG,
CC_EXTCMDS,
CC_RESWDS,
CC_DIRS,
CC_EXPANDEXPL,
CC_RESERVED,
];
for c in codes {
assert_ne!(
c,
1u64 << 29,
"no primary CC_* uses bit 29 (reserved); offending: 0x{:x}",
c
);
}
}
#[test]
fn cc_secondary_pairwise_distinct() {
let codes = [
CC_NOSORT, CC_XORCONT, CC_CCCONT, CC_PATCONT, CC_DEFCONT, CC_UNIQCON, CC_UNIQALL,
];
let unique: std::collections::HashSet<_> = codes.iter().copied().collect();
assert_eq!(
unique.len(),
codes.len(),
"secondary CC_* pairwise distinct"
);
}
#[test]
fn cc_secondary_or_covers_low_7_bits() {
let or_all =
CC_NOSORT | CC_XORCONT | CC_CCCONT | CC_PATCONT | CC_DEFCONT | CC_UNIQCON | CC_UNIQALL;
assert_eq!(
or_all,
(1u64 << 7) - 1,
"secondary CC_* must cover bits 0..6"
);
}
#[test]
fn cc_files_is_bit_zero_pin_alt2() {
assert_eq!(CC_FILES, 1u64, "CC_FILES must be bit 0");
}
#[test]
fn cc_nosort_is_bit_zero() {
assert_eq!(CC_NOSORT, 1u64, "CC_NOSORT must be bit 0 of secondary mask");
}
#[test]
fn cc_reserved_is_highest_bit_31() {
assert_eq!(CC_RESERVED, 1u64 << 31, "CC_RESERVED must be bit 31");
}
#[test]
fn cc_uniqall_is_bit_six() {
assert_eq!(CC_UNIQALL, 1u64 << 6, "CC_UNIQALL must be bit 6");
}
#[test]
fn cct_curstr_is_two() {
assert_eq!(CCT_CURSTR, 2);
}
}