Adam Snaider | 1c095c9 | 2023-07-08 02:09:58 -0400 | [diff] [blame^] | 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, 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. |
| 13 | pub 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 | |
| 20 | pub 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 | |
| 27 | pub 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 struct MultilineArray<'a, A>(pub &'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 | { |
| 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)] |
| 60 | pub struct SelectListWrapper<'a, T: Ord + Serialize>( |
| 61 | #[serde(serialize_with = "SelectList::serialize_starlark")] &'a SelectList<T>, |
| 62 | ); |
| 63 | |
| 64 | impl 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 | |
| 83 | impl 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 | |
| 94 | impl 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 | |
| 105 | impl Data { |
| 106 | pub fn is_empty(&self) -> bool { |
| 107 | self.glob.is_empty() && self.select.is_empty() |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | impl 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 | } |