aboutsummaryrefslogtreecommitdiff
path: root/crate_universe/src/utils/starlark/target_compatible_with.rs
blob: 9ee52b59828dea92118ac038c19f7d3c4fc23323 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use std::collections::BTreeSet;

use serde::ser::{SerializeMap, SerializeTupleStruct, Serializer};
use serde::Serialize;
use serde_starlark::{FunctionCall, MULTILINE};

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct TargetCompatibleWith {
    target_triples: BTreeSet<String>,
}

impl TargetCompatibleWith {
    pub fn new(target_triples: BTreeSet<String>) -> Self {
        TargetCompatibleWith { target_triples }
    }
}

impl Serialize for TargetCompatibleWith {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        // Output looks like:
        //
        //     select({
        //         "configuration": [],
        //         "//conditions:default": ["@platforms//:incompatible"],
        //     })

        let mut plus = serializer.serialize_tuple_struct("+", MULTILINE)?;

        struct SelectInner<'a>(&'a BTreeSet<String>);

        impl<'a> Serialize for SelectInner<'a> {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
            where
                S: Serializer,
            {
                let mut map = serializer.serialize_map(Some(MULTILINE))?;
                for cfg in self.0 {
                    map.serialize_entry(cfg, &[] as &[String])?;
                }
                map.serialize_entry(
                    "//conditions:default",
                    &["@platforms//:incompatible".to_owned()] as &[String],
                )?;
                map.end()
            }
        }

        plus.serialize_field(&FunctionCall::new(
            "select",
            [SelectInner(&self.target_triples)],
        ))?;

        plus.end()
    }
}

#[cfg(test)]
mod test {
    use super::*;

    use indoc::indoc;

    #[test]
    fn target_compatible_with() {
        let target_compatible_with = TargetCompatibleWith::new(BTreeSet::from([
            "@rules_rust//rust/platform:wasm32-unknown-unknown".to_owned(),
            "@rules_rust//rust/platform:wasm32-wasi".to_owned(),
            "@rules_rust//rust/platform:x86_64-apple-darwin".to_owned(),
            "@rules_rust//rust/platform:x86_64-pc-windows-msvc".to_owned(),
            "@rules_rust//rust/platform:x86_64-unknown-linux-gnu".to_owned(),
        ]));

        let expected_starlark = indoc! {r#"
            select({
                "@rules_rust//rust/platform:wasm32-unknown-unknown": [],
                "@rules_rust//rust/platform:wasm32-wasi": [],
                "@rules_rust//rust/platform:x86_64-apple-darwin": [],
                "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [],
                "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [],
                "//conditions:default": ["@platforms//:incompatible"],
            })
        "#};

        assert_eq!(
            target_compatible_with
                .serialize(serde_starlark::Serializer)
                .unwrap(),
            expected_starlark,
        );
    }
}