aconfig: Rust codegen 2nd iteration
Introduce rust codegen 2nd iteration with unit test support. The design
is described in detail in the design doc (go/aconfig_rust_codegen). The general idea is to generate
different code with the same signature for production and test build
targets, just like java/c/cpp codegen.
We will have a FlagProvider struct that has flag methods implementation.
This flag provider instance can then be used in injection pattern. In
additon, we also generate top level functions that wraps around flag
provider call so it can be used in static function style.
Things to be decided later:
should we just generate one set of code, and use cfg! as compile
time marco to compile the right code for the right targets.
Bug: b/279483360
Test: atest aconfig.test
Change-Id: Ic75cedbd0d27b5242014c3ac7fc80692d2ab4589
diff --git a/tools/aconfig/templates/rust.template b/tools/aconfig/templates/rust.template
deleted file mode 100644
index 960c494..0000000
--- a/tools/aconfig/templates/rust.template
+++ /dev/null
@@ -1,29 +0,0 @@
-{{- for mod in modules -}}
-pub mod {mod} \{
-{{ endfor -}}
-{{- for flag in template_flags -}}
-{{- if flag.is_read_only_disabled -}}
-#[inline(always)]
-pub const fn r#{flag.name}() -> bool \{
- false
-}
-
-{{ endif -}}
-{{- if flag.is_read_only_enabled -}}
-#[inline(always)]
-pub const fn r#{flag.name}() -> bool \{
- true
-}
-
-{{ endif -}}
-{{- if flag.is_read_write -}}
-#[inline(always)]
-pub fn r#{flag.name}() -> bool \{
- flags_rust::GetServerConfigurableFlag("{flag.device_config_namespace}", "{flag.device_config_flag}", "false") == "true"
-}
-
-{{ endif -}}
-{{- endfor -}}
-{{- for mod in modules -}}
-}
-{{ endfor -}}
diff --git a/tools/aconfig/templates/rust_prod.template b/tools/aconfig/templates/rust_prod.template
new file mode 100644
index 0000000..543107e
--- /dev/null
+++ b/tools/aconfig/templates/rust_prod.template
@@ -0,0 +1,38 @@
+//! codegenerated rust flag lib
+
+/// flag provider
+pub struct FlagProvider
+
+impl FlagProvider \{
+
+ {{ for flag in template_flags }}
+ /// query flag {flag.name}
+ pub fn {flag.name}(&self) -> bool \{
+ {{ if flag.readwrite -}}
+ flags_rust::GetServerConfigurableFlag(
+ "{flag.device_config_namespace}",
+ "{flag.device_config_flag}",
+ "{flag.default_value}") == "true"
+ {{ -else- }}
+ {flag.default_value}
+ {{ -endif }}
+ }
+ {{ endfor }}
+
+}
+
+/// flag provider
+pub static PROVIDER: FlagProvider = FlagProvider;
+
+{{ for flag in template_flags }}
+/// query flag {flag.name}
+#[inline(always)]
+{{ if flag.readwrite -}}
+pub fn {flag.name}() -> bool \{
+ PROVIDER.{flag.name}()
+{{ -else- }}
+pub fn {flag.name}() -> bool \{
+ {flag.default_value}
+{{ -endif }}
+}
+{{ endfor }}
diff --git a/tools/aconfig/templates/rust_test.template b/tools/aconfig/templates/rust_test.template
new file mode 100644
index 0000000..1e2c28a
--- /dev/null
+++ b/tools/aconfig/templates/rust_test.template
@@ -0,0 +1,61 @@
+//! codegenerated rust flag lib
+
+use std::collections::BTreeMap;
+use std::sync::Mutex;
+
+/// flag provider
+pub struct FlagProvider \{
+ overrides: BTreeMap<&'static str, bool>,
+}
+
+impl FlagProvider \{
+ {{ for flag in template_flags }}
+ /// query flag {flag.name}
+ pub fn {flag.name}(&self) -> bool \{
+ self.overrides.get("{flag.name}").copied().unwrap_or(
+ {{ if flag.readwrite -}}
+ flags_rust::GetServerConfigurableFlag(
+ "{flag.device_config_namespace}",
+ "{flag.device_config_flag}",
+ "{flag.default_value}") == "true"
+ {{ -else- }}
+ {flag.default_value}
+ {{ -endif }}
+ )
+ }
+
+ /// set flag {flag.name}
+ pub fn set_{flag.name}(&mut self, val: bool) \{
+ self.overrides.insert("{flag.name}", val);
+ }
+ {{ endfor }}
+
+ /// clear all flag overrides
+ pub fn reset_flags(&mut self) \{
+ self.overrides.clear();
+ }
+}
+
+/// flag provider
+pub static PROVIDER: Mutex<FlagProvider> = Mutex::new(
+ FlagProvider \{overrides: BTreeMap::new()}
+);
+
+{{ for flag in template_flags }}
+/// query flag {flag.name}
+#[inline(always)]
+pub fn {flag.name}() -> bool \{
+ PROVIDER.lock().unwrap().{flag.name}()
+}
+
+/// set flag {flag.name}
+#[inline(always)]
+pub fn set_{flag.name}(val: bool) \{
+ PROVIDER.lock().unwrap().set_{flag.name}(val);
+}
+{{ endfor }}
+
+/// clear all flag override
+pub fn reset_flags() \{
+ PROVIDER.lock().unwrap().reset_flags()
+}