fred_rs/
client.rs

1//! Functions and definitons related to the persistent client
2//! 
3//! ```
4//! use fred_rs::client::FredClient;
5//! use fred_rs::series::observation::{Builder, Units, Frequency, Response};
6//! 
7//! // Create the client object
8//! let mut c = match FredClient::new() {
9//!     Ok(c) => c,
10//!     Err(msg) => {
11//!         println!("{}", msg);
12//!         return
13//!     },
14//! };
15//! 
16//! // Create the argument builder
17//! let mut builder = Builder::new();
18//! 
19//! // Set the arguments for the builder
20//! builder
21//!     .observation_start("2000-01-01")
22//!     .units(Units::PCH)
23//!     .frequency(Frequency::M);
24//! 
25//! // Make the request and pass in the builder to apply the arguments
26//! let resp: Response = match c.series_observation("GNPCA", Some(builder)) {
27//!     Ok(resp) => resp,
28//!     Err(msg) => {
29//!         println!("{}", msg);
30//!         return
31//!     },
32//! };
33//! ```
34
35use reqwest::blocking::{Client, Response};
36
37use std::time::Duration;
38use std::env;
39
40use crate::*;
41
42const FRED_BASE_URL: &str = "https://api.stlouisfed.org/fred/";
43const FRED_API_KEY: &str = "FRED_API_KEY";
44
45#[derive(Clone, Debug)]
46/// Persistent client object used to access the FRED API
47/// 
48/// Each method for the client represents a data endpoint provided by the API and will return a data object representing the response contents.
49pub struct FredClient {
50    client: Client,
51    url_base: &'static str,
52    api_key: String,
53}
54
55impl FredClient {
56
57    /// Creates and initializes a new client object
58    /// 
59    /// The client will attempt to load an API key from the environment variable 'FRED_API_KEY'.  If this variable is undefined, the key remains empty.
60    /// 
61    /// If a connection cannot be made to the FRED API, it returns Err containing an error message.
62    /// 
63    /// ```
64    /// use fred_rs::client::FredClient;
65    /// 
66    /// let mut client = match FredClient::new() {
67    ///     Ok(c) => c,
68    ///     Err(msg) => {
69    ///         println!("{}", msg);
70    ///         return
71    ///     },
72    /// };
73    /// ```
74    pub fn new() -> Result<FredClient, String> {
75
76        let client = match Client::builder().timeout(Duration::from_secs(30)).build() {
77            Ok(c) => c,
78            Err(msg) => return Err(msg.to_string()),
79        };
80
81        let api_key = match env::var(FRED_API_KEY) {
82            Ok(val) => val,
83            Err(_) => String::from(""),
84        };
85
86        let fred = FredClient {
87            client,
88            url_base: FRED_BASE_URL,
89            api_key,
90        };
91
92        let url = format!("{}category?category_id=125&api_key={}&file_type=json", fred.url_base, fred.api_key);
93        match fred.client.get(url.as_str()).send() {
94            Ok(_) => (),
95            Err(msg) => return Err(msg.to_string()),
96        }
97
98        return Ok(fred)
99
100    }
101
102    /// Sets the FRED API key for the client
103    /// 
104    /// # Arguments
105    /// * `key` - The [API key](https://research.stlouisfed.org/docs/api/api_key.html) generated to access FRED 
106    /// 
107    /// ```
108    /// use fred_rs::client::FredClient;
109    /// 
110    /// let mut client = match FredClient::new() {
111    ///     Ok(c) => c,
112    ///     Err(msg) => {
113    ///         println!("{}", msg);
114    ///         return
115    ///     },
116    /// };
117    /// 
118    /// client.with_key("abcdefghijklmnopqrstuvwxyz123456");
119    /// ```
120    pub fn with_key(&mut self, key: &str) {
121        self.api_key = String::from(key);
122    }
123
124    fn get_request(&mut self, url: &str) -> Result<Response, String> {
125        match self.client.get(url).send() {
126            Ok(r) => Ok(r),
127            Err(msg) => Err(msg.to_string()),
128        }
129    }
130
131    // ----------------------------------------------------------------------
132    // Series
133
134    /// [See fred_rs::series](../series/index.html)
135    /// 
136    /// # Arguments
137    /// `series_id` - The id for a series [[Link]](https://research.stlouisfed.org/docs/api/fred/series.html#series_id)
138    pub fn series(
139        &mut self,
140        series_id: &str,
141        builder: Option<series::Builder>
142    ) -> Result<series::Response, String> {
143        let mut url: String = format!(
144            "{}series?series_id={}&api_key={}&file_type=json",
145            self.url_base,
146            series_id,
147            self.api_key
148        );
149
150        match builder {
151            Some(b) => url.push_str(b.build().as_str()),
152            None => (),
153        }
154
155        match self.get_request(url.as_str()) {
156            Ok(resp) => {
157                let text = resp.text().unwrap();
158                match serde_json::from_str(&text) {
159                    Ok(val) => Ok(val),
160                    Err(_e) => {
161                        match serde_json::from_str(&text) {
162                            Ok(e) => {
163                                let err: error::FredError = e;
164                                let err_msg = format!(
165                                    "ERROR {}: {}",
166                                    err.error_code,
167                                    err.error_message
168                                );
169                                return Err(err_msg);
170                            },
171                            Err(msg) => return Err(String::from(msg.to_string())),
172                        }
173                    },
174                }
175            },
176            Err(e) => return Err(e.to_string()),
177        }
178    }
179
180    /// [See fred_rs::series::categories](../series/categories/index.html)
181    /// 
182    /// # Arguments
183    /// `series_id` - The id for a series [[Link]](https://research.stlouisfed.org/docs/api/fred/series_categories.html#series_id)
184    pub fn series_categories(
185        &mut self,
186        series_id: &str,
187        builder: Option<series::categories::Builder>
188    ) -> Result<category::Response, String> {
189        let mut url: String = format!(
190            "{}series/categories?series_id={}&api_key={}&file_type=json",
191            self.url_base,
192            series_id,
193            self.api_key
194        );
195
196        match builder {
197            Some(b) => url.push_str(b.build().as_str()),
198            None => (),
199        }
200
201        match self.get_request(url.as_str()) {
202            Ok(resp) => {
203                let text = resp.text().unwrap();
204                match serde_json::from_str(&text) {
205                    Ok(val) => Ok(val),
206                    Err(_e) => {
207                        match serde_json::from_str(&text) {
208                            Ok(e) => {
209                                let err: error::FredError = e;
210                                let err_msg = format!(
211                                    "ERROR {}: {}",
212                                    err.error_code,
213                                    err.error_message
214                                );
215                                return Err(err_msg);
216                            },
217                            Err(msg) => return Err(String::from(msg.to_string())),
218                        }
219                    },
220                }
221            },
222            Err(e) => return Err(e.to_string()),
223        }
224    }
225
226    /// [See fred_rs::series::observation](../series/observation/index.html)
227    /// 
228    /// # Arguments
229    /// `series_id` - The id for a series [[Link]](https://research.stlouisfed.org/docs/api/fred/series_observation.html#series_id)
230    pub fn series_observation(
231        &mut self,
232        series_id: &str,
233        builder: Option<series::observation::Builder>
234    ) -> Result<series::observation::Response, String> {
235        let mut url: String = format!(
236            "{}series/observations?series_id={}&api_key={}&file_type=json",
237            self.url_base,
238            series_id,
239            self.api_key
240        );
241
242        match builder {
243            Some(b) => url.push_str(b.build().as_str()),
244            None => (),
245        }
246
247        match self.get_request(url.as_str()) {
248            Ok(resp) => {
249                let text = resp.text().unwrap();
250                match serde_json::from_str(&text) {
251                    Ok(val) => Ok(val),
252                    Err(_e) => {
253                        match serde_json::from_str(&text) {
254                            Ok(e) => {
255                                let err: error::FredError = e;
256                                let err_msg = format!(
257                                    "ERROR {}: {}",
258                                    err.error_code,
259                                    err.error_message
260                                );
261                                return Err(err_msg);
262                            },
263                            Err(msg) => return Err(String::from(msg.to_string())),
264                        }
265                    },
266                }
267            },
268            Err(e) => return Err(e.to_string()),
269        }
270    }
271
272    /// [See fred_rs::series::release](../series/release/index.html)
273    /// 
274    /// # Arguments
275    /// `series_id` - The id for a series [[Link]](https://research.stlouisfed.org/docs/api/fred/series_release.html#series_id)
276    pub fn series_release(
277        &mut self,
278        series_id: &str,
279        builder: Option<series::release::Builder>
280    ) -> Result<release::Response, String> {
281        let mut url: String = format!(
282            "{}series/release?series_id={}&api_key={}&file_type=json",
283            self.url_base,
284            series_id,
285            self.api_key
286        );
287
288        match builder {
289            Some(b) => url.push_str(b.build().as_str()),
290            None => (),
291        }
292
293        match self.get_request(url.as_str()) {
294            Ok(resp) => {
295                let text = resp.text().unwrap();
296                match serde_json::from_str(&text) {
297                    Ok(val) => Ok(val),
298                    Err(_e) => {
299                        match serde_json::from_str(&text) {
300                            Ok(e) => {
301                                let err: error::FredError = e;
302                                let err_msg = format!(
303                                    "ERROR {}: {}",
304                                    err.error_code,
305                                    err.error_message
306                                );
307                                return Err(err_msg);
308                            },
309                            Err(msg) => return Err(String::from(msg.to_string())),
310                        }
311                    },
312                }
313            },
314            Err(e) => return Err(e.to_string()),
315        }
316    }
317    
318    /// [See fred_rs::series::tags](../series/tags/index.html)
319    /// 
320    /// # Arguments
321    /// `series_id` - The id for a series [[Link]](https://research.stlouisfed.org/docs/api/fred/series_tags.html#series_id)
322    pub fn series_tags(
323        &mut self,
324        series_id: &str,
325        builder: Option<series::tags::Builder>
326    ) -> Result<tags::Response, String> {
327
328        let mut url: String = format!(
329            "{}series/tags?series_id={}&api_key={}&file_type=json",
330            self.url_base,
331            series_id,
332            self.api_key
333        );
334
335        match builder {
336            Some(b) => url.push_str(b.build().as_str()),
337            None => (),
338        }
339        
340        match self.get_request(url.as_str()) {
341            Ok(resp) => {
342                let text = resp.text().unwrap();
343                match serde_json::from_str(&text) {
344                    Ok(val) => Ok(val),
345                    Err(_e) => {
346                        match serde_json::from_str(&text) {
347                            Ok(e) => {
348                                let err: error::FredError = e;
349                                let err_msg = format!(
350                                    "ERROR {}: {}",
351                                    err.error_code,
352                                    err.error_message
353                                );
354                                return Err(err_msg);
355                            },
356                            Err(msg) => return Err(String::from(msg.to_string())),
357                        }
358                    },
359                }
360            },
361            Err(e) => return Err(e.to_string()),
362        }
363    }
364
365    /// [See fred_rs::series::updates](../series/updates/index.html)
366    pub fn series_updates(
367        &mut self,
368        builder: Option<series::updates::Builder>
369    ) -> Result<series::updates::Response, String> {
370
371        let mut url: String = format!(
372            "{}series/updates?api_key={}&file_type=json",
373            self.url_base,
374            self.api_key
375        );
376
377        match builder {
378            Some(b) => url.push_str(b.build().as_str()),
379            None => (),
380        }
381        
382        match self.get_request(url.as_str()) {
383            Ok(resp) => {
384                let text = resp.text().unwrap();
385                match serde_json::from_str(&text) {
386                    Ok(val) => Ok(val),
387                    Err(_e) => {
388                        match serde_json::from_str(&text) {
389                            Ok(e) => {
390                                let err: error::FredError = e;
391                                let err_msg = format!(
392                                    "ERROR {}: {}",
393                                    err.error_code,
394                                    err.error_message
395                                );
396                                return Err(err_msg);
397                            },
398                            Err(msg) => return Err(String::from(msg.to_string())),
399                        }
400                    },
401                }
402            },
403            Err(e) => return Err(e.to_string()),
404        }
405    }
406
407    /// [See fred_rs::series::vintagedates](../series/vintagedates/index.html)
408    /// 
409    /// # Arguments
410    /// `series_id` - The id for a series [[Link]](https://research.stlouisfed.org/docs/api/fred/series_vintagedates.html#series_id)
411    pub fn series_vintagedates(
412        &mut self,
413        series_id: &str,
414        builder: Option<series::vintagedates::Builder>
415    ) -> Result<series::vintagedates::Response, String> {
416
417        let mut url: String = format!(
418            "{}series/vintagedates?series_id={}&api_key={}&file_type=json",
419            self.url_base,
420            series_id,
421            self.api_key
422        );
423
424        match builder {
425            Some(b) => url.push_str(b.build().as_str()),
426            None => (),
427        }
428        
429        match self.get_request(url.as_str()) {
430            Ok(resp) => {
431                let text = resp.text().unwrap();
432                match serde_json::from_str(&text) {
433                    Ok(val) => Ok(val),
434                    Err(_e) => {
435                        match serde_json::from_str(&text) {
436                            Ok(e) => {
437                                let err: error::FredError = e;
438                                let err_msg = format!(
439                                    "ERROR {}: {}",
440                                    err.error_code,
441                                    err.error_message
442                                );
443                                return Err(err_msg);
444                            },
445                            Err(msg) => return Err(String::from(msg.to_string())),
446                        }
447                    },
448                }
449            },
450            Err(e) => return Err(e.to_string()),
451        }
452    }
453
454    // ----------------------------------------------------------------------
455    // Series/Search
456
457    /// [See fred_rs::series::search](../series/search/index.html)
458    /// 
459    /// # Arguments
460    /// `search_text` - The words to match against economic data series [[Link]](https://research.stlouisfed.org/docs/api/fred/series_search.html#search_text)
461    pub fn series_search(
462        &mut self,
463        search_text: &str,
464        builder: Option<series::search::Builder>
465    ) -> Result<series::Response, String> {
466        let search_text = search_text.replace(" ", "%20"); // encode strings in url
467
468        let mut url: String = format!(
469            "{}series/search?search_text={}&api_key={}&file_type=json",
470            self.url_base,
471            search_text,
472            self.api_key
473        );
474
475        match builder {
476            Some(b) => url.push_str(b.build().as_str()),
477            None => (),
478        }
479
480        match self.get_request(url.as_str()) {
481            Ok(resp) => {
482                let text = resp.text().unwrap();
483                match serde_json::from_str(&text) {
484                    Ok(val) => Ok(val),
485                    Err(_e) => {
486                        match serde_json::from_str(&text) {
487                            Ok(e) => {
488                                let err: error::FredError = e;
489                                let err_msg = format!(
490                                    "ERROR {}: {}",
491                                    err.error_code,
492                                    err.error_message
493                                );
494                                return Err(err_msg);
495                            },
496                            Err(msg) => return Err(String::from(msg.to_string())),
497                        }
498                    },
499                }
500            },
501            Err(e) => return Err(e.to_string()),
502        }
503    }
504
505    /// [See fred_rs::series::search::tags](../series/search/tags/index.html)
506    /// 
507    /// # Arguments
508    /// `series_search_text` - The words to match against economic data series [[Link]](https://research.stlouisfed.org/docs/api/fred/series_search_tags.html#search_text)
509    pub fn series_search_tags(
510        &mut self,
511        series_search_text: &str,
512        builder: Option<series::search::tags::Builder>
513    ) -> Result<tags::Response, String> {
514        let search_text = series_search_text.replace(" ", "%20"); // encode spaces in url
515
516        let mut url: String = format!(
517            "{}series/search/tags?series_search_text={}&api_key={}&file_type=json",
518            self.url_base,
519            search_text,
520            self.api_key
521        );
522
523        match builder {
524            Some(b) => url.push_str(b.build().as_str()),
525            None => (),
526        }
527        
528        match self.get_request(url.as_str()) {
529            Ok(resp) => {
530                let text = resp.text().unwrap();
531                match serde_json::from_str(&text) {
532                    Ok(val) => Ok(val),
533                    Err(_e) => {
534                        match serde_json::from_str(&text) {
535                            Ok(e) => {
536                                let err: error::FredError = e;
537                                let err_msg = format!(
538                                    "ERROR {}: {}",
539                                    err.error_code,
540                                    err.error_message
541                                );
542                                return Err(err_msg);
543                            },
544                            Err(msg) => return Err(String::from(msg.to_string())),
545                        }
546                    },
547                }
548            },
549            Err(e) => return Err(e.to_string()),
550        }
551    }
552
553    /// [See fred_rs::series::search::related_tags](../series/search/related_tags/index.html)
554    /// 
555    /// # Arguments
556    /// `series_search_text` - The words to match against economic data series [[Link]](https://research.stlouisfed.org/docs/api/fred/series_search_related_tags.html#search_text)
557    pub fn series_search_related_tags(
558        &mut self,
559        series_search_text: &str,
560        builder: series::search::related_tags::Builder
561    ) -> Result<tags::Response, String> {
562
563        let search_text = series_search_text.replace(" ", "%20"); // encode spaces in url
564
565        let mut url: String = format!(
566            "{}series/search/related_tags?series_search_text={}&api_key={}&file_type=json",
567            self.url_base,
568            search_text,
569            self.api_key
570        );
571
572        match builder.build() {
573            Ok(s) => url.push_str(s.as_str()),
574            Err(msg) => return Err(msg),
575        }
576                
577        match self.get_request(url.as_str()) {
578            Ok(resp) => {
579                let text = resp.text().unwrap();
580                match serde_json::from_str(&text) {
581                    Ok(val) => Ok(val),
582                    Err(_e) => {
583                        match serde_json::from_str(&text) {
584                            Ok(e) => {
585                                let err: error::FredError = e;
586                                let err_msg = format!(
587                                    "ERROR {}: {}",
588                                    err.error_code,
589                                    err.error_message
590                                );
591                                return Err(err_msg);
592                            },
593                            Err(msg) => return Err(String::from(msg.to_string())),
594                        }
595                    },
596                }
597            },
598            Err(e) => return Err(e.to_string()),
599        }
600    }
601
602    // ----------------------------------------------------------------------
603    // Tags
604
605    /// [See fred_rs::tags](../tags/index.html)
606    pub fn tags(
607        &mut self,
608        builder: Option<tags::Builder>
609    ) -> Result<tags::Response, String> {
610        let mut url: String = format!(
611            "{}tags?api_key={}&file_type=json",
612            self.url_base,
613            self.api_key
614        );
615
616        match builder {
617            Some(b) => url.push_str(b.build().as_str()),
618            None => (),
619        }
620
621        match self.get_request(url.as_str()) {
622            Ok(resp) => {
623                let text = resp.text().unwrap();
624                match serde_json::from_str(&text) {
625                    Ok(val) => Ok(val),
626                    Err(_e) => {
627                        match serde_json::from_str(&text) {
628                            Ok(e) => {
629                                let err: error::FredError = e;
630                                let err_msg = format!(
631                                    "ERROR {}: {}",
632                                    err.error_code,
633                                    err.error_message
634                                );
635                                return Err(err_msg);
636                            },
637                            Err(msg) => return Err(String::from(msg.to_string())),
638                        }
639                    },
640                }
641            },
642            Err(e) => return Err(e.to_string()),
643        }
644    }
645
646    /// [See fred_rs::tags::series](../tags/series/index.html)
647    pub fn tags_series(
648        &mut self,
649        builder: tags::series::Builder
650    ) -> Result<series::Response, String> {
651        let mut url: String = format!(
652            "{}tags/series?api_key={}&file_type=json",
653            self.url_base,
654            self.api_key
655        );
656
657        match builder.build() {
658            Ok(opt) => url.push_str(opt.as_str()),
659            Err(msg) => return Err(msg),
660        }
661
662        match self.get_request(url.as_str()) {
663            Ok(resp) => {
664                let text = resp.text().unwrap();
665                match serde_json::from_str(&text) {
666                    Ok(val) => Ok(val),
667                    Err(_e) => {
668                        match serde_json::from_str(&text) {
669                            Ok(e) => {
670                                let err: error::FredError = e;
671                                let err_msg = format!(
672                                    "ERROR {}: {}",
673                                    err.error_code,
674                                    err.error_message
675                                );
676                                return Err(err_msg);
677                            },
678                            Err(msg) => return Err(String::from(msg.to_string())),
679                        }
680                    },
681                }
682            },
683            Err(e) => return Err(e.to_string()),
684        }
685    }
686
687    // ----------------------------------------------------------------------
688    // Related Tags
689
690    /// [See fred_rs::related_tags](../related_tags/index.html)
691    pub fn related_tags(
692        &mut self,
693        builder: related_tags::Builder
694    ) -> Result<tags::Response, String> {
695        let mut url: String = format!(
696            "{}related_tags?api_key={}&file_type=json",
697            self.url_base,
698            self.api_key
699        );
700
701        match builder.build() {
702            Ok(opt) => url.push_str(opt.as_str()),
703            Err(msg) => return Err(msg),
704        }
705
706        match self.get_request(url.as_str()) {
707            Ok(resp) => {
708                let text = resp.text().unwrap();
709                match serde_json::from_str(&text) {
710                    Ok(val) => Ok(val),
711                    Err(_e) => {
712                        match serde_json::from_str(&text) {
713                            Ok(e) => {
714                                let err: error::FredError = e;
715                                let err_msg = format!(
716                                    "ERROR {}: {}",
717                                    err.error_code,
718                                    err.error_message
719                                );
720                                return Err(err_msg);
721                            },
722                            Err(msg) => return Err(String::from(msg.to_string())),
723                        }
724                    },
725                }
726            },
727            Err(e) => return Err(e.to_string()),
728        }
729    }
730
731    // ----------------------------------------------------------------------
732    // Sources
733
734    /// [See fred_rs::sources](../sources/index.html)
735    pub fn sources(
736        &mut self,
737        builder: Option<sources::Builder>
738    ) -> Result<source::Response, String> {
739        let mut url: String = format!(
740            "{}sources?api_key={}&file_type=json",
741            self.url_base,
742            self.api_key
743        );
744
745        match builder {
746            Some(b) => url.push_str(b.build().as_str()),
747            None => (),
748        }
749
750        match self.get_request(url.as_str()) {
751            Ok(resp) => {
752                let text = resp.text().unwrap();
753                match serde_json::from_str(&text) {
754                    Ok(val) => Ok(val),
755                    Err(_e) => {
756                        match serde_json::from_str(&text) {
757                            Ok(e) => {
758                                let err: error::FredError = e;
759                                let err_msg = format!(
760                                    "ERROR {}: {}",
761                                    err.error_code,
762                                    err.error_message
763                                );
764                                return Err(err_msg);
765                            },
766                            Err(msg) => return Err(String::from(msg.to_string())),
767                        }
768                    },
769                }
770            },
771            Err(e) => return Err(e.to_string()),
772        }
773    }
774
775    // ----------------------------------------------------------------------
776    // Source
777
778    /// [See fred_rs::source](../source/index.html)
779    /// 
780    /// # Arguments
781    /// `source_id` - The id for a source [[Link]](https://research.stlouisfed.org/docs/api/fred/source.html#source_id)
782    pub fn source(
783        &mut self,
784        source_id: usize,
785        builder: Option<source::Builder>
786    ) -> Result<source::Response, String> {
787        let mut url: String = format!(
788            "{}source?source_id={}&api_key={}&file_type=json",
789            self.url_base,
790            source_id,
791            self.api_key
792        );
793
794        match builder {
795            Some(b) => url.push_str(b.build().as_str()),
796            None => (),
797        }
798
799        match self.get_request(url.as_str()) {
800            Ok(resp) => {
801                let text = resp.text().unwrap();
802                match serde_json::from_str(&text) {
803                    Ok(val) => Ok(val),
804                    Err(_e) => {
805                        match serde_json::from_str(&text) {
806                            Ok(e) => {
807                                let err: error::FredError = e;
808                                let err_msg = format!(
809                                    "ERROR {}: {}",
810                                    err.error_code,
811                                    err.error_message
812                                );
813                                return Err(err_msg);
814                            },
815                            Err(msg) => return Err(String::from(msg.to_string())),
816                        }
817                    },
818                }
819            },
820            Err(e) => return Err(e.to_string()),
821        }
822    }
823
824    /// [See fred_rs::source::releases](../source/releases/index.html)
825    /// 
826    /// # Arguments
827    /// `source_id` - The id for a source [[Link]](https://research.stlouisfed.org/docs/api/fred/source_releases.html#source_id)
828    pub fn source_releases(
829        &mut self,
830        source_id: usize,
831        builder: Option<source::releases::Builder>
832    ) -> Result<release::Response, String> {
833        let mut url: String = format!(
834            "{}source/releases?source_id={}&api_key={}&file_type=json",
835            self.url_base,
836            source_id,
837            self.api_key
838        );
839
840        match builder {
841            Some(b) => url.push_str(b.build().as_str()),
842            None => (),
843        }
844
845        match self.get_request(url.as_str()) {
846            Ok(resp) => {
847                let text = resp.text().unwrap();
848                match serde_json::from_str(&text) {
849                    Ok(val) => Ok(val),
850                    Err(_e) => {
851                        match serde_json::from_str(&text) {
852                            Ok(e) => {
853                                let err: error::FredError = e;
854                                let err_msg = format!(
855                                    "ERROR {}: {}",
856                                    err.error_code,
857                                    err.error_message
858                                );
859                                return Err(err_msg);
860                            },
861                            Err(msg) => return Err(String::from(msg.to_string())),
862                        }
863                    },
864                }
865            },
866            Err(e) => return Err(e.to_string()),
867        }
868    }
869
870    // ----------------------------------------------------------------------
871    // Category
872
873    /// [See fred_rs::category](../category/index.html)
874    /// 
875    /// # Arguments
876    /// `category_id` - The id for a category [[Link]](https://research.stlouisfed.org/docs/api/fred/category.html#category_id)
877    pub fn category(
878        &mut self,
879        category_id: usize
880    ) -> Result<category::Response, String> {
881        let url: String = format!(
882            "{}category?category_id={}&api_key={}&file_type=json",
883            self.url_base,
884            category_id,
885            self.api_key
886        );
887
888        match self.get_request(url.as_str()) {
889            Ok(resp) => {
890                let text = resp.text().unwrap();
891                match serde_json::from_str(&text) {
892                    Ok(val) => Ok(val),
893                    Err(_e) => {
894                        match serde_json::from_str(&text) {
895                            Ok(e) => {
896                                let err: error::FredError = e;
897                                let err_msg = format!(
898                                    "ERROR {}: {}",
899                                    err.error_code,
900                                    err.error_message
901                                );
902                                return Err(err_msg);
903                            },
904                            Err(msg) => return Err(String::from(msg.to_string())),
905                        }
906                    },
907                }
908            },
909            Err(e) => return Err(e.to_string()),
910        }
911    }
912
913    /// [See fred_rs::category::children](../category/children/index.html)
914    /// 
915    /// # Arguments
916    /// `category_id` - The id for a category [[Link]](https://research.stlouisfed.org/docs/api/fred/category_children.html#category_id)
917    pub fn category_children(
918        &mut self,
919        category_id: usize,
920        builder: Option<category::children::Builder>,
921    ) -> Result<category::Response, String> {
922        let mut url: String = format!(
923            "{}category/children?category_id={}&api_key={}&file_type=json",
924            self.url_base,
925            category_id,
926            self.api_key
927        );
928
929        match builder {
930            Some(b) => url.push_str(b.build().as_str()),
931            None => (),
932        }
933
934        match self.get_request(url.as_str()) {
935            Ok(resp) => {
936                let text = resp.text().unwrap();
937                match serde_json::from_str(&text) {
938                    Ok(val) => Ok(val),
939                    Err(_e) => {
940                        match serde_json::from_str(&text) {
941                            Ok(e) => {
942                                let err: error::FredError = e;
943                                let err_msg = format!(
944                                    "ERROR {}: {}",
945                                    err.error_code,
946                                    err.error_message
947                                );
948                                return Err(err_msg);
949                            },
950                            Err(msg) => return Err(String::from(msg.to_string())),
951                        }
952                    },
953                }
954            },
955            Err(e) => return Err(e.to_string()),
956        }
957    }
958
959    /// [See fred_rs::category::related](../category/related/index.html)
960    /// 
961    /// # Arguments
962    /// `category_id` - The id for a category [[Link]](https://research.stlouisfed.org/docs/api/fred/category_related.html#category_id)
963    pub fn category_related(
964        &mut self,
965        category_id: usize,
966        builder: Option<category::related::Builder>,
967    ) -> Result<category::Response, String> {
968        let mut url: String = format!(
969            "{}category/related?category_id={}&api_key={}&file_type=json",
970            self.url_base,
971            category_id,
972            self.api_key
973        );
974
975        match builder {
976            Some(b) => url.push_str(b.build().as_str()),
977            None => (),
978        }
979
980        match self.get_request(url.as_str()) {
981            Ok(resp) => {
982                let text = resp.text().unwrap();
983                match serde_json::from_str(&text) {
984                    Ok(val) => Ok(val),
985                    Err(_e) => {
986                        match serde_json::from_str(&text) {
987                            Ok(e) => {
988                                let err: error::FredError = e;
989                                let err_msg = format!(
990                                    "ERROR {}: {}",
991                                    err.error_code,
992                                    err.error_message
993                                );
994                                return Err(err_msg);
995                            },
996                            Err(msg) => return Err(String::from(msg.to_string())),
997                        }
998                    },
999                }
1000            },
1001            Err(e) => return Err(e.to_string()),
1002        }
1003    }
1004
1005    /// [See fred_rs::category::series](../category/series/index.html)
1006    /// 
1007    /// # Arguments
1008    /// `category_id` - The id for a category [[Link]](https://research.stlouisfed.org/docs/api/fred/series.html#category_id)
1009    pub fn category_series(
1010        &mut self,
1011        category_id: usize,
1012        builder: Option<category::series::Builder>
1013    ) -> Result<series::Response, String> {
1014        let mut url: String = format!(
1015            "{}category/series?category_id={}&api_key={}&file_type=json",
1016            self.url_base,
1017            category_id,
1018            self.api_key
1019        );
1020
1021        match builder {
1022            Some(b) => url.push_str(b.build().as_str()),
1023            None => (),
1024        }
1025
1026        match self.get_request(url.as_str()) {
1027            Ok(resp) => {
1028                let text = resp.text().unwrap();
1029                match serde_json::from_str(&text) {
1030                    Ok(val) => Ok(val),
1031                    Err(_e) => {
1032                        match serde_json::from_str(&text) {
1033                            Ok(e) => {
1034                                let err: error::FredError = e;
1035                                let err_msg = format!(
1036                                    "ERROR {}: {}",
1037                                    err.error_code,
1038                                    err.error_message
1039                                );
1040                                return Err(err_msg);
1041                            },
1042                            Err(msg) => return Err(String::from(msg.to_string())),
1043                        }
1044                    },
1045                }
1046            },
1047            Err(e) => return Err(e.to_string()),
1048        }
1049    }
1050
1051    /// [See fred_rs::category::tags](../category/tags/index.html)
1052    /// 
1053    /// # Arguments
1054    /// `category_id` - The id for a category [[Link]](https://research.stlouisfed.org/docs/api/fred/category_tags.html#category_id)
1055    pub fn category_tags(
1056        &mut self,
1057        category_id: usize,
1058        builder: Option<category::tags::Builder>
1059    ) -> Result<tags::Response, String> {
1060        let mut url: String = format!(
1061            "{}category/tags?category_id={}&api_key={}&file_type=json",
1062            self.url_base,
1063            category_id,
1064            self.api_key
1065        );
1066
1067        match builder {
1068            Some(b) => url.push_str(b.build().as_str()),
1069            None => (),
1070        }
1071
1072        match self.get_request(url.as_str()) {
1073            Ok(resp) => {
1074                let text = resp.text().unwrap();
1075                match serde_json::from_str(&text) {
1076                    Ok(val) => Ok(val),
1077                    Err(_e) => {
1078                        match serde_json::from_str(&text) {
1079                            Ok(e) => {
1080                                let err: error::FredError = e;
1081                                let err_msg = format!(
1082                                    "ERROR {}: {}",
1083                                    err.error_code,
1084                                    err.error_message
1085                                );
1086                                return Err(err_msg);
1087                            },
1088                            Err(msg) => return Err(String::from(msg.to_string())),
1089                        }
1090                    },
1091                }
1092            },
1093            Err(e) => return Err(e.to_string()),
1094        }
1095    }
1096
1097    /// [See fred_rs::category::related_tags](../category/related_tags/index.html)
1098    /// 
1099    /// # Arguments
1100    /// `category_id` - The id for a category [[Link]](https://research.stlouisfed.org/docs/api/fred/category_related_tags.html#category_id)
1101    pub fn category_related_tags(
1102        &mut self,
1103        category_id: usize,
1104        builder: category::related_tags::Builder
1105    ) -> Result<tags::Response, String> {
1106        let mut url: String = format!(
1107            "{}category/related_tags?category_id={}&api_key={}&file_type=json",
1108            self.url_base,
1109            category_id,
1110            self.api_key
1111        );
1112
1113        match builder.build() {
1114            Ok(o) => url.push_str(o.as_str()),
1115            Err(msg) => return Err(msg),
1116        }
1117
1118        match self.get_request(url.as_str()) {
1119            Ok(resp) => {
1120                let text = resp.text().unwrap();
1121                match serde_json::from_str(&text) {
1122                    Ok(val) => Ok(val),
1123                    Err(_e) => {
1124                        match serde_json::from_str(&text) {
1125                            Ok(e) => {
1126                                let err: error::FredError = e;
1127                                let err_msg = format!(
1128                                    "ERROR {}: {}",
1129                                    err.error_code,
1130                                    err.error_message
1131                                );
1132                                return Err(err_msg);
1133                            },
1134                            Err(msg) => return Err(String::from(msg.to_string())),
1135                        }
1136                    },
1137                }
1138            },
1139            Err(e) => return Err(e.to_string()),
1140        }
1141    }
1142
1143    // ----------------------------------------------------------------------
1144    // Releases
1145
1146    /// [See fred_rs::releases](../releases/index.html)
1147    pub fn releases(
1148        &mut self,
1149        builder: Option<releases::Builder>
1150    ) -> Result<release::Response, String> {
1151        let mut url: String = format!(
1152            "{}releases?api_key={}&file_type=json",
1153            self.url_base,
1154            self.api_key
1155        );
1156
1157        match builder {
1158            Some(b) => url.push_str(b.build().as_str()),
1159            None => (),
1160        }
1161
1162        match self.get_request(url.as_str()) {
1163            Ok(resp) => {
1164                let text = resp.text().unwrap();
1165                match serde_json::from_str(&text) {
1166                    Ok(val) => Ok(val),
1167                    Err(_e) => {
1168                        match serde_json::from_str(&text) {
1169                            Ok(e) => {
1170                                let err: error::FredError = e;
1171                                let err_msg = format!(
1172                                    "ERROR {}: {}",
1173                                    err.error_code,
1174                                    err.error_message
1175                                );
1176                                return Err(err_msg);
1177                            },
1178                            Err(msg) => return Err(String::from(msg.to_string())),
1179                        }
1180                    },
1181                }
1182            },
1183            Err(e) => return Err(e.to_string()),
1184        }
1185    }
1186
1187    /// [See fred_rs::releases::dates](../releases/dates/index.html)
1188    pub fn releases_dates(
1189        &mut self,
1190        builder: Option<releases::dates::Builder>
1191    ) -> Result<releases::dates::Response, String> {
1192        let mut url: String = format!(
1193            "{}releases/dates?api_key={}&file_type=json",
1194            self.url_base,
1195            self.api_key
1196        );
1197
1198        match builder {
1199            Some(b) => url.push_str(b.build().as_str()),
1200            None => (),
1201        }
1202
1203        match self.get_request(url.as_str()) {
1204            Ok(resp) => {
1205                let text = resp.text().unwrap();
1206                match serde_json::from_str(&text) {
1207                    Ok(val) => Ok(val),
1208                    Err(_e) => {
1209                        match serde_json::from_str(&text) {
1210                            Ok(e) => {
1211                                let err: error::FredError = e;
1212                                let err_msg = format!(
1213                                    "ERROR {}: {}",
1214                                    err.error_code,
1215                                    err.error_message
1216                                );
1217                                return Err(err_msg);
1218                            },
1219                            Err(msg) => return Err(String::from(msg.to_string())),
1220                        }
1221                    },
1222                }
1223            },
1224            Err(e) => return Err(e.to_string()),
1225        }
1226    }
1227
1228    // ----------------------------------------------------------------------
1229    // Release
1230
1231    /// [See fred_rs::release](../release/index.html)
1232    /// 
1233    /// # Arguments
1234    /// `release_id` - The id for a release [[Link]](https://research.stlouisfed.org/docs/api/fred/release.html#release_id)
1235    pub fn release(
1236        &mut self,
1237        release_id: usize,
1238        builder: Option<release::Builder>
1239    ) -> Result<release::Response, String> {
1240        let mut url: String = format!(
1241            "{}release?release_id={}&api_key={}&file_type=json",
1242            self.url_base,
1243            release_id,
1244            self.api_key
1245        );
1246
1247        match builder {
1248            Some(b) => url.push_str(b.build().as_str()),
1249            None => (),
1250        }
1251
1252        match self.get_request(url.as_str()) {
1253            Ok(resp) => {
1254                let text = resp.text().unwrap();
1255                match serde_json::from_str(&text) {
1256                    Ok(val) => Ok(val),
1257                    Err(_e) => {
1258                        match serde_json::from_str(&text) {
1259                            Ok(e) => {
1260                                let err: error::FredError = e;
1261                                let err_msg = format!(
1262                                    "ERROR {}: {}",
1263                                    err.error_code,
1264                                    err.error_message
1265                                );
1266                                return Err(err_msg);
1267                            },
1268                            Err(msg) => return Err(String::from(msg.to_string())),
1269                        }
1270                    },
1271                }
1272            },
1273            Err(e) => return Err(e.to_string()),
1274        }
1275    }
1276
1277    /// [See fred_rs::release::series](../release/series/index.html)
1278    /// 
1279    /// # Arguments
1280    /// `release_id` - The id for a release [[Link]](https://research.stlouisfed.org/docs/api/fred/release_series.html#release_id)
1281    pub fn release_series(
1282        &mut self,
1283        release_id: usize,
1284        builder: Option<release::series::Builder>
1285    ) -> Result<series::Response, String> {
1286        let mut url: String = format!(
1287            "{}release/series?release_id={}&api_key={}&file_type=json",
1288            self.url_base,
1289            release_id,
1290            self.api_key
1291        );
1292
1293        match builder {
1294            Some(b) => url.push_str(b.build().as_str()),
1295            None => (),
1296        }
1297
1298        match self.get_request(url.as_str()) {
1299            Ok(resp) => {
1300                let text = resp.text().unwrap();
1301                match serde_json::from_str(&text) {
1302                    Ok(val) => Ok(val),
1303                    Err(_e) => {
1304                        match serde_json::from_str(&text) {
1305                            Ok(e) => {
1306                                let err: error::FredError = e;
1307                                let err_msg = format!(
1308                                    "ERROR {}: {}",
1309                                    err.error_code,
1310                                    err.error_message
1311                                );
1312                                return Err(err_msg);
1313                            },
1314                            Err(msg) => return Err(String::from(msg.to_string())),
1315                        }
1316                    },
1317                }
1318            },
1319            Err(e) => return Err(e.to_string()),
1320        }
1321    }
1322
1323    /// [See fred_rs::release::sources](../release/sources/index.html)
1324    /// 
1325    /// # Arguments
1326    /// `release_id` - The id for a release [[Link]](https://research.stlouisfed.org/docs/api/fred/release_sources.html#release_id)
1327    pub fn release_sources(
1328        &mut self,
1329        release_id: usize,
1330        builder: Option<release::sources::Builder>
1331    ) -> Result<source::Response, String> {
1332        let mut url: String = format!(
1333            "{}release/sources?release_id={}&api_key={}&file_type=json",
1334            self.url_base,
1335            release_id,
1336            self.api_key
1337        );
1338
1339        match builder {
1340            Some(b) => url.push_str(b.build().as_str()),
1341            None => (),
1342        }
1343
1344        match self.get_request(url.as_str()) {
1345            Ok(resp) => {
1346                let text = resp.text().unwrap();
1347                match serde_json::from_str(&text) {
1348                    Ok(val) => Ok(val),
1349                    Err(_e) => {
1350                        match serde_json::from_str(&text) {
1351                            Ok(e) => {
1352                                let err: error::FredError = e;
1353                                let err_msg = format!(
1354                                    "ERROR {}: {}",
1355                                    err.error_code,
1356                                    err.error_message
1357                                );
1358                                return Err(err_msg);
1359                            },
1360                            Err(msg) => return Err(String::from(msg.to_string())),
1361                        }
1362                    },
1363                }
1364            },
1365            Err(e) => return Err(e.to_string()),
1366        }
1367    }
1368
1369    /// [See fred_rs::release::tags](../release/tags/index.html)
1370    /// 
1371    /// # Arguments
1372    /// `release_id` - The id for a release [[Link]](https://research.stlouisfed.org/docs/api/fred/release_tags.html#release_id)
1373    pub fn release_tags(
1374        &mut self,
1375        release_id: usize,
1376        builder: Option<release::tags::Builder>
1377    ) -> Result<tags::Response, String> {
1378        let mut url: String = format!(
1379            "{}release/tags?release_id={}&api_key={}&file_type=json",
1380            self.url_base,
1381            release_id,
1382            self.api_key
1383        );
1384
1385        match builder {
1386            Some(b) => url.push_str(b.build().as_str()),
1387            None => (),
1388        }
1389
1390        match self.get_request(url.as_str()) {
1391            Ok(resp) => {
1392                let text = resp.text().unwrap();
1393                match serde_json::from_str(&text) {
1394                    Ok(val) => Ok(val),
1395                    Err(_e) => {
1396                        match serde_json::from_str(&text) {
1397                            Ok(e) => {
1398                                let err: error::FredError = e;
1399                                let err_msg = format!(
1400                                    "ERROR {}: {}",
1401                                    err.error_code,
1402                                    err.error_message
1403                                );
1404                                return Err(err_msg);
1405                            },
1406                            Err(msg) => return Err(String::from(msg.to_string())),
1407                        }
1408                    },
1409                }
1410            },
1411            Err(e) => return Err(e.to_string()),
1412        }
1413    }
1414
1415    /// [See fred_rs::release::related_tags](../release/related_tags/index.html)
1416    /// 
1417    /// # Arguments
1418    /// `release_id` - The id for a release [[Link]](https://research.stlouisfed.org/docs/api/fred/release_related_tags.html#release_id)
1419    pub fn release_related_tags(
1420        &mut self,
1421        release_id: usize,
1422        builder: release::related_tags::Builder
1423    ) -> Result<tags::Response, String> {
1424        let mut url: String = format!(
1425            "{}release/related_tags?release_id={}&api_key={}&file_type=json",
1426            self.url_base,
1427            release_id,
1428            self.api_key
1429        );
1430
1431        match builder.build() {
1432            Ok(o) => url.push_str(o.as_str()),
1433            Err(msg) => return Err(msg),
1434        }
1435
1436        match self.get_request(url.as_str()) {
1437            Ok(resp) => {
1438                let text = resp.text().unwrap();
1439                match serde_json::from_str(&text) {
1440                    Ok(val) => Ok(val),
1441                    Err(_e) => {
1442                        match serde_json::from_str(&text) {
1443                            Ok(e) => {
1444                                let err: error::FredError = e;
1445                                let err_msg = format!(
1446                                    "ERROR {}: {}",
1447                                    err.error_code,
1448                                    err.error_message
1449                                );
1450                                return Err(err_msg);
1451                            },
1452                            Err(msg) => return Err(String::from(msg.to_string())),
1453                        }
1454                    },
1455                }
1456            },
1457            Err(e) => return Err(e.to_string()),
1458        }
1459    }
1460
1461    /// [See fred_rs::release::tables](../release/tables/index.html)
1462    /// 
1463    /// # Arguments
1464    /// `release_id` - The id for a release [[Link]](https://research.stlouisfed.org/docs/api/fred/release_tables.html#release_id)
1465    pub fn release_tables(
1466        &mut self,
1467        release_id: usize,
1468        builder: Option<release::tables::Builder>
1469    ) -> Result<release::tables::Response, String> {
1470        let mut url: String = format!(
1471            "{}release/tables?release_id={}&api_key={}&file_type=json",
1472            self.url_base,
1473            release_id,
1474            self.api_key
1475        );
1476
1477        match builder {
1478            Some(b) => url.push_str(b.build().as_str()),
1479            None => (),
1480        }
1481        
1482        match self.get_request(url.as_str()) {
1483            Ok(resp) => {
1484                let text = resp.text().unwrap();
1485                match serde_json::from_str(&text) {
1486                    Ok(val) => Ok(val),
1487                    Err(_e) => {
1488                        match serde_json::from_str(&text) {
1489                            Ok(e) => {
1490                                let err: error::FredError = e;
1491                                let err_msg = format!(
1492                                    "ERROR {}: {}",
1493                                    err.error_code,
1494                                    err.error_message
1495                                );
1496                                return Err(err_msg);
1497                            },
1498                            Err(msg) => return Err(String::from(msg.to_string())),
1499                        }
1500                    },
1501                }
1502            },
1503            Err(e) => return Err(e.to_string()),
1504        }
1505    }
1506}
1507
1508#[cfg(test)]
1509mod tests {
1510    use super::*;
1511
1512    #[test]
1513    fn client_new() {
1514        match FredClient::new() {
1515            Ok(_) => assert_eq!(1, 1),
1516            Err(msg) => {
1517                println!("{}", msg);
1518                assert_eq!(2, 1)
1519            },
1520        }
1521    }
1522}