• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2022 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 use anyhow::Result;
16 use std::collections::BTreeMap;
17 
18 /// Build module.
19 pub struct BpModule {
20     module_type: String,
21     pub props: BpProperties,
22 }
23 
24 /// Properties of a build module, or of a nested object value.
25 #[derive(Clone, PartialEq, Eq)]
26 pub struct BpProperties {
27     map: BTreeMap<String, BpValue>,
28     /// A raw block of text to append after the last key-value pair, but before the closing brace.
29     /// For example, if you have the properties
30     ///
31     ///     {
32     ///         name: "foo",
33     ///         srcs: ["main.rs"],
34     ///     }
35     ///
36     /// and add `raw_block = "some random text"`, you'll get
37     ///
38     ///     {
39     ///         name: "foo",
40     ///         srcs: ["main.rs"],
41     ///         some random text
42     ///     }
43     pub raw_block: Option<String>,
44 }
45 
46 #[derive(Clone, PartialEq, Eq)]
47 pub enum BpValue {
48     Object(BpProperties),
49     Bool(bool),
50     String(String),
51     List(Vec<BpValue>),
52 }
53 
54 impl BpModule {
new(module_type: String) -> BpModule55     pub fn new(module_type: String) -> BpModule {
56         BpModule { module_type, props: BpProperties::new() }
57     }
58 
59     /// Serialize to Android.bp format.
write(&self, w: &mut impl std::fmt::Write) -> Result<()>60     pub fn write(&self, w: &mut impl std::fmt::Write) -> Result<()> {
61         w.write_str(&self.module_type)?;
62         w.write_str(" ")?;
63         self.props.write(w)?;
64         w.write_str("\n")?;
65         Ok(())
66     }
67 }
68 
69 impl BpProperties {
new() -> Self70     pub fn new() -> Self {
71         BpProperties { map: BTreeMap::new(), raw_block: None }
72     }
73 
get_string(&self, k: &str) -> &str74     pub fn get_string(&self, k: &str) -> &str {
75         match self.map.get(k).unwrap() {
76             BpValue::String(s) => s,
77             _ => unreachable!(),
78         }
79     }
80 
set<T: Into<BpValue>>(&mut self, k: &str, v: T)81     pub fn set<T: Into<BpValue>>(&mut self, k: &str, v: T) {
82         self.map.insert(k.to_string(), v.into());
83     }
84 
object(&mut self, k: &str) -> &mut BpProperties85     pub fn object(&mut self, k: &str) -> &mut BpProperties {
86         let v =
87             self.map.entry(k.to_string()).or_insert_with(|| BpValue::Object(BpProperties::new()));
88         match v {
89             BpValue::Object(v) => v,
90             _ => panic!("key {k:?} already has non-object value"),
91         }
92     }
93 
94     /// Serialize to Android.bp format.
write(&self, w: &mut impl std::fmt::Write) -> Result<()>95     pub fn write(&self, w: &mut impl std::fmt::Write) -> Result<()> {
96         w.write_str("{\n")?;
97         // Sort stuff to match what cargo2android.py's output order.
98         let canonical_order = &[
99             "name",
100             "defaults",
101             "stem",
102             "host_supported",
103             "prefer_rlib",
104             "crate_name",
105             "cargo_env_compat",
106             "cargo_pkg_version",
107             "srcs",
108             "test_suites",
109             "auto_gen_config",
110             "test_options",
111             "edition",
112             "features",
113             "rustlibs",
114             "proc_macros",
115             "static_libs",
116             "shared_libs",
117             "arch",
118             "target",
119             "ld_flags",
120             "apex_available",
121             "visibility",
122         ];
123         let mut props: Vec<(&String, &BpValue)> = self.map.iter().collect();
124         props.sort_by_key(|(k, _)| {
125             let i = canonical_order.iter().position(|x| k == x).unwrap_or(canonical_order.len());
126             (i, (*k).clone())
127         });
128         for (k, v) in props {
129             w.write_str(k)?;
130             w.write_str(": ")?;
131             v.write(w)?;
132             w.write_str(",\n")?;
133         }
134         if let Some(raw_block) = &self.raw_block {
135             w.write_str(raw_block)?;
136             w.write_str(",\n")?;
137         }
138         w.write_str("}")?;
139         Ok(())
140     }
141 }
142 
143 impl BpValue {
144     /// Serialize to Android.bp format.
write(&self, w: &mut impl std::fmt::Write) -> Result<()>145     pub fn write(&self, w: &mut impl std::fmt::Write) -> Result<()> {
146         match self {
147             BpValue::Object(p) => p.write(w)?,
148             BpValue::Bool(b) => write!(w, "{b}")?,
149             BpValue::String(s) => write!(w, "\"{s}\"")?,
150             BpValue::List(vs) => {
151                 w.write_str("[")?;
152                 for (i, v) in vs.iter().enumerate() {
153                     v.write(w)?;
154                     if i != vs.len() - 1 {
155                         w.write_str(", ")?;
156                     }
157                 }
158                 w.write_str("]")?;
159             }
160         }
161         Ok(())
162     }
163 }
164 
165 impl From<bool> for BpValue {
from(x: bool) -> Self166     fn from(x: bool) -> Self {
167         BpValue::Bool(x)
168     }
169 }
170 
171 impl From<&str> for BpValue {
from(x: &str) -> Self172     fn from(x: &str) -> Self {
173         BpValue::String(x.to_string())
174     }
175 }
176 
177 impl From<String> for BpValue {
from(x: String) -> Self178     fn from(x: String) -> Self {
179         BpValue::String(x)
180     }
181 }
182 
183 impl<T: Into<BpValue>> From<Vec<T>> for BpValue {
from(x: Vec<T>) -> Self184     fn from(x: Vec<T>) -> Self {
185         BpValue::List(x.into_iter().map(|x| x.into()).collect())
186     }
187 }
188