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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
use api::set::filtertypes::SetBlock;
use itertools::Itertools;
use std::fmt::Display;

const SEP_OR: &str = "|";

/// Builder for filtered set requests
#[derive(Clone, Debug)]
pub struct SetFilterBuilder {
    filter: String,
}

impl SetFilterBuilder {
    fn new() -> SetFilterBuilder {
        SetFilterBuilder {
            filter: String::new(),
        }
    }

    /// Creates a Setilter with the specified filter parameters
    ///
    /// ```
    /// # use mtgapi_client::prelude::*;
    /// let builder = SetFilter::builder();
    /// let filter = builder
    ///     .name("Khans of Tarkir")
    ///     .block(SetBlock::KhansOfTarkir)
    ///     .build();
    /// assert!(filter == SetFilter("name=Khans of Tarkir&block=Khans of Tarkir".to_string()))
    /// ```
    #[allow(dead_code)]
    pub fn build(self) -> SetFilter {
        SetFilter(self.filter)
    }

    /// Create a custom filter
    ///
    /// ```
    /// # use mtgapi_client::prelude::*;
    /// let builder = SetFilter::builder();
    /// let filter = builder.custom("name", "Dominaria")
    ///     .build();
    /// assert!(filter == SetFilter("name=Dominaria".to_string()))
    /// ```
    #[allow(dead_code)]
    pub fn custom<'a, T>(mut self, key: T, value: T) -> SetFilterBuilder
    where
        T: Into<&'a str>,
    {
        self.add_filter(key.into(), value.into());
        self
    }

    /// Every set that (partially) matches the specified name will match the filter
    ///
    /// ```
    /// # use mtgapi_client::prelude::*;
    /// let builder = SetFilter::builder();
    /// let filter = builder.name("Dominaria")
    ///     .build();
    /// assert!(filter == SetFilter("name=Dominaria".to_string()))
    /// ```
    #[allow(dead_code)]
    pub fn name<'a, T>(mut self, name: T) -> SetFilterBuilder
    where
        T: Into<&'a str>,
    {
        self.add_filter("name", name.into());
        self
    }

    /// Every set that (partially) matches one of the specified names will match the filter
    ///
    /// ```
    /// # use mtgapi_client::prelude::*;
    /// let builder = SetFilter::builder();
    /// let filter = builder.names(&vec!["Dominaria", "Core Set 2019"])
    ///     .build();
    /// assert!(filter == SetFilter("name=Dominaria|Core Set 2019".to_string()));
    /// ```
    #[allow(dead_code)]
    pub fn names<T>(mut self, names: &[T]) -> SetFilterBuilder
    where
        T: Display,
    {
        let values = names.into_iter().join(SEP_OR);
        self.add_filter("name", &values);
        self
    }

    /// Every set that (partially) matches the specified block will match the filter
    ///
    /// ```
    /// # use mtgapi_client::prelude::*;
    /// let builder = SetFilter::builder();
    /// let filter = builder.block(SetBlock::Amonkhet)
    ///     .build();
    /// assert!(filter == SetFilter("block=Amonkhet".to_string()))
    /// ```
    #[allow(dead_code)]
    pub fn block(mut self, block: SetBlock) -> SetFilterBuilder {
        self.add_filter("block", &block.as_str());
        self
    }

    /// Every set that (partially) matches one of the specified blocks will match the filter
    ///
    /// ```
    /// # use mtgapi_client::prelude::*;
    /// let builder = SetFilter::builder();
    /// let filter = builder.blocks(&vec![SetBlock::Amonkhet, SetBlock::Ixalan])
    ///     .build();
    /// assert!(filter == SetFilter("block=Amonkhet|Ixalan".to_string()));
    /// ```
    #[allow(dead_code)]
    pub fn blocks(mut self, blocks: &[SetBlock]) -> SetFilterBuilder {
        let values = blocks.into_iter().map(|value| value.as_str()).join(SEP_OR);
        self.add_filter("block", &values);
        self
    }

    fn add_filter<T>(&mut self, key: T, values: T)
    where
        T: Display,
    {
        if !self.filter.is_empty() {
            self.filter = [&self.filter, "&"].join("");
        }
        self.filter = self.filter.clone() + &[key, values].into_iter().join("=")
    }
}

/// Wrapper around the filter string to be used for filtered set api requests
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct SetFilter(pub String);

impl SetFilter {
    /// Creates a new SetFilterBuilder
    #[allow(dead_code)]
    pub fn builder() -> SetFilterBuilder {
        SetFilterBuilder::new()
    }
}