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
use super::Endpoint;
use crate::{client::build_params, data_types::SortOrder, Error};
use reqwest::Url;

pub struct MasterVersions;

#[derive(Debug, Clone, Default)]
pub struct MasterVersionsParams {
    pub master_id: isize,
    pub page: Option<usize>,
    pub per_page: Option<usize>,
    /// Filter by format, e.g. "Vinyl"
    pub format: Option<String>,
    /// Filter by label
    pub label: Option<String>,
    /// Filter by year released,
    pub released: Option<u16>,
    /// Filter by country of release
    pub country: Option<String>,
    pub sort: Option<MasterVersionsSort>,
    pub sort_order: Option<SortOrder>,
}

#[derive(Debug, Clone)]
pub enum MasterVersionsSort {
    Released,
    Title,
    Format,
    Label,
    CatNo,
    Country,
}

impl AsRef<str> for MasterVersionsSort {
    fn as_ref(&self) -> &str {
        match self {
            Self::Released => "released",
            Self::Title => "title",
            Self::Format => "format",
            Self::Label => "label",
            Self::CatNo => "catno",
            Self::Country => "country",
        }
    }
}

impl MasterVersionsParams {
    fn build(&self, personal_access_token: Option<&str>) -> String {
        let mut params = Vec::with_capacity(9);
        let page_owned: String;
        let per_page_owned: String;
        let released_owned: String;

        if let Some(page) = self.page {
            page_owned = page.to_string();
            params.push(("page", page_owned.as_str()));
        }
        if let Some(per_page) = self.per_page {
            per_page_owned = per_page.to_string();
            params.push(("per_page", per_page_owned.as_str()));
        }
        if let Some(format) = self.format.as_deref() {
            params.push(("format", format));
        }
        if let Some(label) = self.label.as_deref() {
            params.push(("label", label));
        }
        if let Some(released) = self.released {
            released_owned = released.to_string();
            params.push(("released", &released_owned));
        }
        if let Some(country) = self.country.as_deref() {
            params.push(("country", country));
        }
        if let Some(sort) = self.sort.as_ref().map(AsRef::as_ref) {
            params.push(("sort", sort));
        }
        if let Some(sort_order) = self.sort_order.as_ref().map(AsRef::as_ref) {
            params.push(("sort_order", sort_order));
        }
        if let Some(personal_access_token) = personal_access_token {
            params.push(("token", personal_access_token));
        }

        build_params(params.as_slice())
    }
}

impl Endpoint<'_> for MasterVersions {
    type Parameters = MasterVersionsParams;
    type ReturnType = crate::data_types::MasterVersions;

    fn build_url(base: &Url, params: Self::Parameters) -> Result<Url, Error> {
        base.join(&format!(
            "/masters/{0}/versions{1}",
            params.master_id,
            params.build(None)
        ))
        .map_err(|_| Error::UrlError)
    }
}

#[cfg(test)]
mod tests {
    use crate::{Auth, Client};

    use super::*;

    const ID: isize = 3175560;

    #[test]
    fn basic() {
        let _data = Client::builder()
            .build()
            .unwrap()
            .get::<MasterVersions>(MasterVersionsParams {
                master_id: ID,
                ..Default::default()
            })
            .unwrap();
    }

    #[test]
    fn with_auth() {
        let pat = std::env::var("discogs-pat")
            .expect("expected personal access token in env var `discogs-pat`");
        let _data = Client::builder()
            .auth(Auth::Token(pat))
            .build()
            .unwrap()
            .get::<MasterVersions>(MasterVersionsParams {
                master_id: ID,
                page: Some(2),
                per_page: Some(2),
                ..Default::default()
            })
            .unwrap();
    }
}