Skip to main content

oxihuman_core/
feature_gate.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5use std::collections::HashMap;
6
7pub struct FeatureGate {
8    pub enabled: HashMap<String, bool>,
9}
10
11impl FeatureGate {
12    pub fn new() -> Self {
13        FeatureGate {
14            enabled: HashMap::new(),
15        }
16    }
17}
18
19impl Default for FeatureGate {
20    fn default() -> Self {
21        Self::new()
22    }
23}
24
25pub fn new_feature_gate() -> FeatureGate {
26    FeatureGate::new()
27}
28
29pub fn gate_enable(g: &mut FeatureGate, feature: &str) {
30    g.enabled.insert(feature.to_string(), true);
31}
32
33pub fn gate_disable(g: &mut FeatureGate, feature: &str) {
34    g.enabled.insert(feature.to_string(), false);
35}
36
37pub fn gate_is_enabled(g: &FeatureGate, feature: &str) -> bool {
38    *g.enabled.get(feature).unwrap_or(&false)
39}
40
41pub fn gate_toggle(g: &mut FeatureGate, feature: &str) {
42    let current = *g.enabled.get(feature).unwrap_or(&false);
43    g.enabled.insert(feature.to_string(), !current);
44}
45
46pub fn gate_feature_count(g: &FeatureGate) -> usize {
47    g.enabled.len()
48}
49
50pub fn gate_clear(g: &mut FeatureGate) {
51    g.enabled.clear();
52}
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57
58    #[test]
59    fn test_new_empty() {
60        /* new gate has no features */
61        let g = new_feature_gate();
62        assert_eq!(gate_feature_count(&g), 0);
63    }
64
65    #[test]
66    fn test_enable_and_check() {
67        /* enable then check returns true */
68        let mut g = new_feature_gate();
69        gate_enable(&mut g, "dark_mode");
70        assert!(gate_is_enabled(&g, "dark_mode"));
71    }
72
73    #[test]
74    fn test_disable() {
75        /* disable sets feature to false */
76        let mut g = new_feature_gate();
77        gate_enable(&mut g, "beta");
78        gate_disable(&mut g, "beta");
79        assert!(!gate_is_enabled(&g, "beta"));
80    }
81
82    #[test]
83    fn test_unknown_feature_disabled() {
84        /* unknown feature is disabled by default */
85        let g = new_feature_gate();
86        assert!(!gate_is_enabled(&g, "unknown"));
87    }
88
89    #[test]
90    fn test_toggle() {
91        /* toggle flips state */
92        let mut g = new_feature_gate();
93        gate_toggle(&mut g, "x");
94        assert!(gate_is_enabled(&g, "x"));
95        gate_toggle(&mut g, "x");
96        assert!(!gate_is_enabled(&g, "x"));
97    }
98
99    #[test]
100    fn test_feature_count() {
101        /* count includes all registered features */
102        let mut g = new_feature_gate();
103        gate_enable(&mut g, "a");
104        gate_disable(&mut g, "b");
105        assert_eq!(gate_feature_count(&g), 2);
106    }
107
108    #[test]
109    fn test_clear() {
110        /* clear removes all features */
111        let mut g = new_feature_gate();
112        gate_enable(&mut g, "x");
113        gate_clear(&mut g);
114        assert_eq!(gate_feature_count(&g), 0);
115    }
116}