• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use log::{error, info};
2 use paste::paste;
3 use std::sync::Mutex;
4 
5 macro_rules! init_flags {
6     (flags: { $($flag:ident),* }, dependencies: { $($parent:ident => $child:ident),* }) => {
7         #[derive(Default)]
8         struct InitFlags {
9             $($flag: bool,)*
10         }
11 
12         /// Sets all flags to true, for testing
13         pub fn set_all_for_testing() {
14             *FLAGS.lock().unwrap() = InitFlags { $($flag: true,)* };
15         }
16 
17         impl InitFlags {
18             fn parse(flags: Vec<String>) -> Self {
19                 $(let mut $flag = false;)*
20 
21                 for flag in flags {
22                     let values: Vec<&str> = flag.split("=").collect();
23                     if values.len() != 2 {
24                         error!("Bad flag {}, must be in <FLAG>=<VALUE> format", flag);
25                         continue;
26                     }
27 
28                     match values[0] {
29                         $(concat!("INIT_", stringify!($flag)) => $flag = values[1].parse().unwrap_or(false),)*
30                         _ => {}
31                     }
32                 }
33 
34                 Self { $($flag,)* }.reconcile()
35             }
36 
37             fn reconcile(mut self) -> Self {
38                 // Loop to ensure dependencies can be specified in any order
39                 loop {
40                     let mut any_change = false;
41                     $(if self.$parent && !self.$child {
42                         self.$child = true;
43                         any_change = true;
44                     })*
45 
46                     if !any_change {
47                         break;
48                     }
49                 }
50 
51                 // TODO: acl should not be off if l2cap is on, but need to reconcile legacy code
52                 if self.gd_l2cap {
53                     self.gd_acl = false;
54                     self.gd_hci = true;
55                 }
56 
57                 self
58             }
59 
60             fn log(&self) {
61                 info!(concat!("Flags loaded: ", $(stringify!($flag), "={} ",)*), $(self.$flag,)*);
62             }
63         }
64 
65         paste! {
66             $(
67                 #[allow(missing_docs)]
68                 pub fn [<$flag _is_enabled>]() -> bool {
69                     FLAGS.lock().unwrap().$flag
70                 }
71             )*
72         }
73     };
74 }
75 
76 init_flags!(
77     flags: {
78         gd_core,
79         gd_advertising,
80         gd_scanning,
81         gd_security,
82         gd_acl,
83         gd_l2cap,
84         gd_hci,
85         gd_controller,
86         gatt_robust_caching,
87         btaa_hci,
88         gd_rust,
89         gd_link_policy
90     },
91     dependencies: {
92         gd_core => gd_security,
93         gd_security => gd_acl,
94         gd_l2cap => gd_scanning,
95         gd_scanning => gd_advertising,
96         gd_advertising => gd_acl,
97         gd_acl => gd_controller,
98         gd_controller => gd_hci,
99         gd_link_policy => gd_acl
100     }
101 );
102 
103 lazy_static! {
104     static ref FLAGS: Mutex<InitFlags> = Mutex::new(InitFlags::default());
105 }
106 
107 /// Loads the flag values from the passed-in vector of string values
load(flags: Vec<String>)108 pub fn load(flags: Vec<String>) {
109     crate::init_logging();
110 
111     let flags = InitFlags::parse(flags);
112     flags.log();
113     *FLAGS.lock().unwrap() = flags;
114 }
115