Skip to main content

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}