1 use crate::{Flag, FlagPermission, FlagValue, ValuePickedFrom};
2 use aconfig_protos::ProtoFlagPermission as ProtoPermission;
3 use aconfig_protos::ProtoFlagState as ProtoState;
4 use aconfig_protos::ProtoParsedFlag;
5 use aconfig_protos::ProtoParsedFlags;
6 use anyhow::Result;
7 use std::fs;
8 use std::path::Path;
9 
10 // TODO(b/329875578): use container field directly instead of inferring.
infer_container(path: &Path) -> String11 fn infer_container(path: &Path) -> String {
12     let path_str = path.to_string_lossy();
13     path_str
14         .strip_prefix("/apex/")
15         .or_else(|| path_str.strip_prefix('/'))
16         .unwrap_or(&path_str)
17         .strip_suffix("/etc/aconfig_flags.pb")
18         .unwrap_or(&path_str)
19         .to_string()
20 }
21 
convert_parsed_flag(path: &Path, flag: &ProtoParsedFlag) -> Flag22 fn convert_parsed_flag(path: &Path, flag: &ProtoParsedFlag) -> Flag {
23     let namespace = flag.namespace().to_string();
24     let package = flag.package().to_string();
25     let name = flag.name().to_string();
26 
27     let value = match flag.state() {
28         ProtoState::ENABLED => FlagValue::Enabled,
29         ProtoState::DISABLED => FlagValue::Disabled,
30     };
31 
32     let permission = match flag.permission() {
33         ProtoPermission::READ_ONLY => FlagPermission::ReadOnly,
34         ProtoPermission::READ_WRITE => FlagPermission::ReadWrite,
35     };
36 
37     Flag {
38         namespace,
39         package,
40         name,
41         container: infer_container(path),
42         value,
43         staged_value: None,
44         permission,
45         value_picked_from: ValuePickedFrom::Default,
46     }
47 }
48 
load() -> Result<Vec<Flag>>49 pub(crate) fn load() -> Result<Vec<Flag>> {
50     let mut result = Vec::new();
51 
52     let paths = aconfig_device_paths::parsed_flags_proto_paths()?;
53     for path in paths {
54         let bytes = fs::read(path.clone())?;
55         let parsed_flags: ProtoParsedFlags = protobuf::Message::parse_from_bytes(&bytes)?;
56         for flag in parsed_flags.parsed_flag {
57             // TODO(b/334954748): enforce one-container-per-flag invariant.
58             result.push(convert_parsed_flag(&path, &flag));
59         }
60     }
61     Ok(result)
62 }
63