xref: /aosp_15_r20/external/bazelbuild-rules_rust/crate_universe/src/utils/starlark.rs (revision d4726bddaa87cc4778e7472feed243fa4b6c267f)
1 //! A module for representations of starlark constructs
2 
3 mod glob;
4 mod label;
5 mod select;
6 mod select_dict;
7 mod select_list;
8 mod select_scalar;
9 mod select_set;
10 mod serialize;
11 mod target_compatible_with;
12 
13 use std::collections::BTreeSet as Set;
14 
15 use serde::{Serialize, Serializer};
16 use serde_starlark::{Error as StarlarkError, FunctionCall};
17 
18 pub(crate) use glob::*;
19 pub(crate) use label::*;
20 pub(crate) use select::*;
21 pub(crate) use select_dict::*;
22 pub(crate) use select_list::*;
23 pub(crate) use select_scalar::*;
24 pub(crate) use select_set::*;
25 pub(crate) use target_compatible_with::*;
26 
27 #[derive(Serialize)]
28 #[serde(untagged)]
29 pub(crate) enum Starlark {
30     Load(Load),
31     Package(Package),
32     PackageInfo(PackageInfo),
33     License(License),
34     ExportsFiles(ExportsFiles),
35     Filegroup(Filegroup),
36     Alias(Alias),
37     CargoBuildScript(CargoBuildScript),
38     #[serde(serialize_with = "serialize::rust_proc_macro")]
39     RustProcMacro(RustProcMacro),
40     #[serde(serialize_with = "serialize::rust_library")]
41     RustLibrary(RustLibrary),
42     #[serde(serialize_with = "serialize::rust_binary")]
43     RustBinary(RustBinary),
44 
45     #[serde(skip_serializing)]
46     Verbatim(String),
47 }
48 
49 pub(crate) struct Load {
50     pub(crate) bzl: String,
51     pub(crate) items: Set<String>,
52 }
53 
54 pub(crate) struct Package {
55     pub(crate) default_package_metadata: Set<Label>,
56     pub(crate) default_visibility: Set<String>,
57 }
58 
59 pub(crate) struct PackageInfo {
60     pub(crate) name: String,
61     pub(crate) package_name: String,
62     pub(crate) package_url: String,
63     pub(crate) package_version: String,
64 }
65 
66 pub(crate) struct License {
67     pub(crate) name: String,
68     pub(crate) license_kinds: Set<String>,
69     pub(crate) license_text: String,
70 }
71 
72 pub(crate) struct ExportsFiles {
73     pub(crate) paths: Set<String>,
74     pub(crate) globs: Glob,
75 }
76 
77 #[derive(Serialize)]
78 #[serde(rename = "filegroup")]
79 pub(crate) struct Filegroup {
80     pub(crate) name: String,
81     pub(crate) srcs: Glob,
82 }
83 
84 pub(crate) struct Alias {
85     pub(crate) rule: String,
86     pub(crate) name: String,
87     pub(crate) actual: Label,
88     pub(crate) tags: Set<String>,
89 }
90 
91 #[derive(Serialize)]
92 #[serde(rename = "cargo_build_script")]
93 pub(crate) struct CargoBuildScript {
94     pub(crate) name: String,
95     #[serde(skip_serializing_if = "SelectDict::is_empty")]
96     pub(crate) aliases: SelectDict<Label, String>,
97     #[serde(skip_serializing_if = "SelectDict::is_empty")]
98     pub(crate) build_script_env: SelectDict<String, String>,
99     #[serde(skip_serializing_if = "Data::is_empty")]
100     pub(crate) compile_data: Data,
101     #[serde(skip_serializing_if = "SelectSet::is_empty")]
102     pub(crate) crate_features: SelectSet<String>,
103     pub(crate) crate_name: String,
104     #[serde(skip_serializing_if = "Option::is_none")]
105     pub(crate) crate_root: Option<String>,
106     #[serde(skip_serializing_if = "Data::is_empty")]
107     pub(crate) data: Data,
108     #[serde(skip_serializing_if = "SelectSet::is_empty")]
109     pub(crate) deps: SelectSet<Label>,
110     #[serde(skip_serializing_if = "SelectSet::is_empty")]
111     pub(crate) link_deps: SelectSet<Label>,
112     pub(crate) edition: String,
113     #[serde(skip_serializing_if = "Option::is_none")]
114     pub(crate) linker_script: Option<String>,
115     #[serde(skip_serializing_if = "Option::is_none")]
116     pub(crate) links: Option<String>,
117     #[serde(skip_serializing_if = "Option::is_none")]
118     pub(crate) pkg_name: Option<String>,
119     #[serde(skip_serializing_if = "SelectSet::is_empty")]
120     pub(crate) proc_macro_deps: SelectSet<Label>,
121     #[serde(skip_serializing_if = "SelectScalar::is_empty")]
122     pub(crate) rundir: SelectScalar<String>,
123     #[serde(skip_serializing_if = "SelectDict::is_empty")]
124     pub(crate) rustc_env: SelectDict<String, String>,
125     #[serde(skip_serializing_if = "SelectSet::is_empty")]
126     pub(crate) rustc_env_files: SelectSet<String>,
127     #[serde(skip_serializing_if = "SelectList::is_empty")]
128     pub(crate) rustc_flags: SelectList<String>,
129     pub(crate) srcs: Glob,
130     #[serde(skip_serializing_if = "Set::is_empty")]
131     pub(crate) tags: Set<String>,
132     #[serde(skip_serializing_if = "SelectSet::is_empty")]
133     pub(crate) tools: SelectSet<Label>,
134     #[serde(skip_serializing_if = "Set::is_empty")]
135     pub(crate) toolchains: Set<Label>,
136     pub(crate) version: String,
137     pub(crate) visibility: Set<String>,
138 }
139 
140 #[derive(Serialize)]
141 pub(crate) struct RustProcMacro {
142     pub(crate) name: String,
143     #[serde(skip_serializing_if = "SelectSet::is_empty")]
144     pub(crate) deps: SelectSet<Label>,
145     #[serde(skip_serializing_if = "SelectSet::is_empty")]
146     pub(crate) proc_macro_deps: SelectSet<Label>,
147     #[serde(skip_serializing_if = "SelectDict::is_empty")]
148     pub(crate) aliases: SelectDict<Label, String>,
149     #[serde(flatten)]
150     pub(crate) common: CommonAttrs,
151 }
152 
153 #[derive(Serialize)]
154 pub(crate) struct RustLibrary {
155     pub(crate) name: String,
156     #[serde(skip_serializing_if = "SelectSet::is_empty")]
157     pub(crate) deps: SelectSet<Label>,
158     #[serde(skip_serializing_if = "SelectSet::is_empty")]
159     pub(crate) proc_macro_deps: SelectSet<Label>,
160     #[serde(skip_serializing_if = "SelectDict::is_empty")]
161     pub(crate) aliases: SelectDict<Label, String>,
162     #[serde(flatten)]
163     pub(crate) common: CommonAttrs,
164     #[serde(skip_serializing_if = "std::ops::Not::not")]
165     pub(crate) disable_pipelining: bool,
166 }
167 
168 #[derive(Serialize)]
169 pub(crate) struct RustBinary {
170     pub(crate) name: String,
171     #[serde(skip_serializing_if = "SelectSet::is_empty")]
172     pub(crate) deps: SelectSet<Label>,
173     #[serde(skip_serializing_if = "SelectSet::is_empty")]
174     pub(crate) proc_macro_deps: SelectSet<Label>,
175     #[serde(skip_serializing_if = "SelectDict::is_empty")]
176     pub(crate) aliases: SelectDict<Label, String>,
177     #[serde(flatten)]
178     pub(crate) common: CommonAttrs,
179 }
180 
181 #[derive(Serialize)]
182 pub(crate) struct CommonAttrs {
183     #[serde(skip_serializing_if = "Data::is_empty")]
184     pub(crate) compile_data: Data,
185     #[serde(skip_serializing_if = "SelectSet::is_empty")]
186     pub(crate) crate_features: SelectSet<String>,
187     #[serde(skip_serializing_if = "Option::is_none")]
188     pub(crate) crate_root: Option<String>,
189     #[serde(skip_serializing_if = "Data::is_empty")]
190     pub(crate) data: Data,
191     pub(crate) edition: String,
192     #[serde(skip_serializing_if = "Option::is_none")]
193     pub(crate) linker_script: Option<String>,
194     #[serde(skip_serializing_if = "SelectDict::is_empty")]
195     pub(crate) rustc_env: SelectDict<String, String>,
196     #[serde(skip_serializing_if = "SelectSet::is_empty")]
197     pub(crate) rustc_env_files: SelectSet<String>,
198     #[serde(skip_serializing_if = "SelectList::is_empty")]
199     pub(crate) rustc_flags: SelectList<String>,
200     pub(crate) srcs: Glob,
201     #[serde(skip_serializing_if = "Set::is_empty")]
202     pub(crate) tags: Set<String>,
203     #[serde(skip_serializing_if = "Option::is_none")]
204     pub(crate) target_compatible_with: Option<TargetCompatibleWith>,
205     pub(crate) version: String,
206 }
207 
208 pub(crate) struct Data {
209     pub(crate) glob: Glob,
210     pub(crate) select: SelectSet<Label>,
211 }
212 
213 impl Package {
default_visibility_public(default_package_metadata: Set<Label>) -> Self214     pub(crate) fn default_visibility_public(default_package_metadata: Set<Label>) -> Self {
215         let mut default_visibility = Set::new();
216         default_visibility.insert("//visibility:public".to_owned());
217         Package {
218             default_package_metadata,
219             default_visibility,
220         }
221     }
222 }
223 
224 impl Serialize for Alias {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,225     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
226     where
227         S: Serializer,
228     {
229         // Output looks like:
230         //
231         //     rule(
232         //         name = "name",
233         //         actual = "actual",
234         //         tags = [
235         //            "tag1",
236         //            "tag2",
237         //         ],
238         //     )
239 
240         #[derive(Serialize)]
241         struct AliasInner<'a> {
242             pub(crate) name: &'a String,
243             pub(crate) actual: &'a Label,
244             pub(crate) tags: &'a Set<String>,
245         }
246 
247         FunctionCall::new(
248             &self.rule,
249             AliasInner {
250                 name: &self.name,
251                 actual: &self.actual,
252                 tags: &self.tags,
253             },
254         )
255         .serialize(serializer)
256     }
257 }
258 
serialize(starlark: &[Starlark]) -> Result<String, StarlarkError>259 pub(crate) fn serialize(starlark: &[Starlark]) -> Result<String, StarlarkError> {
260     let mut content = String::new();
261     for call in starlark {
262         if !content.is_empty() {
263             content.push('\n');
264         }
265         if let Starlark::Verbatim(comment) = call {
266             content.push_str(comment);
267         } else {
268             content.push_str(&serde_starlark::to_string(call)?);
269         }
270     }
271     Ok(content)
272 }
273