xref: /aosp_15_r20/external/bazelbuild-rules_rust/crate_universe/src/utils/starlark/serialize.rs (revision d4726bddaa87cc4778e7472feed243fa4b6c267f)
1 use serde::ser::{SerializeSeq, SerializeStruct, SerializeTupleStruct, Serializer};
2 use serde::Serialize;
3 use serde_starlark::{FunctionCall, MULTILINE, ONELINE};
4 
5 use super::{
6     Data, ExportsFiles, License, Load, Package, PackageInfo, RustBinary, RustLibrary, RustProcMacro,
7 };
8 
9 // For structs that contain #[serde(flatten)], a quirk of how Serde processes
10 // that attribute is that they get serialized as a map, not struct. In Starlark
11 // unlike in JSON, maps and structs are differently serialized, so we need to
12 // help fill in the function name or else we'd get a Starlark map instead.
rust_proc_macro<S>(rule: &RustProcMacro, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,13 pub(crate) fn rust_proc_macro<S>(rule: &RustProcMacro, serializer: S) -> Result<S::Ok, S::Error>
14 where
15     S: Serializer,
16 {
17     FunctionCall::new("rust_proc_macro", rule).serialize(serializer)
18 }
19 
rust_library<S>(rule: &RustLibrary, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,20 pub(crate) fn rust_library<S>(rule: &RustLibrary, serializer: S) -> Result<S::Ok, S::Error>
21 where
22     S: Serializer,
23 {
24     FunctionCall::new("rust_library", rule).serialize(serializer)
25 }
26 
rust_binary<S>(rule: &RustBinary, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,27 pub(crate) fn rust_binary<S>(rule: &RustBinary, serializer: S) -> Result<S::Ok, S::Error>
28 where
29     S: Serializer,
30 {
31     FunctionCall::new("rust_binary", rule).serialize(serializer)
32 }
33 
34 // Serialize an array with each element on its own line, even if there is just a
35 // single element which serde_starlark would ordinarily place on the same line
36 // as the array brackets.
37 pub(crate) struct MultilineArray<'a, A>(pub(crate) &'a A);
38 
39 impl<'a, A, T> Serialize for MultilineArray<'a, A>
40 where
41     &'a A: IntoIterator<Item = &'a T>,
42     T: Serialize + 'a,
43 {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,44     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
45     where
46         S: Serializer,
47     {
48         let mut array = serializer.serialize_seq(Some(serde_starlark::MULTILINE))?;
49         for element in self.0 {
50             array.serialize_element(element)?;
51         }
52         array.end()
53     }
54 }
55 
56 impl Serialize for Load {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,57     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
58     where
59         S: Serializer,
60     {
61         let line = if self.items.len() > 1 {
62             MULTILINE
63         } else {
64             ONELINE
65         };
66         let mut call = serializer.serialize_tuple_struct("load", line)?;
67         call.serialize_field(&self.bzl)?;
68         for item in &self.items {
69             call.serialize_field(item)?;
70         }
71         call.end()
72     }
73 }
74 
75 impl Serialize for Package {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,76     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
77     where
78         S: Serializer,
79     {
80         let has_metadata = !self.default_package_metadata.is_empty();
81         let mut call = serializer
82             .serialize_struct("package", if has_metadata { MULTILINE } else { ONELINE })?;
83         if has_metadata {
84             call.serialize_field("default_package_metadata", &self.default_package_metadata)?;
85         }
86         call.serialize_field("default_visibility", &self.default_visibility)?;
87         call.end()
88     }
89 }
90 
91 impl Serialize for PackageInfo {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,92     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
93     where
94         S: Serializer,
95     {
96         let mut call = serializer.serialize_struct("package_info", MULTILINE)?;
97         call.serialize_field("name", &self.name)?;
98         call.serialize_field("package_name", &self.package_name)?;
99         call.serialize_field("package_version", &self.package_version)?;
100         call.serialize_field("package_url", &self.package_url)?;
101         call.end()
102     }
103 }
104 
105 impl Serialize for License {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,106     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
107     where
108         S: Serializer,
109     {
110         let mut call = serializer.serialize_struct("license", MULTILINE)?;
111         call.serialize_field("name", &self.name)?;
112         call.serialize_field("license_kinds", &self.license_kinds)?;
113         if !self.license_text.is_empty() {
114             call.serialize_field("license_text", &self.license_text)?;
115         }
116         call.end()
117     }
118 }
119 
120 impl Serialize for ExportsFiles {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,121     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
122     where
123         S: Serializer,
124     {
125         let mut call = serializer.serialize_tuple_struct("exports_files", MULTILINE)?;
126         call.serialize_field(&FunctionCall::new("+", (&self.paths, &self.globs)))?;
127         call.end()
128     }
129 }
130 
131 impl Data {
is_empty(&self) -> bool132     pub(crate) fn is_empty(&self) -> bool {
133         self.glob.has_any_include() && self.select.is_empty()
134     }
135 }
136 
137 impl Serialize for Data {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,138     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
139     where
140         S: Serializer,
141     {
142         let mut plus = serializer.serialize_tuple_struct("+", MULTILINE)?;
143         if !self.glob.has_any_include() {
144             plus.serialize_field(&self.glob)?;
145         }
146         if !self.select.is_empty() || self.glob.has_any_include() {
147             plus.serialize_field(&self.select)?;
148         }
149         plus.end()
150     }
151 }
152