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