freedom_api/extensions/
mod.rs

1//! # FPS API Extension Traits
2//!
3//! This modules contains a collection of extension traits for the `freedom_models` to enable a
4//! HATEOAS-esque API from within rust.
5//!
6//! These are implemented as traits to allow the `freedom_models` crate to remain extremely thin,
7//! so that when it is ingested by other crates which do not require this functionality, it does
8//! not contribute to the dependency graph.
9//!
10//! ## Container
11//!
12//! Unlike the objects fetched directly from the API, objects fetched through a parent are not
13//! wrapped in the `Container<T>` type. This is deliberate as certain objects are nested deeply and
14//! muddy the API when wrapping.
15
16use std::collections::HashMap;
17
18use freedom_models::{Hateoas, utils::Content};
19
20use crate::{api::Value, error, prelude::Api};
21mod account;
22mod band;
23mod request;
24mod satellite;
25mod site;
26mod task;
27mod user;
28
29pub use {
30    account::AccountExt,
31    band::BandExt,
32    request::TaskRequestExt,
33    satellite::{SatelliteConfigurationExt, SatelliteExt},
34    site::{SiteConfigurationExt, SiteExt},
35    task::TaskExt,
36    user::UserExt,
37};
38
39fn get_id(reference: &'static str, links: &HashMap<String, url::Url>) -> Result<i32, error::Error> {
40    let url = links
41        .get(reference)
42        .ok_or(error::Error::MissingUri(reference))?;
43
44    let id_str = url
45        .path_segments()
46        .ok_or(error::Error::InvalidUri("Missing Path".into()))?
47        .next_back()
48        .ok_or(error::Error::InvalidId)?;
49
50    id_str.parse().map_err(|_| error::Error::InvalidId)
51}
52
53async fn get_item<T, C>(
54    reference: &'static str,
55    links: &HashMap<String, url::Url>,
56    client: &C,
57) -> Result<T, error::Error>
58where
59    C: Api,
60    T: Value,
61{
62    let uri = links
63        .get(reference)
64        .ok_or(error::Error::MissingUri(reference))?
65        .clone();
66
67    client.get_json_map(uri).await
68}
69
70async fn get_embedded<T, C>(
71    reference: &'static str,
72    links: &HashMap<String, url::Url>,
73    client: &C,
74) -> Result<T, error::Error>
75where
76    C: Api,
77    T: Value,
78{
79    use freedom_models::utils::Embedded;
80
81    let wrapped = get_item::<Embedded<T>, C>(reference, links, client).await?;
82
83    Ok(wrapped.items)
84}
85
86async fn get_content<T, C>(
87    reference: &'static str,
88    links: &HashMap<String, url::Url>,
89    client: &C,
90) -> Result<T, error::Error>
91where
92    C: Api + Send,
93    T: Value + Hateoas,
94{
95    let wrapped = get_item::<Content<T>, C>(reference, links, client).await?;
96
97    Ok(wrapped.inner)
98}