graphql_federated_graph/directives/
complexity_control.rs

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
use cynic_parser_deser::ValueDeserialize;

#[derive(ValueDeserialize)]
pub struct CostDirective {
    pub weight: i32,
}

impl CostDirective {
    pub fn definition() -> &'static str {
        indoc::indoc! {r#"
            directive @cost(weight: Int!) on
                ARGUMENT_DEFINITION
              | ENUM
              | FIELD_DEFINITION
              | INPUT_FIELD_DEFINITION
              | OBJECT
              | SCALAR
        "#}
    }
}

#[derive(ValueDeserialize, PartialEq, PartialOrd, Clone, Debug)]
#[deser(rename_all = "camelCase", default)]
pub struct ListSizeDirective {
    pub assumed_size: Option<u32>,
    pub slicing_arguments: Vec<String>,
    pub sized_fields: Vec<String>,
    #[deser(default = true)]
    pub require_one_slicing_argument: bool,
}

impl ListSizeDirective {
    pub fn definition() -> &'static str {
        indoc::indoc! {r#"
            directive @listSize(
              assumedSize: Int,
              slicingArguments: [String!],
              sizedFields: [String!],
              requireOneSlicingArgument: Boolean = true
            ) on FIELD_DEFINITION
        "#}
    }

    pub fn merge(self, other: ListSizeDirective) -> Self {
        let mut slicing_arguments = self.slicing_arguments;
        slicing_arguments.extend(other.slicing_arguments);

        let mut sized_fields = self.sized_fields;
        sized_fields.extend(other.sized_fields);

        ListSizeDirective {
            assumed_size: match (self.assumed_size, other.assumed_size) {
                (Some(lhs), Some(rhs)) => Some(std::cmp::max(lhs, rhs)),
                (lhs, rhs) => lhs.or(rhs),
            },
            slicing_arguments,
            sized_fields,
            require_one_slicing_argument: self.require_one_slicing_argument || other.require_one_slicing_argument,
        }
    }
}

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

    #[test]
    fn test_parsing_cost() {
        let value = parse_directive::<CostDirective>("@cost(weight: 1)").unwrap();

        assert_eq!(value.weight, 1);
    }
}