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