summaryrefslogtreecommitdiffstats
path: root/src/package/dependency/condition.rs
blob: df65a5c50e3d26f4a66738e822fe4b6aa2618a43 (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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
//
// Copyright (c) 2020-2021 science+computing ag and other contributors
//
// This program and the accompanying materials are made
// available under the terms of the Eclipse Public License 2.0
// which is available at https://www.eclipse.org/legal/epl-2.0/
//
// SPDX-License-Identifier: EPL-2.0
//

use std::collections::HashMap;

use serde::Deserialize;

use crate::util::EnvironmentVariableName;

/// The Condition type
///
/// This type represents a condition whether a dependency should be included in the package tree or
/// not.
///
/// Right now, we are supporting condition by environment (set or equal) or whether a specific
/// build image is used.
/// All these settings are optional, of course.
///
#[derive(Deserialize, Clone, Debug)]
pub struct Condition {
    #[serde(rename = "has_env", skip_serializing_if = "Option::is_none")]
    has_env: Option<OneOrMore<EnvironmentVariableName>>,

    #[serde(rename = "env_eq", skip_serializing_if = "Option::is_none")]
    env_eq: Option<HashMap<EnvironmentVariableName, String>>,

    #[serde(rename = "in_image", skip_serializing_if = "Option::is_none")]
    in_image: Option<OneOrMore<String>>,
}


/// Helper type for supporting Vec<T> and T in value
/// position of Condition
#[cfg_attr(test, derive(Eq, PartialEq))]
#[derive(Deserialize, Clone, Debug)]
#[serde(untagged)]
pub enum OneOrMore<T: Sized> {
    One(T),
    More(Vec<T>),
}

impl<T: Sized> Into<Vec<T>> for OneOrMore<T> {
    fn into(self) -> Vec<T> {
        match self {
            OneOrMore::One(o) => vec![o],
            OneOrMore::More(m) => m,
        }
    }
}

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

    #[test]
    fn test_has_env_deserialization() {
        let s = r#"has_env = "foo""#;
        let c: Condition = toml::from_str(s).expect("Deserializing has_env");

        assert_eq!(c.has_env.unwrap(), OneOrMore::<EnvironmentVariableName>::One(EnvironmentVariableName::from("foo")));
        assert!(c.env_eq.is_none());
        assert!(c.in_image.is_none());
    }

    #[test]
    fn test_has_env_list_deserialization() {
        let s = r#"has_env = ["foo", "bar"]"#;
        let c: Condition = toml::from_str(s).expect("Deserializing has_env");

        assert_eq!(c.has_env.unwrap(), {
            OneOrMore::<EnvironmentVariableName>::More({
                vec![EnvironmentVariableName::from("foo"), EnvironmentVariableName::from("bar")]
            })
        });
        assert!(c.env_eq.is_none());
        assert!(c.in_image.is_none());
    }

    #[test]
    fn test_env_eq_deserialization() {
        let s = r#"env_eq = { "foo" = "bar" }"#;
        let c: Condition = toml::from_str(s).expect("Deserializing has_env");

        assert!(c.has_env.is_none());
        assert_eq!(c.env_eq.unwrap(), {
            let mut hm = HashMap::new();
            hm.insert(EnvironmentVariableName::from("foo"), String::from("bar"));
            hm
        });
        assert!(c.in_image.is_none());
    }

    #[test]
    fn test_in_image_deserialization() {
        let s = r#"in_image = "foo""#;
        let c: Condition = toml::from_str(s).expect("Deserializing has_env");

        assert!(c.has_env.is_none());
        assert!(c.env_eq.is_none());
        assert_eq!(c.in_image.unwrap(), OneOrMore::<String>::One(String::from("foo")));
    }

    #[test]
    fn test_in_image_list_deserialization() {
        let s = r#"in_image = ["foo"]"#;
        let c: Condition = toml::from_str(s).expect("Deserializing has_env");

        assert!(c.has_env.is_none());
        assert!(c.env_eq.is_none());
        assert_eq!(c.in_image.unwrap(), OneOrMore::<String>::More(vec![String::from("foo")]));
    }

}