pub const CGF_NOSORT: i32 = 1; pub const CGF_LINES: i32 = 2; pub const CGF_HASDL: i32 = 4; pub const CGF_UNIQALL: i32 = 8; pub const CGF_UNIQCON: i32 = 16; pub const CGF_PACKED: i32 = 32; pub const CGF_ROWS: i32 = 64; pub const CGF_FILES: i32 = 128; pub const CGF_MATSORT: i32 = 256; pub const CGF_NUMSORT: i32 = 512; pub const CGF_REVSORT: i32 = 1024;
pub const CMF_FILE: i32 = 1 << 0; pub const CMF_REMOVE: i32 = 1 << 1; pub const CMF_ISPAR: i32 = 1 << 2; pub const CMF_PARBR: i32 = 1 << 3; pub const CMF_PARNEST: i32 = 1 << 4; pub const CMF_NOLIST: i32 = 1 << 5; pub const CMF_DISPLINE: i32 = 1 << 6; pub const CMF_HIDE: i32 = 1 << 7; pub const CMF_NOSPACE: i32 = 1 << 8; pub const CMF_PACKED: i32 = 1 << 9; pub const CMF_ROWS: i32 = 1 << 10; pub const CMF_MULT: i32 = 1 << 11; pub const CMF_FMULT: i32 = 1 << 12; pub const CMF_ALL: i32 = 1 << 13; pub const CMF_DUMMY: i32 = 1 << 14; pub const CMF_MORDER: i32 = 1 << 15; pub const CMF_DELETE: i32 = 1 << 16;
pub const CMF_LINE: i32 = 1; pub const CMF_LEFT: i32 = 2; pub const CMF_RIGHT: i32 = 4; pub const CMF_INTER: i32 = 8;
pub const CPAT_CCLASS: i32 = 0; pub const CPAT_NCLASS: i32 = 1; pub const CPAT_EQUIV: i32 = 2; pub const CPAT_ANY: i32 = 3; pub const CPAT_CHAR: i32 = 4;
pub const CLF_MISS: i32 = 1; pub const CLF_DIFF: i32 = 2; pub const CLF_SUF: i32 = 4; pub const CLF_MID: i32 = 8; pub const CLF_NEW: i32 = 16; pub const CLF_LINE: i32 = 32; pub const CLF_JOIN: i32 = 64; pub const CLF_MATCHED: i32 = 128; pub const CLF_SKIP: i32 = 256;
pub const CAF_QUOTE: i32 = 1; pub const CAF_NOSORT: i32 = 2; pub const CAF_MATCH: i32 = 4; pub const CAF_UNIQCON: i32 = 8; pub const CAF_UNIQALL: i32 = 16; pub const CAF_ARRAYS: i32 = 32; pub const CAF_KEYS: i32 = 64; pub const CAF_ALL: i32 = 128; pub const CAF_MATSORT: i32 = 256; pub const CAF_NUMSORT: i32 = 512; pub const CAF_REVSORT: i32 = 1024;
pub const FC_LINE: i32 = 1; pub const FC_INWORD: i32 = 2;
pub const CPN_WORDS: i32 = 0; pub const CP_WORDS: u32 = 1 << CPN_WORDS; pub const CPN_REDIRS: i32 = 1; pub const CP_REDIRS: u32 = 1 << CPN_REDIRS; pub const CPN_CURRENT: i32 = 2; pub const CP_CURRENT: u32 = 1 << CPN_CURRENT; pub const CPN_PREFIX: i32 = 3; pub const CP_PREFIX: u32 = 1 << CPN_PREFIX; pub const CPN_SUFFIX: i32 = 4; pub const CP_SUFFIX: u32 = 1 << CPN_SUFFIX; pub const CPN_IPREFIX: i32 = 5; pub const CP_IPREFIX: u32 = 1 << CPN_IPREFIX; pub const CPN_ISUFFIX: i32 = 6; pub const CP_ISUFFIX: u32 = 1 << CPN_ISUFFIX; pub const CPN_QIPREFIX: i32 = 7; pub const CP_QIPREFIX: u32 = 1 << CPN_QIPREFIX; pub const CPN_QISUFFIX: i32 = 8; pub const CP_QISUFFIX: u32 = 1 << CPN_QISUFFIX; pub const CPN_COMPSTATE: i32 = 9; pub const CP_COMPSTATE: u32 = 1 << CPN_COMPSTATE;
pub const CP_REALPARAMS: i32 = 10;
pub const CP_ALLREALS: u32 = 0x3ff;
pub const CPN_NMATCHES: i32 = 0; pub const CP_NMATCHES: u32 = 1 << CPN_NMATCHES; pub const CPN_CONTEXT: i32 = 1; pub const CP_CONTEXT: u32 = 1 << CPN_CONTEXT; pub const CPN_PARAMETER: i32 = 2; pub const CP_PARAMETER: u32 = 1 << CPN_PARAMETER; pub const CPN_REDIRECT: i32 = 3; pub const CP_REDIRECT: u32 = 1 << CPN_REDIRECT; pub const CPN_QUOTE: i32 = 4; pub const CP_QUOTE: u32 = 1 << CPN_QUOTE; pub const CPN_QUOTING: i32 = 5; pub const CP_QUOTING: u32 = 1 << CPN_QUOTING; pub const CPN_RESTORE: i32 = 6; pub const CP_RESTORE: u32 = 1 << CPN_RESTORE; pub const CPN_LIST: i32 = 7; pub const CP_LIST: u32 = 1 << CPN_LIST; pub const CPN_INSERT: i32 = 8; pub const CP_INSERT: u32 = 1 << CPN_INSERT; pub const CPN_EXACT: i32 = 9; pub const CP_EXACT: u32 = 1 << CPN_EXACT; pub const CPN_EXACTSTR: i32 = 10; pub const CP_EXACTSTR: u32 = 1 << CPN_EXACTSTR; pub const CPN_PATMATCH: i32 = 11; pub const CP_PATMATCH: u32 = 1 << CPN_PATMATCH; pub const CPN_PATINSERT: i32 = 12; pub const CP_PATINSERT: u32 = 1 << CPN_PATINSERT; pub const CPN_UNAMBIG: i32 = 13; pub const CP_UNAMBIG: u32 = 1 << CPN_UNAMBIG; pub const CPN_UNAMBIGC: i32 = 14; pub const CP_UNAMBIGC: u32 = 1 << CPN_UNAMBIGC; pub const CPN_UNAMBIGP: i32 = 15; pub const CP_UNAMBIGP: u32 = 1 << CPN_UNAMBIGP; pub const CPN_INSERTP: i32 = 16; pub const CP_INSERTP: u32 = 1 << CPN_INSERTP; pub const CPN_LISTMAX: i32 = 17; pub const CP_LISTMAX: u32 = 1 << CPN_LISTMAX; pub const CPN_LASTPROMPT: i32 = 18; pub const CP_LASTPROMPT: u32 = 1 << CPN_LASTPROMPT; pub const CPN_TOEND: i32 = 19; pub const CP_TOEND: u32 = 1 << CPN_TOEND; pub const CPN_OLDLIST: i32 = 20; pub const CP_OLDLIST: u32 = 1 << CPN_OLDLIST; pub const CPN_OLDINS: i32 = 21; pub const CP_OLDINS: u32 = 1 << CPN_OLDINS; pub const CPN_VARED: i32 = 22; pub const CP_VARED: u32 = 1 << CPN_VARED; pub const CPN_LISTLINES: i32 = 23; pub const CP_LISTLINES: u32 = 1 << CPN_LISTLINES; pub const CPN_QUOTES: i32 = 24; pub const CP_QUOTES: u32 = 1 << CPN_QUOTES; pub const CPN_IGNORED: i32 = 25; pub const CP_IGNORED: u32 = 1 << CPN_IGNORED;
pub const CP_KEYPARAMS: i32 = 26;
pub const CP_ALLKEYS: u32 = 0x3ffffff;
pub const INSERTMATCHHOOK_OFFSET: usize = 0; pub const MENUSTARTHOOK_OFFSET: usize = 1; pub const COMPCTLMAKEHOOK_OFFSET: usize = 2; pub const COMPCTLCLEANUPHOOK_OFFSET: usize = 3; pub const COMPLISTMATCHESHOOK_OFFSET: usize = 4;
pub const CM_SPACE: i32 = 2;
#[derive(Debug, Clone, Default)]
#[allow(non_camel_case_types)]
pub struct Cexpl {
pub always: i32, pub str: Option<String>, pub count: i32, pub fcount: i32, }
#[derive(Debug, Clone, Default)]
#[allow(non_camel_case_types)]
pub struct Cmgroup {
pub name: Option<String>, pub prev: Option<Box<Cmgroup>>, pub next: Option<Box<Cmgroup>>, pub flags: i32, pub mcount: i32, pub matches: Vec<Cmatch>, pub lcount: i32, pub llcount: i32, pub ylist: Vec<String>, pub ecount: i32, pub expls: Vec<Cexpl>, pub ccount: i32, pub lexpls: Vec<Cexpl>, pub lmatches: Vec<Cmatch>, pub lfmatches: Vec<Cmatch>, pub lallccs: Vec<String>, pub num: i32, pub nbrbeg: i32, pub nbrend: i32, pub new_: i32, pub dcount: i32, pub cols: i32, pub lins: i32, pub width: i32, pub widths: Vec<i32>, pub totl: i32, pub shortest: i32, pub perm: Option<Box<Cmgroup>>, }
#[derive(Debug, Clone, Default)]
#[allow(non_camel_case_types)]
pub struct Brinfo {
pub next: Option<Box<Brinfo>>, pub prev: Option<Box<Brinfo>>, pub str: Option<String>, pub pos: i32, pub qpos: i32, pub curpos: i32, }
#[derive(Debug, Clone, Default)]
#[allow(non_camel_case_types)]
pub struct Cmatch {
pub str: Option<String>, pub orig: Option<String>, pub ipre: Option<String>, pub ripre: Option<String>, pub isuf: Option<String>, pub ppre: Option<String>, pub psuf: Option<String>, pub prpre: Option<String>, pub pre: Option<String>, pub suf: Option<String>, pub disp: Option<String>, pub autoq: Option<String>, pub flags: i32, pub brpl: Vec<i32>, pub brsl: Vec<i32>, pub rems: Option<String>, pub remf: Option<String>, pub qipl: i32, pub qisl: i32, pub rnum: i32, pub gnum: i32, pub mode: u32, pub modec: char, pub fmode: u32, pub fmodec: char, }
#[derive(Debug, Clone)]
#[allow(non_camel_case_types)]
pub struct Cmlist {
pub next: Option<Box<Cmlist>>, pub matcher: Box<Cmatcher>, pub str: String, }
#[derive(Debug, Clone, Default)]
#[allow(non_camel_case_types)]
pub struct Cmatcher {
pub refc: i32, pub next: Option<Box<Cmatcher>>, pub flags: i32, pub line: Option<Box<Cpattern>>, pub llen: i32, pub word: Option<Box<Cpattern>>, pub wlen: i32, pub left: Option<Box<Cpattern>>, pub lalen: i32, pub right: Option<Box<Cpattern>>, pub ralen: i32, }
#[derive(Debug, Clone, Default)]
#[allow(non_camel_case_types)]
pub struct Cpattern {
pub next: Option<Box<Cpattern>>, pub tp: i32, pub str: Option<Vec<u8>>, pub chr: u32, }
#[derive(Debug, Clone, Default)]
#[allow(non_camel_case_types)]
pub struct Cline {
pub next: Option<Box<Cline>>, pub flags: i32, pub line: Option<String>, pub llen: i32, pub word: Option<String>, pub wlen: i32, pub orig: Option<String>, pub olen: i32, pub slen: i32, pub prefix: Option<Box<Cline>>, pub suffix: Option<Box<Cline>>, pub min: i32, pub max: i32, }
#[derive(Debug, Clone, Default)]
#[allow(non_camel_case_types)]
pub struct Aminfo {
pub firstm: Option<Box<Cmatch>>, pub exact: i32, pub exactm: Option<Box<Cmatch>>, pub count: i32, pub line: Option<Box<Cline>>, }
#[derive(Debug, Clone, Default)]
#[allow(non_camel_case_types)]
pub struct Menuinfo {
pub group: Option<Box<Cmgroup>>, pub cur: Option<Box<Cmatch>>, pub pos: i32, pub len: i32, pub end: i32, pub we: i32, pub insc: i32, pub asked: i32, pub prebr: Option<String>, pub postbr: Option<String>, }
#[derive(Debug, Clone, Default)]
#[allow(non_camel_case_types)]
pub struct Ccmakedat {
pub str: Option<String>, pub incmd: i32, pub lst: i32, }
#[derive(Debug, Clone, Default)]
#[allow(non_camel_case_types)]
pub struct Chdata {
pub matches: Option<Box<Cmgroup>>, pub num: i32, pub nmesg: i32, pub cur: Option<Box<Cmatch>>, }
#[derive(Debug, Clone, Default)]
#[allow(non_camel_case_types)]
pub struct Cadata {
pub ipre: Option<String>, pub isuf: Option<String>, pub ppre: Option<String>, pub psuf: Option<String>, pub prpre: Option<String>, pub pre: Option<String>, pub suf: Option<String>, pub group: Option<String>, pub rems: Option<String>, pub remf: Option<String>, pub ign: Option<String>, pub flags: i32, pub aflags: i32, pub match_: Option<Box<Cmatcher>>, pub exp: Option<String>, pub apar: Option<String>, pub opar: Option<String>, pub dpar: Vec<String>, pub disp: Option<String>, pub mesg: Option<String>, pub dummies: i32, }
#[derive(Debug, Clone, Default)]
#[allow(non_camel_case_types)]
pub struct Cldata {
pub zterm_columns: i32, pub zterm_lines: i32, pub menuacc: i32, pub valid: i32, pub nlist: i32, pub nlines: i32, pub hidden: i32, pub onlyexpl: i32, pub showall: i32, }
#[cfg(test)]
mod tests {
use super::*;
use crate::ported::zle::zle_main::zle_test_setup;
#[test]
fn cgf_flags_correct() {
let _g = crate::test_util::global_state_lock();
let _g = zle_test_setup();
assert_eq!(CGF_NOSORT, 1);
assert_eq!(CGF_LINES, 2);
assert_eq!(CGF_HASDL, 4);
assert_eq!(CGF_REVSORT, 1024);
}
#[test]
fn cmf_match_flags_distinct() {
let _g = crate::test_util::global_state_lock();
let _g = zle_test_setup();
let all = CMF_FILE
| CMF_REMOVE
| CMF_ISPAR
| CMF_PARBR
| CMF_PARNEST
| CMF_NOLIST
| CMF_DISPLINE
| CMF_HIDE
| CMF_NOSPACE
| CMF_PACKED
| CMF_ROWS
| CMF_MULT
| CMF_FMULT
| CMF_ALL
| CMF_DUMMY
| CMF_MORDER
| CMF_DELETE;
assert_eq!(all.count_ones(), 17);
}
#[test]
fn cmf_matcher_flags_correct() {
let _g = crate::test_util::global_state_lock();
let _g = zle_test_setup();
assert_eq!(CMF_LINE, 1);
assert_eq!(CMF_LEFT, 2);
assert_eq!(CMF_RIGHT, 4);
assert_eq!(CMF_INTER, 8);
}
#[test]
fn cpat_enum_values_correct() {
let _g = crate::test_util::global_state_lock();
let _g = zle_test_setup();
assert_eq!(CPAT_CCLASS, 0);
assert_eq!(CPAT_NCLASS, 1);
assert_eq!(CPAT_EQUIV, 2);
assert_eq!(CPAT_ANY, 3);
assert_eq!(CPAT_CHAR, 4);
}
#[test]
fn cp_realparams_mask_covers_10_bits() {
let _g = crate::test_util::global_state_lock();
let _g = zle_test_setup();
assert_eq!(CP_REALPARAMS, 10);
assert_eq!(CP_ALLREALS, 0x3ff);
assert_eq!(CP_ALLREALS.count_ones(), 10);
assert_eq!(
CP_WORDS
| CP_REDIRS
| CP_CURRENT
| CP_PREFIX
| CP_SUFFIX
| CP_IPREFIX
| CP_ISUFFIX
| CP_QIPREFIX
| CP_QISUFFIX
| CP_COMPSTATE,
CP_ALLREALS
);
}
#[test]
fn cp_keyparams_mask_covers_26_bits() {
let _g = crate::test_util::global_state_lock();
let _g = zle_test_setup();
assert_eq!(CP_KEYPARAMS, 26);
assert_eq!(CP_ALLKEYS, 0x3ffffff);
assert_eq!(CP_ALLKEYS.count_ones(), 26);
}
#[test]
fn caf_flags_correct() {
let _g = crate::test_util::global_state_lock();
let _g = zle_test_setup();
assert_eq!(CAF_QUOTE, 1);
assert_eq!(CAF_NOSORT, 2);
assert_eq!(CAF_REVSORT, 1024);
}
#[test]
fn hook_offsets_sequential() {
let _g = crate::test_util::global_state_lock();
let _g = zle_test_setup();
assert_eq!(INSERTMATCHHOOK_OFFSET, 0);
assert_eq!(MENUSTARTHOOK_OFFSET, 1);
assert_eq!(COMPCTLMAKEHOOK_OFFSET, 2);
assert_eq!(COMPCTLCLEANUPHOOK_OFFSET, 3);
assert_eq!(COMPLISTMATCHESHOOK_OFFSET, 4);
}
#[test]
fn cm_space_is_2() {
let _g = crate::test_util::global_state_lock();
let _g = zle_test_setup();
assert_eq!(CM_SPACE, 2);
}
#[test]
fn structs_default_construct() {
let _g = crate::test_util::global_state_lock();
let _g = zle_test_setup();
let _ = Cexpl::default();
let _ = Cmgroup::default();
let _ = Cmatch::default();
let _ = Cmatcher::default();
let _ = Cpattern::default();
let _ = Cline::default();
let _ = Aminfo::default();
let _ = Menuinfo::default();
let _ = Ccmakedat::default();
let _ = Chdata::default();
let _ = Cadata::default();
let _ = Cldata::default();
}
#[test]
fn cgf_flags_match_c_comp_h_canonical_values() {
let _g = crate::test_util::global_state_lock();
assert_eq!(CGF_NOSORT, 1, "c:85");
assert_eq!(CGF_LINES, 2, "c:86");
assert_eq!(CGF_HASDL, 4, "c:87");
assert_eq!(CGF_UNIQALL, 8, "c:88");
assert_eq!(CGF_UNIQCON, 16, "c:89");
assert_eq!(CGF_PACKED, 32, "c:90");
assert_eq!(CGF_ROWS, 64, "c:91");
assert_eq!(CGF_FILES, 128, "c:92");
assert_eq!(CGF_MATSORT, 256, "c:93");
assert_eq!(CGF_NUMSORT, 512, "c:94");
assert_eq!(CGF_REVSORT, 1024, "c:95");
}
#[test]
fn cmf_match_flags_match_c_comp_h_canonical_values() {
let _g = crate::test_util::global_state_lock();
assert_eq!(CMF_FILE, 1 << 0, "c:127");
assert_eq!(CMF_REMOVE, 1 << 1, "c:128");
assert_eq!(CMF_ISPAR, 1 << 2, "c:129");
assert_eq!(CMF_PARBR, 1 << 3, "c:130");
assert_eq!(CMF_PARNEST, 1 << 4, "c:131");
assert_eq!(CMF_NOLIST, 1 << 5, "c:132");
assert_eq!(CMF_DISPLINE, 1 << 6, "c:133");
assert_eq!(CMF_HIDE, 1 << 7, "c:134");
assert_eq!(CMF_NOSPACE, 1 << 8, "c:135");
assert_eq!(CMF_PACKED, 1 << 9, "c:136");
assert_eq!(CMF_ROWS, 1 << 10, "c:137");
assert_eq!(CMF_MULT, 1 << 11, "c:138");
assert_eq!(CMF_FMULT, 1 << 12, "c:139");
assert_eq!(CMF_ALL, 1 << 13, "c:140");
assert_eq!(CMF_DUMMY, 1 << 14, "c:141");
assert_eq!(CMF_MORDER, 1 << 15, "c:142");
assert_eq!(CMF_DELETE, 1 << 16, "c:143");
}
#[test]
fn cgf_group_flags_are_distinct_single_bits() {
let _g = crate::test_util::global_state_lock();
let flags = [
CGF_NOSORT,
CGF_LINES,
CGF_HASDL,
CGF_UNIQALL,
CGF_UNIQCON,
CGF_PACKED,
CGF_ROWS,
CGF_FILES,
CGF_MATSORT,
CGF_NUMSORT,
CGF_REVSORT,
];
for &f in &flags {
assert_eq!(
(f as u32).count_ones(),
1,
"CGF flag {} = {:#x} must be a single bit",
f,
f
);
}
let mut all: u32 = 0;
for &f in &flags {
let bit = f as u32;
assert_eq!(
all & bit,
0,
"CGF flag {:#x} overlaps with existing bits",
bit
);
all |= bit;
}
}
#[test]
fn cmf_match_flags_are_distinct_single_bits() {
let _g = crate::test_util::global_state_lock();
let flags = [
CMF_FILE,
CMF_REMOVE,
CMF_ISPAR,
CMF_PARBR,
CMF_PARNEST,
CMF_NOLIST,
CMF_DISPLINE,
CMF_HIDE,
CMF_NOSPACE,
CMF_PACKED,
CMF_ROWS,
CMF_MULT,
CMF_FMULT,
CMF_ALL,
CMF_DUMMY,
CMF_MORDER,
CMF_DELETE,
];
for &f in &flags {
assert_eq!(
(f as u32).count_ones(),
1,
"CMF flag {} = {:#x} must be a single bit",
f,
f
);
}
let mut all: u32 = 0;
for &f in &flags {
let bit = f as u32;
assert_eq!(all & bit, 0, "CMF flag {:#x} overlaps", bit);
all |= bit;
}
}
#[test]
fn cgf_nosort_is_bit_zero() {
let _g = crate::test_util::global_state_lock();
assert_eq!(
CGF_NOSORT, 1,
"CGF_NOSORT must be bit 0 — the early-exit `!sort` test"
);
}
#[test]
fn cmf_file_is_bit_zero() {
let _g = crate::test_util::global_state_lock();
assert_eq!(
CMF_FILE, 1,
"CMF_FILE must be bit 0 — the file-match fast-path"
);
}
#[test]
fn cgf_top_flags_match_canonical_high_bits() {
let _g = crate::test_util::global_state_lock();
assert_eq!(CGF_PACKED, 32);
assert_eq!(CGF_ROWS, 64);
assert_eq!(CGF_FILES, 128);
assert_eq!(CGF_MATSORT, 256);
assert_eq!(CGF_NUMSORT, 512);
assert_eq!(CGF_REVSORT, 1024);
}
#[test]
fn cmf_low_byte_flags_are_single_bits() {
assert_eq!(CMF_FILE, 1);
assert_eq!(CMF_REMOVE, 2);
assert_eq!(CMF_ISPAR, 4);
assert_eq!(CMF_PARBR, 8);
assert_eq!(CMF_PARNEST, 16);
assert_eq!(CMF_NOLIST, 32);
assert_eq!(CMF_DISPLINE, 64);
assert_eq!(CMF_HIDE, 128);
}
#[test]
fn cmf_high_byte_flags_are_single_bits() {
assert_eq!(CMF_NOSPACE, 1 << 8);
assert_eq!(CMF_PACKED, 1 << 9);
assert_eq!(CMF_ROWS, 1 << 10);
assert_eq!(CMF_MULT, 1 << 11);
assert_eq!(CMF_FMULT, 1 << 12);
assert_eq!(CMF_ALL, 1 << 13);
assert_eq!(CMF_DUMMY, 1 << 14);
assert_eq!(CMF_MORDER, 1 << 15);
assert_eq!(CMF_DELETE, 1 << 16);
}
#[test]
fn cmf_match_flags_pairwise_disjoint() {
let flags = [
CMF_FILE,
CMF_REMOVE,
CMF_ISPAR,
CMF_PARBR,
CMF_PARNEST,
CMF_NOLIST,
CMF_DISPLINE,
CMF_HIDE,
CMF_NOSPACE,
CMF_PACKED,
CMF_ROWS,
CMF_MULT,
CMF_FMULT,
CMF_ALL,
CMF_DUMMY,
CMF_MORDER,
CMF_DELETE,
];
for i in 0..flags.len() {
for j in (i + 1)..flags.len() {
assert_eq!(
flags[i] & flags[j],
0,
"CMF_* flags {} and {} must not overlap",
flags[i],
flags[j]
);
}
}
}
#[test]
fn cgf_flags_pairwise_disjoint() {
let flags = [
CGF_NOSORT,
CGF_LINES,
CGF_HASDL,
CGF_UNIQALL,
CGF_UNIQCON,
CGF_PACKED,
CGF_ROWS,
CGF_FILES,
CGF_MATSORT,
CGF_NUMSORT,
];
for i in 0..flags.len() {
for j in (i + 1)..flags.len() {
assert_eq!(
flags[i] & flags[j],
0,
"CGF_* flags {} and {} must not overlap",
flags[i],
flags[j]
);
}
}
}
#[test]
fn cgf_low_bits_canonical() {
assert_eq!(CGF_NOSORT, 1);
assert_eq!(CGF_LINES, 2);
assert_eq!(CGF_HASDL, 4);
assert_eq!(CGF_UNIQALL, 8);
assert_eq!(CGF_UNIQCON, 16);
}
#[test]
fn cpat_enum_sequential_0_through_4() {
assert_eq!(CPAT_CCLASS, 0, "c:185");
assert_eq!(CPAT_NCLASS, 1, "c:186");
assert_eq!(CPAT_EQUIV, 2, "c:187");
assert_eq!(CPAT_ANY, 3, "c:188");
assert_eq!(CPAT_CHAR, 4, "c:189");
}
#[test]
fn cpat_enum_pairwise_distinct() {
let codes = [CPAT_CCLASS, CPAT_NCLASS, CPAT_EQUIV, CPAT_ANY, CPAT_CHAR];
let unique: std::collections::HashSet<_> = codes.iter().copied().collect();
assert_eq!(unique.len(), codes.len(), "CPAT_* must be distinct");
}
#[test]
fn clf_flags_are_single_bits() {
for &v in &[
CLF_MISS,
CLF_DIFF,
CLF_SUF,
CLF_MID,
CLF_NEW,
CLF_LINE,
CLF_JOIN,
CLF_MATCHED,
CLF_SKIP,
] {
assert!(
(v as u32).is_power_of_two(),
"CLF_* flag {} must be a single bit",
v
);
}
}
#[test]
fn clf_canonical_values() {
assert_eq!(CLF_MISS, 1, "c:259");
assert_eq!(CLF_DIFF, 2, "c:260");
assert_eq!(CLF_SUF, 4, "c:261");
assert_eq!(CLF_MID, 8, "c:262");
assert_eq!(CLF_NEW, 16, "c:263");
assert_eq!(CLF_LINE, 32, "c:264");
assert_eq!(CLF_JOIN, 64, "c:265");
assert_eq!(CLF_MATCHED, 128, "c:266");
assert_eq!(CLF_SKIP, 256, "c:267");
}
#[test]
fn clf_flags_pairwise_distinct() {
let codes = [
CLF_MISS,
CLF_DIFF,
CLF_SUF,
CLF_MID,
CLF_NEW,
CLF_LINE,
CLF_JOIN,
CLF_MATCHED,
CLF_SKIP,
];
let unique: std::collections::HashSet<_> = codes.iter().copied().collect();
assert_eq!(unique.len(), codes.len(), "CLF_* must be pairwise distinct");
}
#[test]
fn caf_canonical_values() {
assert_eq!(CAF_QUOTE, 1, "c:299");
assert_eq!(CAF_NOSORT, 2, "c:300");
assert_eq!(CAF_MATCH, 4, "c:301");
assert_eq!(CAF_UNIQCON, 8, "c:302");
}
#[test]
fn caf_flags_are_single_bits() {
for &v in &[CAF_QUOTE, CAF_NOSORT, CAF_MATCH, CAF_UNIQCON] {
assert!(
(v as u32).is_power_of_two(),
"CAF_* flag {} must be a single bit",
v
);
}
}
#[test]
fn cmf_secondary_canonical_values() {
assert_eq!(CMF_LINE, 1, "c:172");
assert_eq!(CMF_LEFT, 2, "c:174");
assert_eq!(CMF_RIGHT, 4, "c:176");
assert_eq!(CMF_INTER, 8, "c:178");
}
#[test]
fn cmf_secondary_flags_are_single_bits() {
for &v in &[CMF_LINE, CMF_LEFT, CMF_RIGHT, CMF_INTER] {
assert!(
(v as u32).is_power_of_two(),
"CMF secondary flag {} must be a single bit",
v
);
}
}
#[test]
fn cmf_main_flags_all_non_negative() {
for &v in &[
CMF_FILE,
CMF_REMOVE,
CMF_ISPAR,
CMF_PARBR,
CMF_PARNEST,
CMF_NOLIST,
CMF_DISPLINE,
CMF_HIDE,
CMF_NOSPACE,
CMF_PACKED,
CMF_ROWS,
CMF_MULT,
CMF_FMULT,
CMF_ALL,
CMF_DUMMY,
CMF_MORDER,
CMF_DELETE,
] {
assert!(v >= 0, "CMF_* flag {} must be ≥ 0", v);
}
}
#[test]
fn cgf_all_flags_are_single_bits() {
for &v in &[
CGF_NOSORT,
CGF_LINES,
CGF_HASDL,
CGF_UNIQALL,
CGF_UNIQCON,
CGF_PACKED,
CGF_ROWS,
CGF_FILES,
CGF_MATSORT,
CGF_NUMSORT,
CGF_REVSORT,
] {
assert!(
(v as u32).is_power_of_two(),
"CGF_* flag {} must be a single bit",
v
);
}
}
#[test]
fn cp_flags_match_cpn_shift_definition() {
assert_eq!(CP_WORDS, 1u32 << CPN_WORDS, "c:365");
assert_eq!(CP_REDIRS, 1u32 << CPN_REDIRS, "c:367");
assert_eq!(CP_CURRENT, 1u32 << CPN_CURRENT, "c:369");
assert_eq!(CP_PREFIX, 1u32 << CPN_PREFIX, "c:371");
assert_eq!(CP_SUFFIX, 1u32 << CPN_SUFFIX, "c:373");
}
#[test]
fn cp_high_bit_flags_match_cpn_shift_definition() {
assert_eq!(CP_UNAMBIGP, 1u32 << CPN_UNAMBIGP, "c:420");
assert_eq!(CP_INSERTP, 1u32 << CPN_INSERTP, "c:422");
assert_eq!(CP_LISTMAX, 1u32 << CPN_LISTMAX, "c:424");
assert_eq!(CP_LASTPROMPT, 1u32 << CPN_LASTPROMPT, "c:426");
assert_eq!(CP_TOEND, 1u32 << CPN_TOEND, "c:428");
assert_eq!(CP_OLDLIST, 1u32 << CPN_OLDLIST, "c:430");
assert_eq!(CP_OLDINS, 1u32 << CPN_OLDINS, "c:432");
assert_eq!(CP_VARED, 1u32 << CPN_VARED, "c:434");
assert_eq!(CP_LISTLINES, 1u32 << CPN_LISTLINES, "c:436");
assert_eq!(CP_QUOTES, 1u32 << CPN_QUOTES, "c:438");
assert_eq!(CP_IGNORED, 1u32 << CPN_IGNORED, "c:440");
}
#[test]
fn cpn_indices_pairwise_distinct_and_in_range() {
let cpns: Vec<i32> = vec![
CPN_WORDS,
CPN_REDIRS,
CPN_CURRENT,
CPN_PREFIX,
CPN_SUFFIX,
CPN_UNAMBIGP,
CPN_INSERTP,
CPN_LISTMAX,
CPN_LASTPROMPT,
CPN_TOEND,
CPN_OLDLIST,
CPN_OLDINS,
CPN_VARED,
CPN_LISTLINES,
CPN_QUOTES,
CPN_IGNORED,
];
let unique: std::collections::HashSet<_> = cpns.iter().copied().collect();
assert_eq!(unique.len(), cpns.len(), "CPN_* must be pairwise distinct");
for &v in &cpns {
assert!(
v >= 0 && v <= 25,
"CPN_* index {} must be in 0..=25 range",
v
);
}
}
#[test]
fn cp_allkeys_is_low_26_bits() {
assert_eq!(
CP_ALLKEYS,
(1u32 << 26) - 1,
"CP_ALLKEYS must be (1<<26)-1 = 0x3ffffff"
);
}
#[test]
fn cp_keyparams_count_matches_allkeys_bit_width() {
assert_eq!(
CP_KEYPARAMS, 26,
"CP_KEYPARAMS must equal CP_ALLKEYS bit count"
);
assert_eq!(
(CP_ALLKEYS + 1).trailing_zeros() as i32,
CP_KEYPARAMS,
"CP_ALLKEYS+1 leading bit position = CP_KEYPARAMS"
);
}
#[test]
fn hook_offsets_contiguous_zero_through_four() {
assert_eq!(INSERTMATCHHOOK_OFFSET, 0, "c:447");
assert_eq!(MENUSTARTHOOK_OFFSET, 1, "c:448");
assert_eq!(COMPCTLMAKEHOOK_OFFSET, 2, "c:449");
assert_eq!(COMPCTLCLEANUPHOOK_OFFSET, 3, "c:450");
assert_eq!(COMPLISTMATCHESHOOK_OFFSET, 4, "c:451");
}
#[test]
fn hook_offsets_pairwise_distinct() {
let offs = [
INSERTMATCHHOOK_OFFSET,
MENUSTARTHOOK_OFFSET,
COMPCTLMAKEHOOK_OFFSET,
COMPCTLCLEANUPHOOK_OFFSET,
COMPLISTMATCHESHOOK_OFFSET,
];
let unique: std::collections::HashSet<_> = offs.iter().copied().collect();
assert_eq!(
unique.len(),
offs.len(),
"hook offsets must be pairwise distinct"
);
}
#[test]
fn cm_space_canonical_value() {
assert_eq!(CM_SPACE, 2, "c:474");
}
#[test]
fn cpn_indices_fit_in_u32_shift() {
for &v in &[
CPN_WORDS,
CPN_REDIRS,
CPN_CURRENT,
CPN_PREFIX,
CPN_SUFFIX,
CPN_UNAMBIGP,
CPN_INSERTP,
CPN_LISTMAX,
CPN_LASTPROMPT,
CPN_TOEND,
CPN_OLDLIST,
CPN_OLDINS,
CPN_VARED,
CPN_LISTLINES,
CPN_QUOTES,
CPN_IGNORED,
] {
assert!((v as u32) < 32, "CPN_* index {} must fit u32 shift", v);
}
}
#[test]
fn hook_offsets_are_valid_usize_indices() {
let _: usize = INSERTMATCHHOOK_OFFSET;
let _: usize = MENUSTARTHOOK_OFFSET;
let _: usize = COMPCTLMAKEHOOK_OFFSET;
let _: usize = COMPCTLCLEANUPHOOK_OFFSET;
let _: usize = COMPLISTMATCHESHOOK_OFFSET;
}
#[test]
fn cp_allkeys_contains_endpoints() {
assert_eq!(
CP_WORDS & CP_ALLKEYS,
CP_WORDS,
"CP_WORDS (bit 0) ⊆ CP_ALLKEYS"
);
assert_eq!(
CP_IGNORED & CP_ALLKEYS,
CP_IGNORED,
"CP_IGNORED (bit 25) ⊆ CP_ALLKEYS"
);
}
#[test]
fn cgf_flags_all_i32_type() {
let _: i32 = CGF_NOSORT;
let _: i32 = CGF_LINES;
let _: i32 = CGF_REVSORT;
}
#[test]
fn cgf_flags_dense_low_bits() {
let all = [
CGF_NOSORT,
CGF_LINES,
CGF_HASDL,
CGF_UNIQALL,
CGF_UNIQCON,
CGF_PACKED,
CGF_ROWS,
CGF_FILES,
CGF_MATSORT,
CGF_NUMSORT,
CGF_REVSORT,
];
let or_all: i32 = all.iter().fold(0, |acc, &v| acc | v);
let expected = (1i32 << 11) - 1;
assert_eq!(or_all, expected, "CGF_* must cover bits 0..=10 (no gaps)");
}
#[test]
fn cgf_flags_all_powers_of_two() {
for &v in &[
CGF_NOSORT,
CGF_LINES,
CGF_HASDL,
CGF_UNIQALL,
CGF_UNIQCON,
CGF_PACKED,
CGF_ROWS,
CGF_FILES,
CGF_MATSORT,
CGF_NUMSORT,
CGF_REVSORT,
] {
assert!(
(v as u32).is_power_of_two(),
"CGF_* {} must be a single bit",
v
);
}
}
#[test]
fn cgf_flags_pairwise_distinct() {
let codes = [
CGF_NOSORT,
CGF_LINES,
CGF_HASDL,
CGF_UNIQALL,
CGF_UNIQCON,
CGF_PACKED,
CGF_ROWS,
CGF_FILES,
CGF_MATSORT,
CGF_NUMSORT,
CGF_REVSORT,
];
let unique: std::collections::HashSet<_> = codes.iter().copied().collect();
assert_eq!(unique.len(), codes.len(), "CGF_* must be pairwise distinct");
}
#[test]
fn cgf_nosort_is_bit_zero_alt() {
assert_eq!(CGF_NOSORT, 1, "c:85 — NOSORT is bit 0");
}
#[test]
fn cmf_flags_all_i32_type() {
let _: i32 = CMF_FILE;
let _: i32 = CMF_ALL;
}
#[test]
fn cmf_file_is_bit_zero_alt() {
assert_eq!(CMF_FILE, 1i32 << 0, "c:127 — FILE is bit 0");
}
#[test]
fn cmf_flags_dense_bits_zero_through_13() {
let all = [
CMF_FILE,
CMF_REMOVE,
CMF_ISPAR,
CMF_PARBR,
CMF_PARNEST,
CMF_NOLIST,
CMF_DISPLINE,
CMF_HIDE,
CMF_NOSPACE,
CMF_PACKED,
CMF_ROWS,
CMF_MULT,
CMF_FMULT,
CMF_ALL,
];
let or_all: i32 = all.iter().fold(0, |acc, &v| acc | v);
let expected = (1i32 << 14) - 1;
assert_eq!(or_all, expected, "CMF_* must cover bits 0..=13 (no gaps)");
}
#[test]
fn cmf_flags_pairwise_distinct() {
let codes = [
CMF_FILE,
CMF_REMOVE,
CMF_ISPAR,
CMF_PARBR,
CMF_PARNEST,
CMF_NOLIST,
CMF_DISPLINE,
CMF_HIDE,
CMF_NOSPACE,
CMF_PACKED,
CMF_ROWS,
CMF_MULT,
CMF_FMULT,
CMF_ALL,
];
let unique: std::collections::HashSet<_> = codes.iter().copied().collect();
assert_eq!(unique.len(), codes.len(), "CMF_* must be pairwise distinct");
}
#[test]
fn cmf_flags_all_powers_of_two() {
for &v in &[
CMF_FILE,
CMF_REMOVE,
CMF_ISPAR,
CMF_PARBR,
CMF_PARNEST,
CMF_NOLIST,
CMF_DISPLINE,
CMF_HIDE,
CMF_NOSPACE,
CMF_PACKED,
CMF_ROWS,
CMF_MULT,
CMF_FMULT,
CMF_ALL,
] {
assert!(
(v as u32).is_power_of_two(),
"CMF_* {} must be a single bit",
v
);
}
}
#[test]
fn cgf_flags_all_powers_of_two_alt() {
for &v in &[
CGF_NOSORT,
CGF_LINES,
CGF_HASDL,
CGF_UNIQALL,
CGF_UNIQCON,
CGF_PACKED,
CGF_ROWS,
CGF_FILES,
CGF_MATSORT,
CGF_NUMSORT,
CGF_REVSORT,
] {
assert!(
(v as u32).is_power_of_two(),
"CGF_* {} must be a single bit",
v
);
}
}
#[test]
fn cgf_flags_pairwise_distinct_alt() {
let codes = [
CGF_NOSORT,
CGF_LINES,
CGF_HASDL,
CGF_UNIQALL,
CGF_UNIQCON,
CGF_PACKED,
CGF_ROWS,
CGF_FILES,
CGF_MATSORT,
CGF_NUMSORT,
CGF_REVSORT,
];
let unique: std::collections::HashSet<_> = codes.iter().copied().collect();
assert_eq!(unique.len(), codes.len(), "CGF_* pairwise distinct");
}
#[test]
fn cgf_or_covers_low_11_bits() {
let or_all = CGF_NOSORT
| CGF_LINES
| CGF_HASDL
| CGF_UNIQALL
| CGF_UNIQCON
| CGF_PACKED
| CGF_ROWS
| CGF_FILES
| CGF_MATSORT
| CGF_NUMSORT
| CGF_REVSORT;
assert_eq!(
or_all,
(1i32 << 11) - 1,
"CGF_* must cover bits 0..=10 (no gaps)"
);
}
#[test]
fn cpat_values_sequential_0_to_4() {
assert_eq!(CPAT_CCLASS, 0);
assert_eq!(CPAT_NCLASS, 1);
assert_eq!(CPAT_EQUIV, 2);
assert_eq!(CPAT_ANY, 3);
assert_eq!(CPAT_CHAR, 4);
}
#[test]
fn cpat_pairwise_distinct() {
let codes = [CPAT_CCLASS, CPAT_NCLASS, CPAT_EQUIV, CPAT_ANY, CPAT_CHAR];
let unique: std::collections::HashSet<_> = codes.iter().copied().collect();
assert_eq!(unique.len(), codes.len(), "CPAT_* pairwise distinct");
}
#[test]
fn clf_flags_powers_of_two() {
for &v in &[CLF_MISS, CLF_DIFF, CLF_SUF] {
assert!(
(v as u32).is_power_of_two(),
"CLF_* {} must be a single bit",
v
);
}
}
#[test]
fn clf_flags_exact_values() {
assert_eq!(CLF_MISS, 1);
assert_eq!(CLF_DIFF, 2);
assert_eq!(CLF_SUF, 4);
}
#[test]
fn cp_equals_one_shift_cpn_duality() {
assert_eq!(CP_EXACTSTR, 1u32 << CPN_EXACTSTR);
assert_eq!(CP_PATMATCH, 1u32 << CPN_PATMATCH);
assert_eq!(CP_PATINSERT, 1u32 << CPN_PATINSERT);
assert_eq!(CP_UNAMBIG, 1u32 << CPN_UNAMBIG);
assert_eq!(CP_IGNORED, 1u32 << CPN_IGNORED);
assert_eq!(CP_TOEND, 1u32 << CPN_TOEND);
}
#[test]
fn cp_allkeys_covers_26_bits() {
assert_eq!(CP_ALLKEYS, 0x3ffffffu32);
assert_eq!(CP_ALLKEYS, (1u32 << 26) - 1, "26 bits set");
assert_eq!(CP_ALLKEYS.count_ones(), 26);
}
#[test]
fn hook_offsets_sequential_0_to_4() {
assert_eq!(INSERTMATCHHOOK_OFFSET, 0);
assert_eq!(MENUSTARTHOOK_OFFSET, 1);
assert_eq!(COMPCTLMAKEHOOK_OFFSET, 2);
assert_eq!(COMPCTLCLEANUPHOOK_OFFSET, 3);
assert_eq!(COMPLISTMATCHESHOOK_OFFSET, 4);
}
#[test]
fn hook_offsets_pairwise_distinct_alt() {
let codes = [
INSERTMATCHHOOK_OFFSET,
MENUSTARTHOOK_OFFSET,
COMPCTLMAKEHOOK_OFFSET,
COMPCTLCLEANUPHOOK_OFFSET,
COMPLISTMATCHESHOOK_OFFSET,
];
let unique: std::collections::HashSet<_> = codes.iter().copied().collect();
assert_eq!(unique.len(), codes.len(), "hook offsets pairwise distinct");
}
#[test]
fn cm_space_is_two() {
assert_eq!(CM_SPACE, 2);
}
#[test]
fn cmf_line_class_flags_are_powers_of_two() {
for &v in &[CMF_LINE, CMF_LEFT, CMF_RIGHT, CMF_INTER] {
assert!(
(v as u32).is_power_of_two(),
"CMF_* line/edge {} must be single bit",
v
);
}
}
}