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

pub struct ArtistReleases;

#[derive(Debug, Clone, Default)]
pub struct ArtistReleasesParams {
    pub artist_id: isize,
    /// Seemes to be `year`, `title`, or `format`
    pub sort: Option<String>,
    pub sort_order: Option<SortOrder>,
}

impl Endpoint<'_> for ArtistReleases {
    type Parameters = ArtistReleasesParams;
    type ReturnType = serde_json::Value;

    fn build_url(
        base: &reqwest::Url,
        params: Self::Parameters,
    ) -> Result<reqwest::Url, crate::Error> {
        let mut out = base
            .join(&format!("/artists/{}/releases", params.artist_id))
            .map_err(|_| Error::UrlError)?;

        // idk if preallocating is better here
        // i also tried a match stmt over a tuple of the two options
        // seems trivially different, but could be interesting to measure
        let mut pairs = Vec::with_capacity(
            usize::from(params.sort.is_some()) + usize::from(params.sort_order.is_some()),
        );
        if let Some(sort) = params.sort.as_deref() {
            pairs.push(("sort", sort));
        }
        if let Some(sort_order) = params.sort_order.as_ref() {
            pairs.push(("sort_order", sort_order.as_ref()));
        }
        out.query_pairs_mut().extend_pairs(pairs);

        Ok(out)
    }
}

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

    #[test]
    fn basic() {
        let artist_id = 3946211;
        let params = ArtistReleasesParams {
            artist_id,
            ..Default::default()
        };

        let client = Client::default();
        let data = client.get::<ArtistReleases>(params).unwrap();

        dbg![data];
    }
}