1 use std::collections::BTreeSet;
2 
3 use serde::ser::{SerializeMap, SerializeTupleStruct, Serializer};
4 use serde::Serialize;
5 use serde_starlark::{FunctionCall, MULTILINE};
6 
7 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
8 pub(crate) struct TargetCompatibleWith {
9     target_triples: BTreeSet<String>,
10 }
11 
12 impl TargetCompatibleWith {
new(target_triples: BTreeSet<String>) -> Self13     pub(crate) fn new(target_triples: BTreeSet<String>) -> Self {
14         TargetCompatibleWith { target_triples }
15     }
16 }
17 
18 impl Serialize for TargetCompatibleWith {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,19     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
20     where
21         S: Serializer,
22     {
23         // Output looks like:
24         //
25         //     select({
26         //         "configuration": [],
27         //         "//conditions:default": ["@platforms//:incompatible"],
28         //     })
29 
30         let mut plus = serializer.serialize_tuple_struct("+", MULTILINE)?;
31 
32         struct SelectInner<'a>(&'a BTreeSet<String>);
33 
34         impl<'a> Serialize for SelectInner<'a> {
35             fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
36             where
37                 S: Serializer,
38             {
39                 let mut map = serializer.serialize_map(Some(MULTILINE))?;
40                 for cfg in self.0 {
41                     map.serialize_entry(cfg, &[] as &[String])?;
42                 }
43                 map.serialize_entry(
44                     "//conditions:default",
45                     &["@platforms//:incompatible".to_owned()] as &[String],
46                 )?;
47                 map.end()
48             }
49         }
50 
51         plus.serialize_field(&FunctionCall::new(
52             "select",
53             [SelectInner(&self.target_triples)],
54         ))?;
55 
56         plus.end()
57     }
58 }
59 
60 #[cfg(test)]
61 mod test {
62     use super::*;
63 
64     use indoc::indoc;
65 
66     #[test]
target_compatible_with()67     fn target_compatible_with() {
68         let target_compatible_with = TargetCompatibleWith::new(BTreeSet::from([
69             "@rules_rust//rust/platform:wasm32-unknown-unknown".to_owned(),
70             "@rules_rust//rust/platform:wasm32-wasi".to_owned(),
71             "@rules_rust//rust/platform:x86_64-apple-darwin".to_owned(),
72             "@rules_rust//rust/platform:x86_64-pc-windows-msvc".to_owned(),
73             "@rules_rust//rust/platform:x86_64-unknown-linux-gnu".to_owned(),
74         ]));
75 
76         let expected_starlark = indoc! {r#"
77             select({
78                 "@rules_rust//rust/platform:wasm32-unknown-unknown": [],
79                 "@rules_rust//rust/platform:wasm32-wasi": [],
80                 "@rules_rust//rust/platform:x86_64-apple-darwin": [],
81                 "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [],
82                 "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [],
83                 "//conditions:default": ["@platforms//:incompatible"],
84             })
85         "#};
86 
87         assert_eq!(
88             target_compatible_with
89                 .serialize(serde_starlark::Serializer)
90                 .unwrap(),
91             expected_starlark,
92         );
93     }
94 }
95