hubcaps_ex/search/
repos.rs

1use std::collections::HashMap;
2use std::fmt;
3
4use serde::Deserialize;
5use url::form_urlencoded;
6
7use super::{Search, SearchResult};
8use crate::users::User;
9use crate::{Future, SortDirection, Stream};
10
11#[derive(Clone, Copy, Debug, PartialEq)]
12pub enum ReposSort {
13    /// Sort by the number of stars
14    Stars,
15    ///Sort by the number of forks
16    Forks,
17    /// Sort by when the repo was last updated
18    Updated,
19}
20
21impl fmt::Display for ReposSort {
22    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23        match *self {
24            ReposSort::Stars => "stars",
25            ReposSort::Forks => "forks",
26            ReposSort::Updated => "updated",
27        }
28        .fmt(f)
29    }
30}
31
32/// Provides access to [search operations for repositories](https://developer.github.com/v3/search/#search-repositories)
33///
34pub struct SearchRepos {
35    search: Search,
36}
37
38impl SearchRepos {
39    #[doc(hidden)]
40    pub fn new(search: Search) -> Self {
41        Self { search }
42    }
43
44    fn search_uri<Q>(&self, q: Q, options: &SearchReposOptions) -> String
45    where
46        Q: Into<String>,
47    {
48        let mut uri = vec!["/search/repositories".to_string()];
49        let query_options = options.serialize().unwrap_or_default();
50        let query = form_urlencoded::Serializer::new(query_options)
51            .append_pair("q", &q.into())
52            .finish();
53
54        uri.push(query);
55        uri.join("?")
56    }
57
58    /// Return a stream of search results repository query
59    /// See [github docs](https://developer.github.com/v3/search/#parameters)
60    /// for query format options
61    pub fn iter<Q>(&self, q: Q, options: &SearchReposOptions) -> Stream<ReposItem>
62    where
63        Q: Into<String>,
64    {
65        self.search.iter::<ReposItem>(&self.search_uri(q, options))
66    }
67
68    /// Return the first page of search result repository query
69    /// See [github docs](https://developer.github.com/v3/search/#parameters)
70    /// for query format options
71    pub fn list<Q>(&self, q: Q, options: &SearchReposOptions) -> Future<SearchResult<ReposItem>>
72    where
73        Q: Into<String>,
74    {
75        self.search
76            .search::<ReposItem>(&self.search_uri(q, options))
77    }
78}
79
80#[derive(Default)]
81pub struct SearchReposOptions {
82    params: HashMap<&'static str, String>,
83}
84
85impl SearchReposOptions {
86    pub fn builder() -> SearchReposOptionsBuilder {
87        SearchReposOptionsBuilder::default()
88    }
89
90    pub fn serialize(&self) -> Option<String> {
91        if self.params.is_empty() {
92            None
93        } else {
94            let encoded: String = form_urlencoded::Serializer::new(String::new())
95                .extend_pairs(&self.params)
96                .finish();
97            Some(encoded)
98        }
99    }
100}
101
102#[derive(Default)]
103pub struct SearchReposOptionsBuilder(SearchReposOptions);
104
105impl SearchReposOptionsBuilder {
106    pub fn per_page(&mut self, n: usize) -> &mut Self {
107        self.0.params.insert("per_page", n.to_string());
108        self
109    }
110
111    pub fn sort(&mut self, sort: ReposSort) -> &mut Self {
112        self.0.params.insert("sort", sort.to_string());
113        self
114    }
115
116    pub fn order(&mut self, direction: SortDirection) -> &mut Self {
117        self.0.params.insert("order", direction.to_string());
118        self
119    }
120
121    pub fn build(&self) -> SearchReposOptions {
122        SearchReposOptions {
123            params: self.0.params.clone(),
124        }
125    }
126}
127
128#[derive(Debug, Deserialize)]
129pub struct ReposItem {
130    pub id: u32,
131    pub name: String,
132    pub full_name: String,
133    pub owner: User,
134    pub private: bool,
135    pub html_url: String,
136    pub description: String,
137    pub fork: bool,
138    pub url: String,
139    pub forks_url: String,
140    pub keys_url: String,
141    pub collaborators_url: String,
142    pub teams_url: String,
143    pub hooks_url: String,
144    pub issue_events_url: String,
145    pub events_url: String,
146    pub assignees_url: String,
147    pub branches_url: String,
148    pub tags_url: String,
149    pub blobs_url: String,
150    pub git_tags_url: String,
151    pub git_refs_url: String,
152    pub trees_url: String,
153    pub statuses_url: String,
154    pub languages_url: String,
155    pub stargazers_url: String,
156    pub contributors_url: String,
157    pub subscribers_url: String,
158    pub subscription_url: String,
159    pub commits_url: String,
160    pub git_commits_url: String,
161    pub comments_url: String,
162    pub issue_comment_url: String,
163    pub contents_url: String,
164    pub compare_url: String,
165    pub merges_url: String,
166    pub archive_url: String,
167    pub downloads_url: String,
168    pub issues_url: String,
169    pub pulls_url: String,
170    pub milestones_url: String,
171    pub notifications_url: String,
172    pub labels_url: String,
173    pub releases_url: String,
174    pub deployments_url: String,
175    pub created_at: String,
176    pub updated_at: String,
177    pub pushed_at: String,
178    pub git_url: String,
179    pub ssh_url: String,
180    pub clone_url: String,
181    pub svn_url: String,
182    pub homepage: String,
183    pub size: u32,
184    pub stargazers_count: u32,
185    pub watchers_count: u32,
186    pub language: String,
187    pub has_issues: bool,
188    pub has_projects: bool,
189    pub has_downloads: bool,
190    pub has_wiki: bool,
191    pub has_pages: bool,
192    pub forks_count: u32,
193    pub mirror_url: Option<String>,
194    pub archived: bool,
195    pub open_issues_count: u32,
196    pub license: License,
197    pub forks: u32,
198    pub open_issues: u32,
199    pub watchers: u32,
200    pub default_branch: String,
201    pub score: f64,
202}
203
204#[derive(Debug, Deserialize)]
205pub struct License {
206    key: String,
207    name: String,
208    spdx_id: String,
209    url: String,
210}