Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b24633b0 authored by Marybeth Fair's avatar Marybeth Fair Committed by Gerrit Code Review
Browse files

Merge "aconfig: implement fingerprint for rust" into main

parents a951ebf0 2670756d
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -23,6 +23,10 @@ rust_defaults {
        "libtinytemplate",
        "libconvert_finalized_flags",
    ],
    cfgs: select(release_flag("RELEASE_ACONFIG_FINGERPRINT_RUST"), {
        true: ["enable_fingerprint_rust"],
        default: [],
    }),
}

rust_binary_host {
+3 −0
Original line number Diff line number Diff line
@@ -25,3 +25,6 @@ itertools = "0.10.5"
serde = { version = "1.0.152", features = ["derive"] }
serde_json = "1.0.93"
convert_finalized_flags = { path = "../convert_finalized_flags" }

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(enable_fingerprint_rust)'] }
+62 −60
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ pub fn generate_rust_code<I>(
    flag_ids: HashMap<String, u16>,
    parsed_flags_iter: I,
    codegen_mode: CodegenMode,
    package_fingerprint: Option<u64>,
) -> Result<OutputFile>
where
    I: Iterator<Item = ProtoParsedFlag>,
@@ -40,12 +41,15 @@ where
        .collect();
    let has_readwrite = template_flags.iter().any(|item| item.readwrite);
    let container = (template_flags.first().expect("zero template flags").container).to_string();
    let use_package_fingerprint = package_fingerprint.is_some();
    let context = TemplateContext {
        package: package.to_string(),
        template_flags,
        modules: package.split('.').map(|s| s.to_string()).collect::<Vec<_>>(),
        has_readwrite,
        container,
        use_package_fingerprint,
        package_fingerprint: package_fingerprint.unwrap_or_default(),
    };
    let mut template = TinyTemplate::new();
    template.add_template(
@@ -69,6 +73,8 @@ struct TemplateContext {
    pub modules: Vec<String>,
    pub has_readwrite: bool,
    pub container: String,
    pub use_package_fingerprint: bool,
    pub package_fingerprint: u64,
}

#[derive(Serialize)]
@@ -131,10 +137,9 @@ use log::{log, LevelFilter, Level};
/// flag provider
pub struct FlagProvider;

static PACKAGE_OFFSET: LazyLock<Result<Option<u32>, AconfigStorageError>> = LazyLock::new(|| unsafe {
static PACKAGE_CONTEXT: LazyLock<Result<Option<PackageReadContext>, AconfigStorageError>> = LazyLock::new(|| unsafe {
    get_mapped_storage_file("system", StorageFileType::PackageMap)
    .and_then(|package_map| get_package_read_context(&package_map, "com.android.aconfig.test"))
    .map(|context| context.map(|c| c.boolean_start_index))
});

static FLAG_VAL_MAP: LazyLock<Result<Mmap, AconfigStorageError>> = LazyLock::new(|| unsafe {
@@ -153,13 +158,13 @@ static CACHED_disabled_rw: LazyLock<bool> = LazyLock::new(|| {
        .as_ref()
        .map_err(|err| format!("failed to get flag val map: {err}"))
        .and_then(|flag_val_map| {
            PACKAGE_OFFSET
            PACKAGE_CONTEXT
              .as_ref()
               .map_err(|err| format!("failed to get package read offset: {err}"))
               .and_then(|package_offset| {
                   match package_offset {
                       Some(offset) => {
                           get_boolean_flag_value(&flag_val_map, offset + 0)
               .map_err(|err| format!("failed to get package read context: {err}"))
               .and_then(|package_context| {
                   match package_context {
                       Some(context) => {
                           get_boolean_flag_value(&flag_val_map, context.boolean_start_index + 0)
                               .map_err(|err| format!("failed to get flag: {err}"))
                       },
                       None => {
@@ -193,13 +198,13 @@ static CACHED_disabled_rw_exported: LazyLock<bool> = LazyLock::new(|| {
            .as_ref()
            .map_err(|err| format!("failed to get flag val map: {err}"))
            .and_then(|flag_val_map| {
                PACKAGE_OFFSET
                PACKAGE_CONTEXT
                    .as_ref()
                    .map_err(|err| format!("failed to get package read offset: {err}"))
                    .and_then(|package_offset| {
                        match package_offset {
                            Some(offset) => {
                                get_boolean_flag_value(&flag_val_map, offset + 1)
                .map_err(|err| format!("failed to get package read context: {err}"))
                .and_then(|package_context| {
                    match package_context {
                        Some(context) => {
                           get_boolean_flag_value(&flag_val_map, context.boolean_start_index + 1)
                                    .map_err(|err| format!("failed to get flag: {err}"))
                            },
                            None => {
@@ -233,13 +238,13 @@ static CACHED_disabled_rw_in_other_namespace: LazyLock<bool> = LazyLock::new(||
            .as_ref()
            .map_err(|err| format!("failed to get flag val map: {err}"))
            .and_then(|flag_val_map| {
                PACKAGE_OFFSET
                PACKAGE_CONTEXT
                    .as_ref()
                    .map_err(|err| format!("failed to get package read offset: {err}"))
                    .and_then(|package_offset| {
                        match package_offset {
                            Some(offset) => {
                                get_boolean_flag_value(&flag_val_map, offset + 2)
                .map_err(|err| format!("failed to get package read context: {err}"))
                .and_then(|package_context| {
                    match package_context {
                        Some(context) => {
                           get_boolean_flag_value(&flag_val_map, context.boolean_start_index + 2)
                                    .map_err(|err| format!("failed to get flag: {err}"))
                            },
                            None => {
@@ -274,13 +279,13 @@ static CACHED_enabled_rw: LazyLock<bool> = LazyLock::new(|| {
            .as_ref()
            .map_err(|err| format!("failed to get flag val map: {err}"))
            .and_then(|flag_val_map| {
                PACKAGE_OFFSET
                PACKAGE_CONTEXT
                    .as_ref()
                    .map_err(|err| format!("failed to get package read offset: {err}"))
                    .and_then(|package_offset| {
                        match package_offset {
                            Some(offset) => {
                                get_boolean_flag_value(&flag_val_map, offset + 7)
                    .map_err(|err| format!("failed to get package read context: {err}"))
                    .and_then(|package_context| {
                      match package_context {
                            Some(context) => {
                              get_boolean_flag_value(&flag_val_map, context.boolean_start_index + 7)
                                      .map_err(|err| format!("failed to get flag: {err}"))
                            },
                            None => {
@@ -426,10 +431,9 @@ pub struct FlagProvider {
    overrides: BTreeMap<&'static str, bool>,
}

static PACKAGE_OFFSET: LazyLock<Result<Option<u32>, AconfigStorageError>> = LazyLock::new(|| unsafe {
static PACKAGE_CONTEXT: LazyLock<Result<Option<PackageReadContext>, AconfigStorageError>> = LazyLock::new(|| unsafe {
    get_mapped_storage_file("system", StorageFileType::PackageMap)
    .and_then(|package_map| get_package_read_context(&package_map, "com.android.aconfig.test"))
    .map(|context| context.map(|c| c.boolean_start_index))
});

static FLAG_VAL_MAP: LazyLock<Result<Mmap, AconfigStorageError>> = LazyLock::new(|| unsafe {
@@ -448,13 +452,13 @@ static CACHED_disabled_rw: LazyLock<bool> = LazyLock::new(|| {
        .as_ref()
        .map_err(|err| format!("failed to get flag val map: {err}"))
        .and_then(|flag_val_map| {
            PACKAGE_OFFSET
            PACKAGE_CONTEXT
               .as_ref()
               .map_err(|err| format!("failed to get package read offset: {err}"))
               .and_then(|package_offset| {
                   match package_offset {
                       Some(offset) => {
                           get_boolean_flag_value(&flag_val_map, offset + 0)
                    .map_err(|err| format!("failed to get package read context: {err}"))
                    .and_then(|package_context| {
                      match package_context {
                            Some(context) => {
                              get_boolean_flag_value(&flag_val_map, context.boolean_start_index + 0)
                               .map_err(|err| format!("failed to get flag: {err}"))
                       },
                       None => {
@@ -488,13 +492,13 @@ static CACHED_disabled_rw_exported: LazyLock<bool> = LazyLock::new(|| {
            .as_ref()
            .map_err(|err| format!("failed to get flag val map: {err}"))
            .and_then(|flag_val_map| {
                PACKAGE_OFFSET
                PACKAGE_CONTEXT
                    .as_ref()
                    .map_err(|err| format!("failed to get package read offset: {err}"))
                    .and_then(|package_offset| {
                        match package_offset {
                            Some(offset) => {
                                get_boolean_flag_value(&flag_val_map, offset + 1)
                    .map_err(|err| format!("failed to get package read context: {err}"))
                    .and_then(|package_context| {
                      match package_context {
                            Some(context) => {
                              get_boolean_flag_value(&flag_val_map, context.boolean_start_index + 1)
                                    .map_err(|err| format!("failed to get flag: {err}"))
                            },
                            None => {
@@ -528,13 +532,13 @@ static CACHED_disabled_rw_in_other_namespace: LazyLock<bool> = LazyLock::new(||
            .as_ref()
            .map_err(|err| format!("failed to get flag val map: {err}"))
            .and_then(|flag_val_map| {
                PACKAGE_OFFSET
                PACKAGE_CONTEXT
                    .as_ref()
                    .map_err(|err| format!("failed to get package read offset: {err}"))
                    .and_then(|package_offset| {
                        match package_offset {
                            Some(offset) => {
                                get_boolean_flag_value(&flag_val_map, offset + 2)
                    .map_err(|err| format!("failed to get package read context: {err}"))
                    .and_then(|package_context| {
                      match package_context {
                            Some(context) => {
                              get_boolean_flag_value(&flag_val_map, context.boolean_start_index + 2)
                                    .map_err(|err| format!("failed to get flag: {err}"))
                            },
                            None => {
@@ -569,13 +573,13 @@ static CACHED_enabled_rw: LazyLock<bool> = LazyLock::new(|| {
            .as_ref()
            .map_err(|err| format!("failed to get flag val map: {err}"))
            .and_then(|flag_val_map| {
                PACKAGE_OFFSET
                PACKAGE_CONTEXT
                    .as_ref()
                    .map_err(|err| format!("failed to get package read offset: {err}"))
                    .and_then(|package_offset| {
                        match package_offset {
                            Some(offset) => {
                                get_boolean_flag_value(&flag_val_map, offset + 7)
                    .map_err(|err| format!("failed to get package read context: {err}"))
                    .and_then(|package_context| {
                      match package_context {
                            Some(context) => {
                              get_boolean_flag_value(&flag_val_map, context.boolean_start_index + 7)
                                    .map_err(|err| format!("failed to get flag: {err}"))
                            },
                            None => {
@@ -926,15 +930,13 @@ pub fn enabled_rw() -> bool {
            flag_ids,
            modified_parsed_flags.into_iter(),
            mode,
            None,
        )
        .unwrap();
        assert_eq!("src/lib.rs", format!("{}", generated.path.display()));
        assert_eq!(
            None,
            crate::test::first_significant_code_diff(
        crate::test::assert_no_significant_code_diff(
            expected,
                &String::from_utf8(generated.contents).unwrap()
            )
            &String::from_utf8(generated.contents).unwrap(),
        );
    }

+17 −2
Original line number Diff line number Diff line
@@ -258,13 +258,28 @@ pub fn create_rust_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<Ou
        "Exported mode for generated rust flag library is disabled"
    );
    let parsed_flags = input.try_parse_flags()?;
    let modified_parsed_flags = modify_parsed_flags_based_on_mode(parsed_flags, codegen_mode)?;
    let modified_parsed_flags =
        modify_parsed_flags_based_on_mode(parsed_flags.clone(), codegen_mode)?;
    let Some(package) = find_unique_package(&modified_parsed_flags) else {
        bail!("no parsed flags, or the parsed flags use different packages");
    };
    let package = package.to_string();

    let package_fingerprint: Option<u64> = if cfg!(enable_fingerprint_rust) {
        let mut flag_names = extract_flag_names(parsed_flags)?;
        Some(compute_flags_fingerprint(&mut flag_names))
    } else {
        None
    };

    let flag_ids = assign_flag_ids(&package, modified_parsed_flags.iter())?;
    generate_rust_code(&package, flag_ids, modified_parsed_flags.into_iter(), codegen_mode)
    generate_rust_code(
        &package,
        flag_ids,
        modified_parsed_flags.into_iter(),
        codegen_mode,
        package_fingerprint,
    )
}

pub fn create_storage(
+24 −0
Original line number Diff line number Diff line
@@ -333,6 +333,30 @@ parsed_flag {
        }
    }

    /// Asserts that the two strings are equivalent. For use in tests. Fails
    /// with formatted error message for easier debugging.
    pub fn assert_no_significant_code_diff(expected: &str, actual: &str) {
        let expected =
            expected.lines().map(|line| line.trim_start()).filter(|line| !line.is_empty());
        let actual = actual.lines().map(|line| line.trim_start()).filter(|line| !line.is_empty());
        let fail_message: Option<String> =
            match itertools::diff_with(expected, actual, |left, right| left == right) {
                Some(itertools::Diff::FirstMismatch(_, mut left, mut right)) => Some(format!(
                    "DOES NOT MATCH: 1) expected, 2) actual:\n{}\n{}",
                    left.next().unwrap(),
                    right.next().unwrap()
                )),
                Some(itertools::Diff::Shorter(_, mut left)) => {
                    Some(format!("LHS trailing data: '{}'", left.next().unwrap()))
                }
                Some(itertools::Diff::Longer(_, mut right)) => {
                    Some(format!("RHS trailing data: '{}'", right.next().unwrap()))
                }
                None => None,
            };
        assert!(fail_message.is_none(), "{}", fail_message.unwrap());
    }

    #[test]
    fn test_first_significant_code_diff() {
        assert!(first_significant_code_diff("", "").is_none());
Loading