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