blob: d8675e70314c936da0fabf37c580ed18ef8aeb3c [file] [log] [blame]
Mårten Kongstadf73b9632023-05-24 15:43:47 +02001/*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use anyhow::Result;
18use serde::Serialize;
19use tinytemplate::TinyTemplate;
20
Mårten Kongstad066575b2023-06-07 16:29:25 +020021use crate::codegen;
Dennis Shen3cfbcf52023-07-17 14:57:23 +000022use crate::commands::{CodegenMode, OutputFile};
Mårten Kongstad403658f2023-06-14 09:51:56 +020023use crate::protos::{ProtoFlagPermission, ProtoFlagState, ProtoParsedFlag};
Mårten Kongstadf73b9632023-05-24 15:43:47 +020024
Dennis Shen3cfbcf52023-07-17 14:57:23 +000025pub fn generate_rust_code<'a, I>(
26 package: &str,
27 parsed_flags_iter: I,
28 codegen_mode: CodegenMode,
29) -> Result<OutputFile>
Mårten Kongstad403658f2023-06-14 09:51:56 +020030where
31 I: Iterator<Item = &'a ProtoParsedFlag>,
32{
33 let template_flags: Vec<TemplateParsedFlag> =
34 parsed_flags_iter.map(|pf| TemplateParsedFlag::new(package, pf)).collect();
Dennis Shen737b8e32023-11-08 19:58:47 +000035 let has_readwrite = template_flags.iter().any(|item| item.readwrite);
Mårten Kongstadfbd71e22023-05-31 13:29:35 +020036 let context = TemplateContext {
37 package: package.to_string(),
Mårten Kongstad403658f2023-06-14 09:51:56 +020038 template_flags,
Mårten Kongstadfbd71e22023-05-31 13:29:35 +020039 modules: package.split('.').map(|s| s.to_string()).collect::<Vec<_>>(),
Dennis Shen737b8e32023-11-08 19:58:47 +000040 has_readwrite,
Mårten Kongstadfbd71e22023-05-31 13:29:35 +020041 };
Mårten Kongstadf73b9632023-05-24 15:43:47 +020042 let mut template = TinyTemplate::new();
Dennis Shen3cfbcf52023-07-17 14:57:23 +000043 template.add_template(
44 "rust_code_gen",
45 match codegen_mode {
46 CodegenMode::Production => include_str!("../templates/rust_prod.template"),
47 CodegenMode::Test => include_str!("../templates/rust_test.template"),
48 },
49 )?;
Mårten Kongstadf73b9632023-05-24 15:43:47 +020050 let contents = template.render("rust_code_gen", &context)?;
51 let path = ["src", "lib.rs"].iter().collect();
52 Ok(OutputFile { contents: contents.into(), path })
53}
54
55#[derive(Serialize)]
56struct TemplateContext {
Mårten Kongstad9fb58962023-05-31 13:02:13 +020057 pub package: String,
Mårten Kongstad403658f2023-06-14 09:51:56 +020058 pub template_flags: Vec<TemplateParsedFlag>,
Mårten Kongstadfbd71e22023-05-31 13:29:35 +020059 pub modules: Vec<String>,
Dennis Shen737b8e32023-11-08 19:58:47 +000060 pub has_readwrite: bool,
Mårten Kongstadf73b9632023-05-24 15:43:47 +020061}
62
63#[derive(Serialize)]
64struct TemplateParsedFlag {
Dennis Shen3cfbcf52023-07-17 14:57:23 +000065 pub readwrite: bool,
66 pub default_value: String,
Mårten Kongstadf73b9632023-05-24 15:43:47 +020067 pub name: String,
Mårten Kongstad066575b2023-06-07 16:29:25 +020068 pub device_config_namespace: String,
69 pub device_config_flag: String,
Mårten Kongstadf73b9632023-05-24 15:43:47 +020070}
71
Mårten Kongstad066575b2023-06-07 16:29:25 +020072impl TemplateParsedFlag {
Mårten Kongstadfbd71e22023-05-31 13:29:35 +020073 #[allow(clippy::nonminimal_bool)]
Mårten Kongstad403658f2023-06-14 09:51:56 +020074 fn new(package: &str, pf: &ProtoParsedFlag) -> Self {
Mårten Kongstadfbd71e22023-05-31 13:29:35 +020075 let template = TemplateParsedFlag {
Dennis Shen3cfbcf52023-07-17 14:57:23 +000076 readwrite: pf.permission() == ProtoFlagPermission::READ_WRITE,
77 default_value: match pf.state() {
78 ProtoFlagState::ENABLED => "true".to_string(),
79 ProtoFlagState::DISABLED => "false".to_string(),
80 },
Mårten Kongstad403658f2023-06-14 09:51:56 +020081 name: pf.name().to_string(),
82 device_config_namespace: pf.namespace().to_string(),
83 device_config_flag: codegen::create_device_config_ident(package, pf.name())
84 .expect("values checked at flag parse time"),
Mårten Kongstadfbd71e22023-05-31 13:29:35 +020085 };
Mårten Kongstadfbd71e22023-05-31 13:29:35 +020086 template
87 }
Mårten Kongstadf73b9632023-05-24 15:43:47 +020088}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
Mårten Kongstadf73b9632023-05-24 15:43:47 +020093
Dennis Shen3cfbcf52023-07-17 14:57:23 +000094 const PROD_EXPECTED: &str = r#"
95//! codegenerated rust flag lib
96
97/// flag provider
Mårten Kongstad2d5309c2023-07-20 11:33:19 +020098pub struct FlagProvider;
Dennis Shen3cfbcf52023-07-17 14:57:23 +000099
Dennis Shen737b8e32023-11-08 19:58:47 +0000100lazy_static::lazy_static! {
101 /// flag value cache for disabled_rw
102 static ref CACHED_disabled_rw: bool = flags_rust::GetServerConfigurableFlag(
103 "aconfig_flags.aconfig_test",
104 "com.android.aconfig.test.disabled_rw",
105 "false") == "true";
106
Mårten Kongstadbc76a3d2023-11-17 09:37:06 +0100107 /// flag value cache for disabled_rw_in_other_namespace
108 static ref CACHED_disabled_rw_in_other_namespace: bool = flags_rust::GetServerConfigurableFlag(
Ted Bauerc3073782023-11-15 18:04:54 +0000109 "aconfig_flags.other_namespace",
Mårten Kongstadbc76a3d2023-11-17 09:37:06 +0100110 "com.android.aconfig.test.disabled_rw_in_other_namespace",
Ted Bauerc3073782023-11-15 18:04:54 +0000111 "false") == "true";
112
Dennis Shen737b8e32023-11-08 19:58:47 +0000113 /// flag value cache for enabled_rw
114 static ref CACHED_enabled_rw: bool = flags_rust::GetServerConfigurableFlag(
115 "aconfig_flags.aconfig_test",
116 "com.android.aconfig.test.enabled_rw",
117 "true") == "true";
118}
119
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000120impl FlagProvider {
121 /// query flag disabled_ro
122 pub fn disabled_ro(&self) -> bool {
123 false
124 }
125
126 /// query flag disabled_rw
127 pub fn disabled_rw(&self) -> bool {
Dennis Shen737b8e32023-11-08 19:58:47 +0000128 *CACHED_disabled_rw
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000129 }
130
Mårten Kongstadbc76a3d2023-11-17 09:37:06 +0100131 /// query flag disabled_rw_in_other_namespace
132 pub fn disabled_rw_in_other_namespace(&self) -> bool {
133 *CACHED_disabled_rw_in_other_namespace
Ted Bauerc3073782023-11-15 18:04:54 +0000134 }
135
Zhi Dou71f1b352023-08-21 22:49:46 +0000136 /// query flag enabled_fixed_ro
137 pub fn enabled_fixed_ro(&self) -> bool {
138 true
139 }
140
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000141 /// query flag enabled_ro
142 pub fn enabled_ro(&self) -> bool {
143 true
144 }
145
146 /// query flag enabled_rw
147 pub fn enabled_rw(&self) -> bool {
Dennis Shen737b8e32023-11-08 19:58:47 +0000148 *CACHED_enabled_rw
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000149 }
150}
151
152/// flag provider
153pub static PROVIDER: FlagProvider = FlagProvider;
154
155/// query flag disabled_ro
Mårten Kongstadf73b9632023-05-24 15:43:47 +0200156#[inline(always)]
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000157pub fn disabled_ro() -> bool {
Mårten Kongstadf73b9632023-05-24 15:43:47 +0200158 false
159}
160
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000161/// query flag disabled_rw
Mårten Kongstadf73b9632023-05-24 15:43:47 +0200162#[inline(always)]
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000163pub fn disabled_rw() -> bool {
164 PROVIDER.disabled_rw()
Mårten Kongstadf73b9632023-05-24 15:43:47 +0200165}
166
Mårten Kongstadbc76a3d2023-11-17 09:37:06 +0100167/// query flag disabled_rw_in_other_namespace
Ted Bauerc3073782023-11-15 18:04:54 +0000168#[inline(always)]
Mårten Kongstadbc76a3d2023-11-17 09:37:06 +0100169pub fn disabled_rw_in_other_namespace() -> bool {
170 PROVIDER.disabled_rw_in_other_namespace()
Ted Bauerc3073782023-11-15 18:04:54 +0000171}
172
Zhi Dou71f1b352023-08-21 22:49:46 +0000173/// query flag enabled_fixed_ro
174#[inline(always)]
175pub fn enabled_fixed_ro() -> bool {
176 true
177}
178
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000179/// query flag enabled_ro
Mårten Kongstadf73b9632023-05-24 15:43:47 +0200180#[inline(always)]
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000181pub fn enabled_ro() -> bool {
Mårten Kongstadf73b9632023-05-24 15:43:47 +0200182 true
183}
184
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000185/// query flag enabled_rw
Mårten Kongstadf73b9632023-05-24 15:43:47 +0200186#[inline(always)]
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000187pub fn enabled_rw() -> bool {
188 PROVIDER.enabled_rw()
Mårten Kongstadf73b9632023-05-24 15:43:47 +0200189}
190"#;
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000191
192 const TEST_EXPECTED: &str = r#"
193//! codegenerated rust flag lib
194
195use std::collections::BTreeMap;
196use std::sync::Mutex;
197
198/// flag provider
199pub struct FlagProvider {
200 overrides: BTreeMap<&'static str, bool>,
201}
202
203impl FlagProvider {
204 /// query flag disabled_ro
205 pub fn disabled_ro(&self) -> bool {
206 self.overrides.get("disabled_ro").copied().unwrap_or(
207 false
208 )
209 }
210
211 /// set flag disabled_ro
212 pub fn set_disabled_ro(&mut self, val: bool) {
213 self.overrides.insert("disabled_ro", val);
214 }
215
216 /// query flag disabled_rw
217 pub fn disabled_rw(&self) -> bool {
218 self.overrides.get("disabled_rw").copied().unwrap_or(
219 flags_rust::GetServerConfigurableFlag(
Dennis Shenb352b9d2023-08-16 17:33:33 +0000220 "aconfig_flags.aconfig_test",
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000221 "com.android.aconfig.test.disabled_rw",
222 "false") == "true"
223 )
224 }
225
226 /// set flag disabled_rw
227 pub fn set_disabled_rw(&mut self, val: bool) {
228 self.overrides.insert("disabled_rw", val);
229 }
230
Mårten Kongstadbc76a3d2023-11-17 09:37:06 +0100231 /// query flag disabled_rw_in_other_namespace
232 pub fn disabled_rw_in_other_namespace(&self) -> bool {
233 self.overrides.get("disabled_rw_in_other_namespace").copied().unwrap_or(
Ted Bauerc3073782023-11-15 18:04:54 +0000234 flags_rust::GetServerConfigurableFlag(
235 "aconfig_flags.other_namespace",
Mårten Kongstadbc76a3d2023-11-17 09:37:06 +0100236 "com.android.aconfig.test.disabled_rw_in_other_namespace",
Ted Bauerc3073782023-11-15 18:04:54 +0000237 "false") == "true"
238 )
239 }
240
Mårten Kongstadbc76a3d2023-11-17 09:37:06 +0100241 /// set flag disabled_rw_in_other_namespace
242 pub fn set_disabled_rw_in_other_namespace(&mut self, val: bool) {
243 self.overrides.insert("disabled_rw_in_other_namespace", val);
Ted Bauerc3073782023-11-15 18:04:54 +0000244 }
245
Zhi Dou71f1b352023-08-21 22:49:46 +0000246 /// query flag enabled_fixed_ro
247 pub fn enabled_fixed_ro(&self) -> bool {
248 self.overrides.get("enabled_fixed_ro").copied().unwrap_or(
249 true
250 )
251 }
252
253 /// set flag enabled_fixed_ro
254 pub fn set_enabled_fixed_ro(&mut self, val: bool) {
255 self.overrides.insert("enabled_fixed_ro", val);
256 }
257
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000258 /// query flag enabled_ro
259 pub fn enabled_ro(&self) -> bool {
260 self.overrides.get("enabled_ro").copied().unwrap_or(
261 true
262 )
263 }
264
265 /// set flag enabled_ro
266 pub fn set_enabled_ro(&mut self, val: bool) {
267 self.overrides.insert("enabled_ro", val);
268 }
269
270 /// query flag enabled_rw
271 pub fn enabled_rw(&self) -> bool {
272 self.overrides.get("enabled_rw").copied().unwrap_or(
273 flags_rust::GetServerConfigurableFlag(
Dennis Shenb352b9d2023-08-16 17:33:33 +0000274 "aconfig_flags.aconfig_test",
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000275 "com.android.aconfig.test.enabled_rw",
276 "true") == "true"
277 )
278 }
279
280 /// set flag enabled_rw
281 pub fn set_enabled_rw(&mut self, val: bool) {
282 self.overrides.insert("enabled_rw", val);
283 }
284
285 /// clear all flag overrides
286 pub fn reset_flags(&mut self) {
287 self.overrides.clear();
288 }
289}
290
291/// flag provider
292pub static PROVIDER: Mutex<FlagProvider> = Mutex::new(
293 FlagProvider {overrides: BTreeMap::new()}
294);
295
296/// query flag disabled_ro
297#[inline(always)]
298pub fn disabled_ro() -> bool {
299 PROVIDER.lock().unwrap().disabled_ro()
300}
301
302/// set flag disabled_ro
303#[inline(always)]
304pub fn set_disabled_ro(val: bool) {
305 PROVIDER.lock().unwrap().set_disabled_ro(val);
306}
307
308/// query flag disabled_rw
309#[inline(always)]
310pub fn disabled_rw() -> bool {
311 PROVIDER.lock().unwrap().disabled_rw()
312}
313
314/// set flag disabled_rw
315#[inline(always)]
316pub fn set_disabled_rw(val: bool) {
317 PROVIDER.lock().unwrap().set_disabled_rw(val);
318}
319
Mårten Kongstadbc76a3d2023-11-17 09:37:06 +0100320/// query flag disabled_rw_in_other_namespace
Ted Bauerc3073782023-11-15 18:04:54 +0000321#[inline(always)]
Mårten Kongstadbc76a3d2023-11-17 09:37:06 +0100322pub fn disabled_rw_in_other_namespace() -> bool {
323 PROVIDER.lock().unwrap().disabled_rw_in_other_namespace()
Ted Bauerc3073782023-11-15 18:04:54 +0000324}
325
Mårten Kongstadbc76a3d2023-11-17 09:37:06 +0100326/// set flag disabled_rw_in_other_namespace
Ted Bauerc3073782023-11-15 18:04:54 +0000327#[inline(always)]
Mårten Kongstadbc76a3d2023-11-17 09:37:06 +0100328pub fn set_disabled_rw_in_other_namespace(val: bool) {
329 PROVIDER.lock().unwrap().set_disabled_rw_in_other_namespace(val);
Ted Bauerc3073782023-11-15 18:04:54 +0000330}
331
Zhi Dou71f1b352023-08-21 22:49:46 +0000332/// query flag enabled_fixed_ro
333#[inline(always)]
334pub fn enabled_fixed_ro() -> bool {
335 PROVIDER.lock().unwrap().enabled_fixed_ro()
336}
337
338/// set flag enabled_fixed_ro
339#[inline(always)]
340pub fn set_enabled_fixed_ro(val: bool) {
341 PROVIDER.lock().unwrap().set_enabled_fixed_ro(val);
342}
343
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000344/// query flag enabled_ro
345#[inline(always)]
346pub fn enabled_ro() -> bool {
347 PROVIDER.lock().unwrap().enabled_ro()
348}
349
350/// set flag enabled_ro
351#[inline(always)]
352pub fn set_enabled_ro(val: bool) {
353 PROVIDER.lock().unwrap().set_enabled_ro(val);
354}
355
356/// query flag enabled_rw
357#[inline(always)]
358pub fn enabled_rw() -> bool {
359 PROVIDER.lock().unwrap().enabled_rw()
360}
361
362/// set flag enabled_rw
363#[inline(always)]
364pub fn set_enabled_rw(val: bool) {
365 PROVIDER.lock().unwrap().set_enabled_rw(val);
366}
367
368/// clear all flag override
369pub fn reset_flags() {
370 PROVIDER.lock().unwrap().reset_flags()
371}
372"#;
373
374 fn test_generate_rust_code(mode: CodegenMode) {
375 let parsed_flags = crate::test::parse_test_flags();
376 let generated =
377 generate_rust_code(crate::test::TEST_PACKAGE, parsed_flags.parsed_flag.iter(), mode)
378 .unwrap();
379 assert_eq!("src/lib.rs", format!("{}", generated.path.display()));
Mårten Kongstadb0255072023-06-08 10:15:43 +0200380 assert_eq!(
381 None,
382 crate::test::first_significant_code_diff(
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000383 match mode {
384 CodegenMode::Production => PROD_EXPECTED,
385 CodegenMode::Test => TEST_EXPECTED,
386 },
Mårten Kongstadb0255072023-06-08 10:15:43 +0200387 &String::from_utf8(generated.contents).unwrap()
388 )
389 );
Mårten Kongstadf73b9632023-05-24 15:43:47 +0200390 }
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000391
392 #[test]
393 fn test_generate_rust_code_for_prod() {
394 test_generate_rust_code(CodegenMode::Production);
395 }
396
397 #[test]
398 fn test_generate_rust_code_for_test() {
399 test_generate_rust_code(CodegenMode::Test);
400 }
Mårten Kongstadf73b9632023-05-24 15:43:47 +0200401}