alpaca_data/news/
request.rs1use alpaca_core::{QueryWriter, pagination::PaginatedRequest};
2
3use crate::Error;
4
5use super::Sort;
6
7#[derive(Clone, Debug, Default)]
8pub struct ListRequest {
9 pub start: Option<String>,
10 pub end: Option<String>,
11 pub sort: Option<Sort>,
12 pub symbols: Option<Vec<String>>,
13 pub limit: Option<u32>,
14 pub include_content: Option<bool>,
15 pub exclude_contentless: Option<bool>,
16 pub page_token: Option<String>,
17}
18
19impl ListRequest {
20 pub(crate) fn validate(&self) -> Result<(), Error> {
21 validate_limit(self.limit, 1, 50)?;
22
23 if let Some(symbols) = &self.symbols {
24 validate_symbols(symbols)?;
25 }
26
27 Ok(())
28 }
29
30 pub(crate) fn into_query(self) -> Vec<(String, String)> {
31 let mut query = QueryWriter::default();
32 query.push_opt("start", self.start);
33 query.push_opt("end", self.end);
34 query.push_opt("sort", self.sort);
35 if let Some(symbols) = self.symbols {
36 query.push_csv("symbols", symbols);
37 }
38 query.push_opt("limit", self.limit);
39 query.push_opt("include_content", self.include_content);
40 query.push_opt("exclude_contentless", self.exclude_contentless);
41 query.push_opt("page_token", self.page_token);
42 query.finish()
43 }
44}
45
46impl PaginatedRequest for ListRequest {
47 fn with_page_token(&self, page_token: Option<String>) -> Self {
48 let mut next = self.clone();
49 next.page_token = page_token;
50 next
51 }
52}
53
54fn validate_symbols(symbols: &[String]) -> Result<(), Error> {
55 if symbols.is_empty() {
56 return Err(Error::InvalidRequest(
57 "symbols are invalid: must not be empty when provided".to_owned(),
58 ));
59 }
60
61 if symbols.iter().any(|symbol| symbol.trim().is_empty()) {
62 return Err(Error::InvalidRequest(
63 "symbols are invalid: must not contain empty or whitespace-only entries".to_owned(),
64 ));
65 }
66
67 Ok(())
68}
69
70fn validate_limit(limit: Option<u32>, min: u32, max: u32) -> Result<(), Error> {
71 if let Some(limit) = limit
72 && !(min..=max).contains(&limit)
73 {
74 return Err(Error::InvalidRequest(format!(
75 "limit must be between {min} and {max}"
76 )));
77 }
78
79 Ok(())
80}