Skip to main content

oxihuman_core/
bitmask_flags.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5pub struct BitmaskFlags {
6    pub bits: u32,
7    pub names: Vec<String>,
8}
9
10pub fn new_bitmask_flags(names: Vec<&str>) -> BitmaskFlags {
11    BitmaskFlags {
12        bits: 0,
13        names: names.iter().map(|s| s.to_string()).collect(),
14    }
15}
16
17fn find_idx(f: &BitmaskFlags, name: &str) -> Option<usize> {
18    f.names.iter().position(|n| n == name)
19}
20
21pub fn bmf_set(f: &mut BitmaskFlags, name: &str) -> bool {
22    if let Some(i) = find_idx(f, name) {
23        f.bits |= 1 << i;
24        true
25    } else {
26        false
27    }
28}
29
30pub fn bmf_clear(f: &mut BitmaskFlags, name: &str) -> bool {
31    if let Some(i) = find_idx(f, name) {
32        f.bits &= !(1 << i);
33        true
34    } else {
35        false
36    }
37}
38
39pub fn bmf_test(f: &BitmaskFlags, name: &str) -> bool {
40    if let Some(i) = find_idx(f, name) {
41        (f.bits >> i) & 1 == 1
42    } else {
43        false
44    }
45}
46
47pub fn bmf_raw(f: &BitmaskFlags) -> u32 {
48    f.bits
49}
50
51pub fn bmf_set_by_index(f: &mut BitmaskFlags, idx: usize) {
52    if idx < f.names.len() {
53        f.bits |= 1 << idx;
54    }
55}
56
57pub fn bmf_count_set(f: &BitmaskFlags) -> u32 {
58    f.bits.count_ones()
59}
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64
65    #[test]
66    fn set_and_test() {
67        /* set a flag by name and test it */
68        let mut f = new_bitmask_flags(vec!["alpha", "beta", "gamma"]);
69        bmf_set(&mut f, "beta");
70        assert!(bmf_test(&f, "beta"));
71        assert!(!bmf_test(&f, "alpha"));
72    }
73
74    #[test]
75    fn clear_flag() {
76        /* clear resets a set flag */
77        let mut f = new_bitmask_flags(vec!["x"]);
78        bmf_set(&mut f, "x");
79        bmf_clear(&mut f, "x");
80        assert!(!bmf_test(&f, "x"));
81    }
82
83    #[test]
84    fn unknown_name_returns_false() {
85        /* unknown name returns false without panic */
86        let mut f = new_bitmask_flags(vec!["a"]);
87        assert!(!bmf_set(&mut f, "zzz"));
88    }
89
90    #[test]
91    fn raw_bits() {
92        /* raw bits match manual expectation */
93        let mut f = new_bitmask_flags(vec!["a", "b", "c"]);
94        bmf_set(&mut f, "a");
95        bmf_set(&mut f, "c");
96        assert_eq!(bmf_raw(&f), 0b101);
97    }
98
99    #[test]
100    fn set_by_index() {
101        /* set_by_index works like set by name */
102        let mut f = new_bitmask_flags(vec!["x", "y"]);
103        bmf_set_by_index(&mut f, 1);
104        assert!(bmf_test(&f, "y"));
105    }
106
107    #[test]
108    fn count_set() {
109        /* count_set returns number of 1-bits */
110        let mut f = new_bitmask_flags(vec!["a", "b", "c"]);
111        bmf_set(&mut f, "a");
112        bmf_set(&mut f, "b");
113        assert_eq!(bmf_count_set(&f), 2);
114    }
115
116    #[test]
117    fn initial_all_clear() {
118        /* all flags start cleared */
119        let f = new_bitmask_flags(vec!["p", "q"]);
120        assert_eq!(bmf_count_set(&f), 0);
121    }
122}