blob: 4d362c739afe01b185a03e5aabe2378eaf222a51 [file] [log] [blame]
Adam Snaider1c095c92023-07-08 02:09:58 -04001use serde::ser::{SerializeSeq, SerializeStruct, SerializeTupleStruct, Serializer};
2use serde::Serialize;
3use serde_starlark::{FunctionCall, MULTILINE, ONELINE};
4
5use super::{
6 Data, ExportsFiles, Load, Package, RustBinary, RustLibrary, RustProcMacro, SelectList,
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.
13pub fn rust_proc_macro<S>(rule: &RustProcMacro, serializer: S) -> Result<S::Ok, S::Error>
14where
15 S: Serializer,
16{
17 FunctionCall::new("rust_proc_macro", rule).serialize(serializer)
18}
19
20pub fn rust_library<S>(rule: &RustLibrary, serializer: S) -> Result<S::Ok, S::Error>
21where
22 S: Serializer,
23{
24 FunctionCall::new("rust_library", rule).serialize(serializer)
25}
26
27pub fn rust_binary<S>(rule: &RustBinary, serializer: S) -> Result<S::Ok, S::Error>
28where
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.
37pub struct MultilineArray<'a, A>(pub &'a A);
38
39impl<'a, A, T> Serialize for MultilineArray<'a, A>
40where
41 &'a A: IntoIterator<Item = &'a T>,
42 T: Serialize + 'a,
43{
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// TODO: This can go away after SelectList's derived Serialize impl (used by
57// tera) goes away and `serialize_starlark` becomes its real Serialize impl.
58#[derive(Serialize)]
59#[serde(transparent)]
60pub struct SelectListWrapper<'a, T: Ord + Serialize>(
61 #[serde(serialize_with = "SelectList::serialize_starlark")] &'a SelectList<T>,
62);
63
64impl Serialize for Load {
65 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
66 where
67 S: Serializer,
68 {
69 let line = if self.items.len() > 1 {
70 MULTILINE
71 } else {
72 ONELINE
73 };
74 let mut call = serializer.serialize_tuple_struct("load", line)?;
75 call.serialize_field(&self.bzl)?;
76 for item in &self.items {
77 call.serialize_field(item)?;
78 }
79 call.end()
80 }
81}
82
83impl Serialize for Package {
84 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
85 where
86 S: Serializer,
87 {
88 let mut call = serializer.serialize_struct("package", ONELINE)?;
89 call.serialize_field("default_visibility", &self.default_visibility)?;
90 call.end()
91 }
92}
93
94impl Serialize for ExportsFiles {
95 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
96 where
97 S: Serializer,
98 {
99 let mut call = serializer.serialize_tuple_struct("exports_files", MULTILINE)?;
100 call.serialize_field(&FunctionCall::new("+", (&self.paths, &self.globs)))?;
101 call.end()
102 }
103}
104
105impl Data {
106 pub fn is_empty(&self) -> bool {
107 self.glob.is_empty() && self.select.is_empty()
108 }
109}
110
111impl Serialize for Data {
112 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
113 where
114 S: Serializer,
115 {
116 let mut plus = serializer.serialize_tuple_struct("+", MULTILINE)?;
117 if !self.glob.is_empty() {
118 plus.serialize_field(&self.glob)?;
119 }
120 if !self.select.is_empty() || self.glob.is_empty() {
121 plus.serialize_field(&SelectListWrapper(&self.select))?;
122 }
123 plus.end()
124 }
125}