ferric_fred/release_tables_request.rs
1use chrono::NaiveDate;
2
3use crate::{Client, ReleaseElementId, ReleaseTable, Result};
4
5/// A builder for a `release/tables` request, returned by
6/// [`Client::release_tables`]. Fetches a release's table tree — the whole tree
7/// by default, or the subtree rooted at one element via
8/// [`element`](ReleaseTablesRequest::element). Finish with
9/// [`send`](ReleaseTablesRequest::send).
10///
11/// ```no_run
12/// # async fn run(client: &ferric_fred::Client) -> ferric_fred::Result<()> {
13/// use ferric_fred::ReleaseId;
14/// let table = client.release_tables(ReleaseId::new(10)).send().await?;
15/// println!("{} root elements", table.roots.len());
16/// # Ok(())
17/// # }
18/// ```
19#[derive(Debug, Clone)]
20#[must_use = "a ReleaseTablesRequest does nothing until you call `.send()`"]
21pub struct ReleaseTablesRequest<'a> {
22 client: &'a Client,
23 release_id: u32,
24 element_id: Option<ReleaseElementId>,
25 include_observation_values: bool,
26 observation_date: Option<NaiveDate>,
27}
28
29impl<'a> ReleaseTablesRequest<'a> {
30 pub(crate) fn new(client: &'a Client, release_id: u32) -> Self {
31 Self {
32 client,
33 release_id,
34 element_id: None,
35 include_observation_values: false,
36 observation_date: None,
37 }
38 }
39
40 /// Fetch only the subtree rooted at this element (`element_id`), instead of
41 /// the release's whole table tree.
42 pub fn element(mut self, element_id: ReleaseElementId) -> Self {
43 self.element_id = Some(element_id);
44 self
45 }
46
47 /// Fold each series element's observation value into the returned tree
48 /// (populating [`ReleaseTableElement::observation_value`] and
49 /// [`observation_date`](crate::ReleaseTableElement::observation_date)). Off
50 /// by default — the tree is structure-only. Without an explicit
51 /// [`observation_date`](ReleaseTablesRequest::observation_date), FRED returns
52 /// its latest value for each series.
53 pub fn include_observation_values(mut self, include: bool) -> Self {
54 self.include_observation_values = include;
55 self
56 }
57
58 /// Request observation values as of this date (ISO `YYYY-MM-DD`). Implies
59 /// [`include_observation_values(true)`](ReleaseTablesRequest::include_observation_values),
60 /// since a date is meaningless without values. FRED formats the returned
61 /// per-element `observation_date` to each series' frequency.
62 pub fn observation_date(mut self, date: NaiveDate) -> Self {
63 self.observation_date = Some(date);
64 self.include_observation_values = true;
65 self
66 }
67
68 /// Run the request and return the (sub)tree.
69 ///
70 /// # Errors
71 ///
72 /// Returns an error if the request fails to send, FRED returns a non-success
73 /// status, or the response body cannot be deserialized.
74 pub async fn send(self) -> Result<ReleaseTable> {
75 self.client.execute_release_tables(&self).await
76 }
77
78 /// Serialize the set parameters to FRED query key/value pairs. `api_key` and
79 /// `file_type` are added by the client, not here.
80 pub(crate) fn query_params(&self) -> Vec<(&'static str, String)> {
81 let mut params: Vec<(&'static str, String)> =
82 vec![("release_id", self.release_id.to_string())];
83 if let Some(element_id) = self.element_id {
84 params.push(("element_id", element_id.get().to_string()));
85 }
86 if self.include_observation_values {
87 params.push(("include_observation_values", "true".to_string()));
88 }
89 if let Some(date) = self.observation_date {
90 params.push(("observation_date", date.format("%Y-%m-%d").to_string()));
91 }
92 params
93 }
94}