blob: 78e62ba095a517d0bff6676df06368fc94b13750 [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
107 /// flag value cache for enabled_rw
108 static ref CACHED_enabled_rw: bool = flags_rust::GetServerConfigurableFlag(
109 "aconfig_flags.aconfig_test",
110 "com.android.aconfig.test.enabled_rw",
111 "true") == "true";
112}
113
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000114impl FlagProvider {
115 /// query flag disabled_ro
116 pub fn disabled_ro(&self) -> bool {
117 false
118 }
119
120 /// query flag disabled_rw
121 pub fn disabled_rw(&self) -> bool {
Dennis Shen737b8e32023-11-08 19:58:47 +0000122 *CACHED_disabled_rw
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000123 }
124
Zhi Dou71f1b352023-08-21 22:49:46 +0000125 /// query flag enabled_fixed_ro
126 pub fn enabled_fixed_ro(&self) -> bool {
127 true
128 }
129
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000130 /// query flag enabled_ro
131 pub fn enabled_ro(&self) -> bool {
132 true
133 }
134
135 /// query flag enabled_rw
136 pub fn enabled_rw(&self) -> bool {
Dennis Shen737b8e32023-11-08 19:58:47 +0000137 *CACHED_enabled_rw
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000138 }
139}
140
141/// flag provider
142pub static PROVIDER: FlagProvider = FlagProvider;
143
144/// query flag disabled_ro
Mårten Kongstadf73b9632023-05-24 15:43:47 +0200145#[inline(always)]
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000146pub fn disabled_ro() -> bool {
Mårten Kongstadf73b9632023-05-24 15:43:47 +0200147 false
148}
149
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000150/// query flag disabled_rw
Mårten Kongstadf73b9632023-05-24 15:43:47 +0200151#[inline(always)]
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000152pub fn disabled_rw() -> bool {
153 PROVIDER.disabled_rw()
Mårten Kongstadf73b9632023-05-24 15:43:47 +0200154}
155
Zhi Dou71f1b352023-08-21 22:49:46 +0000156/// query flag enabled_fixed_ro
157#[inline(always)]
158pub fn enabled_fixed_ro() -> bool {
159 true
160}
161
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000162/// query flag enabled_ro
Mårten Kongstadf73b9632023-05-24 15:43:47 +0200163#[inline(always)]
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000164pub fn enabled_ro() -> bool {
Mårten Kongstadf73b9632023-05-24 15:43:47 +0200165 true
166}
167
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000168/// query flag enabled_rw
Mårten Kongstadf73b9632023-05-24 15:43:47 +0200169#[inline(always)]
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000170pub fn enabled_rw() -> bool {
171 PROVIDER.enabled_rw()
Mårten Kongstadf73b9632023-05-24 15:43:47 +0200172}
173"#;
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000174
175 const TEST_EXPECTED: &str = r#"
176//! codegenerated rust flag lib
177
178use std::collections::BTreeMap;
179use std::sync::Mutex;
180
181/// flag provider
182pub struct FlagProvider {
183 overrides: BTreeMap<&'static str, bool>,
184}
185
186impl FlagProvider {
187 /// query flag disabled_ro
188 pub fn disabled_ro(&self) -> bool {
189 self.overrides.get("disabled_ro").copied().unwrap_or(
190 false
191 )
192 }
193
194 /// set flag disabled_ro
195 pub fn set_disabled_ro(&mut self, val: bool) {
196 self.overrides.insert("disabled_ro", val);
197 }
198
199 /// query flag disabled_rw
200 pub fn disabled_rw(&self) -> bool {
201 self.overrides.get("disabled_rw").copied().unwrap_or(
202 flags_rust::GetServerConfigurableFlag(
Dennis Shenb352b9d2023-08-16 17:33:33 +0000203 "aconfig_flags.aconfig_test",
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000204 "com.android.aconfig.test.disabled_rw",
205 "false") == "true"
206 )
207 }
208
209 /// set flag disabled_rw
210 pub fn set_disabled_rw(&mut self, val: bool) {
211 self.overrides.insert("disabled_rw", val);
212 }
213
Zhi Dou71f1b352023-08-21 22:49:46 +0000214 /// query flag enabled_fixed_ro
215 pub fn enabled_fixed_ro(&self) -> bool {
216 self.overrides.get("enabled_fixed_ro").copied().unwrap_or(
217 true
218 )
219 }
220
221 /// set flag enabled_fixed_ro
222 pub fn set_enabled_fixed_ro(&mut self, val: bool) {
223 self.overrides.insert("enabled_fixed_ro", val);
224 }
225
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000226 /// query flag enabled_ro
227 pub fn enabled_ro(&self) -> bool {
228 self.overrides.get("enabled_ro").copied().unwrap_or(
229 true
230 )
231 }
232
233 /// set flag enabled_ro
234 pub fn set_enabled_ro(&mut self, val: bool) {
235 self.overrides.insert("enabled_ro", val);
236 }
237
238 /// query flag enabled_rw
239 pub fn enabled_rw(&self) -> bool {
240 self.overrides.get("enabled_rw").copied().unwrap_or(
241 flags_rust::GetServerConfigurableFlag(
Dennis Shenb352b9d2023-08-16 17:33:33 +0000242 "aconfig_flags.aconfig_test",
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000243 "com.android.aconfig.test.enabled_rw",
244 "true") == "true"
245 )
246 }
247
248 /// set flag enabled_rw
249 pub fn set_enabled_rw(&mut self, val: bool) {
250 self.overrides.insert("enabled_rw", val);
251 }
252
253 /// clear all flag overrides
254 pub fn reset_flags(&mut self) {
255 self.overrides.clear();
256 }
257}
258
259/// flag provider
260pub static PROVIDER: Mutex<FlagProvider> = Mutex::new(
261 FlagProvider {overrides: BTreeMap::new()}
262);
263
264/// query flag disabled_ro
265#[inline(always)]
266pub fn disabled_ro() -> bool {
267 PROVIDER.lock().unwrap().disabled_ro()
268}
269
270/// set flag disabled_ro
271#[inline(always)]
272pub fn set_disabled_ro(val: bool) {
273 PROVIDER.lock().unwrap().set_disabled_ro(val);
274}
275
276/// query flag disabled_rw
277#[inline(always)]
278pub fn disabled_rw() -> bool {
279 PROVIDER.lock().unwrap().disabled_rw()
280}
281
282/// set flag disabled_rw
283#[inline(always)]
284pub fn set_disabled_rw(val: bool) {
285 PROVIDER.lock().unwrap().set_disabled_rw(val);
286}
287
Zhi Dou71f1b352023-08-21 22:49:46 +0000288/// query flag enabled_fixed_ro
289#[inline(always)]
290pub fn enabled_fixed_ro() -> bool {
291 PROVIDER.lock().unwrap().enabled_fixed_ro()
292}
293
294/// set flag enabled_fixed_ro
295#[inline(always)]
296pub fn set_enabled_fixed_ro(val: bool) {
297 PROVIDER.lock().unwrap().set_enabled_fixed_ro(val);
298}
299
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000300/// query flag enabled_ro
301#[inline(always)]
302pub fn enabled_ro() -> bool {
303 PROVIDER.lock().unwrap().enabled_ro()
304}
305
306/// set flag enabled_ro
307#[inline(always)]
308pub fn set_enabled_ro(val: bool) {
309 PROVIDER.lock().unwrap().set_enabled_ro(val);
310}
311
312/// query flag enabled_rw
313#[inline(always)]
314pub fn enabled_rw() -> bool {
315 PROVIDER.lock().unwrap().enabled_rw()
316}
317
318/// set flag enabled_rw
319#[inline(always)]
320pub fn set_enabled_rw(val: bool) {
321 PROVIDER.lock().unwrap().set_enabled_rw(val);
322}
323
324/// clear all flag override
325pub fn reset_flags() {
326 PROVIDER.lock().unwrap().reset_flags()
327}
328"#;
329
330 fn test_generate_rust_code(mode: CodegenMode) {
331 let parsed_flags = crate::test::parse_test_flags();
332 let generated =
333 generate_rust_code(crate::test::TEST_PACKAGE, parsed_flags.parsed_flag.iter(), mode)
334 .unwrap();
335 assert_eq!("src/lib.rs", format!("{}", generated.path.display()));
Mårten Kongstadb0255072023-06-08 10:15:43 +0200336 assert_eq!(
337 None,
338 crate::test::first_significant_code_diff(
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000339 match mode {
340 CodegenMode::Production => PROD_EXPECTED,
341 CodegenMode::Test => TEST_EXPECTED,
342 },
Mårten Kongstadb0255072023-06-08 10:15:43 +0200343 &String::from_utf8(generated.contents).unwrap()
344 )
345 );
Mårten Kongstadf73b9632023-05-24 15:43:47 +0200346 }
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000347
348 #[test]
349 fn test_generate_rust_code_for_prod() {
350 test_generate_rust_code(CodegenMode::Production);
351 }
352
353 #[test]
354 fn test_generate_rust_code_for_test() {
355 test_generate_rust_code(CodegenMode::Test);
356 }
Mårten Kongstadf73b9632023-05-24 15:43:47 +0200357}