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
// Third party
use std::collections::HashMap;
use url::form_urlencoded;

/// options availble for search
#[derive(Default, Clone, Debug)]
pub struct SearchOptions {
    params: HashMap<&'static str, String>,
}

impl SearchOptions {
    /// return a new instance of a builder for options
    pub fn builder() -> SearchOptionsBuilder {
        SearchOptionsBuilder::new()
    }

    /// serialize options as a string. returns None if no options are defined
    pub fn serialize(&self) -> Option<String> {
        if self.params.is_empty() {
            None
        } else {
            Some(
                form_urlencoded::Serializer::new(String::new())
                    .extend_pairs(&self.params)
                    .finish(),
            )
        }
    }

    pub fn as_builder(&self) -> SearchOptionsBuilder {
        SearchOptionsBuilder::copy_from(self)
    }
}

/// a builder interface for search option
/// Typically this is initialized with SearchOptions::builder()
#[derive(Default, Debug)]
pub struct SearchOptionsBuilder {
    params: HashMap<&'static str, String>,
}

impl SearchOptionsBuilder {
    pub fn new() -> SearchOptionsBuilder {
        SearchOptionsBuilder {
            ..Default::default()
        }
    }

    fn copy_from(search_options: &SearchOptions) -> SearchOptionsBuilder {
        SearchOptionsBuilder {
            params: search_options.params.clone(),
        }
    }

    pub fn fields<F>(&mut self, fs: Vec<F>) -> &mut SearchOptionsBuilder
    where
        F: Into<String>,
    {
        self.params.insert(
            "fields",
            fs.into_iter()
                .map(|f| f.into())
                .collect::<Vec<String>>()
                .join(","),
        );
        self
    }

    pub fn validate(&mut self, v: bool) -> &mut SearchOptionsBuilder {
        self.params.insert("validateQuery", v.to_string());
        self
    }

    pub fn max_results(&mut self, m: u64) -> &mut SearchOptionsBuilder {
        self.params.insert("maxResults", m.to_string());
        self
    }

    pub fn start_at(&mut self, s: u64) -> &mut SearchOptionsBuilder {
        self.params.insert("startAt", s.to_string());
        self
    }

    pub fn type_name(&mut self, t: &str) -> &mut SearchOptionsBuilder {
        self.params.insert("type", t.to_string());
        self
    }

    pub fn name(&mut self, n: &str) -> &mut SearchOptionsBuilder {
        self.params.insert("name", n.to_string());
        self
    }

    pub fn project_key_or_id(&mut self, id: &str) -> &mut SearchOptionsBuilder {
        self.params.insert("projectKeyOrId", id.to_string());
        self
    }

    pub fn expand<E>(&mut self, ex: Vec<E>) -> &mut SearchOptionsBuilder
    where
        E: Into<String>,
    {
        self.params.insert(
            "expand",
            ex.into_iter()
                .map(|e| e.into())
                .collect::<Vec<String>>()
                .join(","),
        );
        self
    }

    pub fn state(&mut self, s: &str) -> &mut SearchOptionsBuilder {
        self.params.insert("state", s.to_string());
        self
    }

    pub fn build(&self) -> SearchOptions {
        SearchOptions {
            params: self.params.clone(),
        }
    }
}