Skip to main content

pexels_api/
search.rs

1use crate::{MediaSort, MediaType, Orientation, Size};
2
3#[derive(Debug, Clone, Default)]
4pub struct SearchParams {
5    pub page: Option<u32>,
6    pub per_page: Option<u32>,
7    pub orientation: Option<Orientation>,
8    pub size: Option<Size>,
9    pub color: Option<String>,
10    pub locale: Option<String>,
11}
12
13impl SearchParams {
14    pub fn new() -> Self {
15        Self::default()
16    }
17
18    pub fn page(mut self, page: u32) -> Self {
19        self.page = Some(page);
20        self
21    }
22
23    pub fn per_page(mut self, per_page: u32) -> Self {
24        self.per_page = Some(per_page);
25        self
26    }
27
28    pub fn orientation(mut self, orientation: Orientation) -> Self {
29        self.orientation = Some(orientation);
30        self
31    }
32
33    pub fn size(mut self, size: Size) -> Self {
34        self.size = Some(size);
35        self
36    }
37
38    pub fn color(mut self, color: impl Into<String>) -> Self {
39        self.color = Some(color.into());
40        self
41    }
42
43    pub fn locale(mut self, locale: impl Into<String>) -> Self {
44        self.locale = Some(locale.into());
45        self
46    }
47
48    pub fn to_query_params(&self) -> Vec<(String, String)> {
49        let mut params = Vec::new();
50
51        if let Some(page) = self.page {
52            params.push(("page".to_string(), page.to_string()));
53        }
54
55        if let Some(per_page) = self.per_page {
56            params.push(("per_page".to_string(), per_page.to_string()));
57        }
58
59        if let Some(orientation) = &self.orientation {
60            params.push(("orientation".to_string(), orientation.to_string()));
61        }
62
63        if let Some(size) = &self.size {
64            params.push(("size".to_string(), size.to_string()));
65        }
66
67        if let Some(color) = &self.color {
68            params.push(("color".to_string(), color.clone()));
69        }
70
71        if let Some(locale) = &self.locale {
72            params.push(("locale".to_string(), locale.clone()));
73        }
74
75        params
76    }
77}
78
79// Pagination parameters for API requests
80#[derive(Debug, Clone, Default)]
81pub struct PaginationParams {
82    /// Page number to retrieve
83    pub page: Option<u32>,
84
85    /// Number of items per page
86    pub per_page: Option<u32>,
87}
88
89impl PaginationParams {
90    /// Create a new PaginationParams instance
91    pub fn new() -> Self {
92        Self::default()
93    }
94
95    /// Set the page number
96    pub fn page(mut self, page: u32) -> Self {
97        self.page = Some(page);
98        self
99    }
100
101    /// Set the number of items per page
102    pub fn per_page(mut self, per_page: u32) -> Self {
103        self.per_page = Some(per_page);
104        self
105    }
106
107    pub(crate) fn to_query_params(&self) -> Vec<(String, String)> {
108        let mut params = Vec::new();
109
110        if let Some(page) = self.page {
111            params.push(("page".to_string(), page.to_string()));
112        }
113
114        if let Some(per_page) = self.per_page {
115            params.push(("per_page".to_string(), per_page.to_string()));
116        }
117
118        params
119    }
120}
121
122/// Video search parameters
123#[derive(Debug, Clone, Default)]
124pub struct VideoSearchParams {
125    /// Page number to retrieve
126    pub page: Option<u32>,
127
128    /// Number of videos per page
129    pub per_page: Option<u32>,
130
131    /// Orientation filter (landscape, portrait, square)
132    pub orientation: Option<String>,
133
134    /// Size filter (large, medium, small)
135    pub size: Option<String>,
136
137    /// Locale for localized results
138    pub locale: Option<String>,
139}
140
141impl VideoSearchParams {
142    /// Create a new VideoSearchParams instance
143    pub fn new() -> Self {
144        Self::default()
145    }
146
147    /// Set the page number
148    pub fn page(mut self, page: u32) -> Self {
149        self.page = Some(page);
150        self
151    }
152
153    /// Set the number of items per page
154    pub fn per_page(mut self, per_page: u32) -> Self {
155        self.per_page = Some(per_page);
156        self
157    }
158
159    /// Set the orientation filter
160    pub fn orientation(mut self, orientation: impl Into<String>) -> Self {
161        self.orientation = Some(orientation.into());
162        self
163    }
164
165    /// Set the size filter
166    pub fn size(mut self, size: impl Into<String>) -> Self {
167        self.size = Some(size.into());
168        self
169    }
170
171    /// Set the locale for localized results
172    pub fn locale(mut self, locale: impl Into<String>) -> Self {
173        self.locale = Some(locale.into());
174        self
175    }
176
177    pub(crate) fn to_query_params(&self) -> Vec<(String, String)> {
178        let mut params = Vec::new();
179
180        if let Some(page) = self.page {
181            params.push(("page".to_string(), page.to_string()));
182        }
183
184        if let Some(per_page) = self.per_page {
185            params.push(("per_page".to_string(), per_page.to_string()));
186        }
187
188        if let Some(orientation) = &self.orientation {
189            params.push(("orientation".to_string(), orientation.clone()));
190        }
191
192        if let Some(size) = &self.size {
193            params.push(("size".to_string(), size.clone()));
194        }
195
196        if let Some(locale) = &self.locale {
197            params.push(("locale".to_string(), locale.clone()));
198        }
199
200        params
201    }
202}
203
204/// Popular video parameters.
205#[derive(Debug, Clone, Default)]
206pub struct PopularVideoParams {
207    /// Page number to retrieve
208    pub page: Option<u32>,
209
210    /// Number of videos per page
211    pub per_page: Option<u32>,
212
213    /// Minimum video width in pixels
214    pub min_width: Option<u32>,
215
216    /// Minimum video height in pixels
217    pub min_height: Option<u32>,
218
219    /// Minimum video duration in seconds
220    pub min_duration: Option<u32>,
221
222    /// Maximum video duration in seconds
223    pub max_duration: Option<u32>,
224}
225
226impl PopularVideoParams {
227    /// Create a new PopularVideoParams instance
228    pub fn new() -> Self {
229        Self::default()
230    }
231
232    /// Create popular video params from simple pagination params.
233    pub fn from_pagination(params: &PaginationParams) -> Self {
234        Self { page: params.page, per_page: params.per_page, ..Self::default() }
235    }
236
237    /// Set the page number
238    pub fn page(mut self, page: u32) -> Self {
239        self.page = Some(page);
240        self
241    }
242
243    /// Set the number of items per page
244    pub fn per_page(mut self, per_page: u32) -> Self {
245        self.per_page = Some(per_page);
246        self
247    }
248
249    /// Set the minimum video width in pixels
250    pub fn min_width(mut self, min_width: u32) -> Self {
251        self.min_width = Some(min_width);
252        self
253    }
254
255    /// Set the minimum video height in pixels
256    pub fn min_height(mut self, min_height: u32) -> Self {
257        self.min_height = Some(min_height);
258        self
259    }
260
261    /// Set the minimum video duration in seconds
262    pub fn min_duration(mut self, min_duration: u32) -> Self {
263        self.min_duration = Some(min_duration);
264        self
265    }
266
267    /// Set the maximum video duration in seconds
268    pub fn max_duration(mut self, max_duration: u32) -> Self {
269        self.max_duration = Some(max_duration);
270        self
271    }
272
273    pub(crate) fn to_query_params(&self) -> Vec<(String, String)> {
274        let mut params = Vec::new();
275
276        if let Some(page) = self.page {
277            params.push(("page".to_string(), page.to_string()));
278        }
279
280        if let Some(per_page) = self.per_page {
281            params.push(("per_page".to_string(), per_page.to_string()));
282        }
283
284        if let Some(min_width) = self.min_width {
285            params.push(("min_width".to_string(), min_width.to_string()));
286        }
287
288        if let Some(min_height) = self.min_height {
289            params.push(("min_height".to_string(), min_height.to_string()));
290        }
291
292        if let Some(min_duration) = self.min_duration {
293            params.push(("min_duration".to_string(), min_duration.to_string()));
294        }
295
296        if let Some(max_duration) = self.max_duration {
297            params.push(("max_duration".to_string(), max_duration.to_string()));
298        }
299
300        params
301    }
302}
303
304/// Collection media parameters.
305#[derive(Debug, Clone, Default)]
306pub struct CollectionMediaParams {
307    /// Page number to retrieve
308    pub page: Option<u32>,
309
310    /// Number of media items per page
311    pub per_page: Option<u32>,
312
313    /// Media type filter
314    pub media_type: Option<MediaType>,
315
316    /// Sort order
317    pub sort: Option<MediaSort>,
318}
319
320impl CollectionMediaParams {
321    /// Create a new CollectionMediaParams instance
322    pub fn new() -> Self {
323        Self::default()
324    }
325
326    /// Create collection media params from simple pagination params.
327    pub fn from_pagination(params: &PaginationParams) -> Self {
328        Self { page: params.page, per_page: params.per_page, ..Self::default() }
329    }
330
331    /// Set the page number
332    pub fn page(mut self, page: u32) -> Self {
333        self.page = Some(page);
334        self
335    }
336
337    /// Set the number of items per page
338    pub fn per_page(mut self, per_page: u32) -> Self {
339        self.per_page = Some(per_page);
340        self
341    }
342
343    /// Filter collection media to photos or videos.
344    pub fn media_type(mut self, media_type: MediaType) -> Self {
345        self.media_type = Some(media_type);
346        self
347    }
348
349    /// Set collection media sort order.
350    pub fn sort(mut self, sort: MediaSort) -> Self {
351        self.sort = Some(sort);
352        self
353    }
354
355    pub(crate) fn to_query_params(&self) -> Vec<(String, String)> {
356        let mut params = Vec::new();
357
358        if let Some(page) = self.page {
359            params.push(("page".to_string(), page.to_string()));
360        }
361
362        if let Some(per_page) = self.per_page {
363            params.push(("per_page".to_string(), per_page.to_string()));
364        }
365
366        if let Some(media_type) = &self.media_type {
367            if !matches!(media_type, MediaType::Empty) {
368                params.push(("type".to_string(), media_type.as_str().to_string()));
369            }
370        }
371
372        if let Some(sort) = &self.sort {
373            params.push(("sort".to_string(), sort.as_str().to_string()));
374        }
375
376        params
377    }
378}
379
380#[cfg(test)]
381mod tests {
382    use super::*;
383
384    #[test]
385    fn popular_video_params_include_documented_filters() {
386        let params = PopularVideoParams::new()
387            .page(2)
388            .per_page(20)
389            .min_width(1280)
390            .min_height(720)
391            .min_duration(5)
392            .max_duration(60)
393            .to_query_params();
394
395        assert_eq!(
396            params,
397            vec![
398                ("page".to_string(), "2".to_string()),
399                ("per_page".to_string(), "20".to_string()),
400                ("min_width".to_string(), "1280".to_string()),
401                ("min_height".to_string(), "720".to_string()),
402                ("min_duration".to_string(), "5".to_string()),
403                ("max_duration".to_string(), "60".to_string()),
404            ]
405        );
406    }
407
408    #[test]
409    fn collection_media_params_include_type_and_sort() {
410        let params = CollectionMediaParams::new()
411            .page(1)
412            .per_page(10)
413            .media_type(MediaType::Photo)
414            .sort(MediaSort::Desc)
415            .to_query_params();
416
417        assert_eq!(
418            params,
419            vec![
420                ("page".to_string(), "1".to_string()),
421                ("per_page".to_string(), "10".to_string()),
422                ("type".to_string(), "photos".to_string()),
423                ("sort".to_string(), "desc".to_string()),
424            ]
425        );
426    }
427}