blob: 0e377aa94f04ff0209c5d4cc7a4e0bca0e892917 [file] [log] [blame]
MÃ¥rten Kongstad4d2b4b02023-04-27 16:05:58 +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::{Context, Result};
18use clap::ValueEnum;
19use serde::{Deserialize, Serialize};
20use std::fmt;
21use std::io::Read;
22
23use crate::aconfig::{Flag, Override};
24use crate::cache::Cache;
25
26#[derive(Clone, Serialize, Deserialize)]
27pub enum Source {
28 #[allow(dead_code)] // only used in unit tests
29 Memory,
30 File(String),
31}
32
33impl fmt::Display for Source {
34 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
35 match self {
36 Self::Memory => write!(f, "<memory>"),
37 Self::File(path) => write!(f, "{}", path),
38 }
39 }
40}
41
42pub struct Input {
43 pub source: Source,
44 pub reader: Box<dyn Read>,
45}
46
47pub fn create_cache(aconfigs: Vec<Input>, overrides: Vec<Input>) -> Result<Cache> {
48 let mut cache = Cache::new();
49
50 for mut input in aconfigs {
51 let mut contents = String::new();
52 input.reader.read_to_string(&mut contents)?;
53 let flags = Flag::try_from_text_proto_list(&contents)
54 .with_context(|| format!("Failed to parse {}", input.source))?;
55 for flag in flags {
56 cache.add_flag(input.source.clone(), flag)?;
57 }
58 }
59
60 for mut input in overrides {
61 let mut contents = String::new();
62 input.reader.read_to_string(&mut contents)?;
63 let overrides = Override::try_from_text_proto_list(&contents)
64 .with_context(|| format!("Failed to parse {}", input.source))?;
65 for override_ in overrides {
66 cache.add_override(input.source.clone(), override_)?;
67 }
68 }
69
70 Ok(cache)
71}
72
73#[derive(Copy, Clone, Debug, PartialEq, Eq, ValueEnum)]
74pub enum Format {
75 Text,
76 Debug,
77}
78
79pub fn dump_cache(cache: Cache, format: Format) -> Result<()> {
80 match format {
81 Format::Text => {
82 for item in cache.iter() {
83 println!("{}: {}", item.id, item.value());
84 }
85 }
86 Format::Debug => {
87 for item in cache.iter() {
88 println!("{}: {}", item.id, item.value());
89 for value in &item.values {
90 println!(" {}: {}", value.source, value.value);
91 }
92 }
93 }
94 }
95 Ok(())
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101
102 #[test]
103 fn test_create_cache() {
104 let s = r#"
105 flag {
106 id: "a"
107 description: "Description of a"
108 value: true
109 }
110 "#;
111 let aconfigs = vec![Input { source: Source::Memory, reader: Box::new(s.as_bytes()) }];
112 let o = r#"
113 override {
114 id: "a"
115 value: false
116 }
117 "#;
118 let overrides = vec![Input { source: Source::Memory, reader: Box::new(o.as_bytes()) }];
119 let cache = create_cache(aconfigs, overrides).unwrap();
120 let value = cache.iter().find(|&item| item.id == "a").unwrap().value();
121 assert!(!value);
122 }
123}