Skip to content

Commit

Permalink
Merge pull request #21 from jontze/feat/add-helper-macro
Browse files Browse the repository at this point in the history
Add helper macro
  • Loading branch information
jontze authored Aug 16, 2023
2 parents f4013ad + 97a61d4 commit 1e333e1
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 20 deletions.
2 changes: 1 addition & 1 deletion src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use price::PriceApi;
use station::StationApi;
use std::sync::Arc;

/// The main struct of the crate giving access to the station and price api of tankerkoenig.
/// The main struct of the crate giving access to the [`StationApi`] and [`PriceApi`] of tankerkoenig.
/// Create a new instance of the struct with your api key as parameter.
///
/// ## Example
Expand Down
46 changes: 27 additions & 19 deletions src/api/price.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,9 @@ impl PriceApi {

/// Fetch the prices of all fuel types of the given station ids (up to 10 at once).
///
/// ## Further Explanation
/// You can only fetch 10 stations at once. If you want to fetch more than 10 stations,
/// You can only fetch prices for 10 stations at once. If you want to fetch more than 10 stations,
/// you have to call this function multiple times. This is due to a limitation of the
/// [tankerkoenig API](https://creativecommons.tankerkoenig.de/).
/// Read more about that on their [website](https://creativecommons.tankerkoenig.de/)
/// [tankerkoenig API](https://creativecommons.tankerkoenig.de/). Use the helper [`macro@chunk_into_option_arrays`](crate::chunk_into_option_arrays) to make this easier.
///
/// ## Example
/// ```
Expand All @@ -64,6 +62,27 @@ impl PriceApi {
/// Ok(prices)
/// }
/// ```
///
/// ## Example with [`macro@chunk_into_option_arrays`](crate::chunk_into_option_arrays)
/// ```
/// use tankerkoenig::Tankerkoenig;
/// use tankerkoenig::models;
/// use tankerkoenig::chunk_into_option_arrays;
///
/// async fn request_station_prices() -> Result<Vec<models::PriceResponse>, tankerkoenig::Error> {
/// let tanker = Tankerkoenig::new("your-api-key")?;
/// let station_ids = ["id-1", "id-2", "id-3", "id-4", "id-5", "id-6", "id-7"];
///
/// let mut all_prices = Vec::new();
/// for chunk in chunk_into_option_arrays!(station_ids) {
/// let prices = tanker.price.fetch(&chunk).await?;
/// // Remember to wait between the requests to not get blocked by the API
/// all_prices.push(prices);
/// }
/// Ok(all_prices)
/// }
/// ```
///
pub async fn fetch<S>(
&self,
ids: &[Option<S>; MAX_REQUEST_STATION_IDS],
Expand Down Expand Up @@ -162,22 +181,11 @@ mod test {
Pin::from(Box::new(ready(result)))
});

let ids = ["456", "789"];
let transformed = crate::chunk_into_option_arrays!(ids);

let api = PriceApi::new(Arc::new(Box::new(mock_client)), api_key);
let res = api
.fetch(&[
Some("456"),
Some("789"),
None,
None,
None,
None,
None,
None,
None,
None,
])
.await
.unwrap();
let res = api.fetch(&transformed.get(0).unwrap()).await.unwrap();

let station_prices: models::price::PriceResponse =
serde_json::from_str(&data_string).unwrap();
Expand Down
108 changes: 108 additions & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,43 @@
/// Macro to transform a vector into a vector of arrays with a fixed size of 10.
/// The last array will be filled with None if the vector is not divisible by 10.
///
/// # Example
/// ```
/// use tankerkoenig::chunk_into_option_arrays;
///
/// let input_vec = vec!["1", "2", "3", "4", "5", "6", "7", "8", "9"];
/// let output_vec = chunk_into_option_arrays!(input_vec);
///
/// assert_eq!(output_vec.len(), 1);
/// assert_eq!(output_vec[0], [
/// Some("1".to_string()),
/// Some("2".to_string()),
/// Some("3".to_string()),
/// Some("4".to_string()),
/// Some("5".to_string()),
/// Some("6".to_string()),
/// Some("7".to_string()),
/// Some("8".to_string()),
/// Some("9".to_string()),
/// None]);
/// ```
///
#[macro_export]
macro_rules! chunk_into_option_arrays {
($input_vec:expr) => {{
$input_vec
.chunks(10)
.map(|chunk| {
let mut current: [Option<String>; 10] = Default::default();
for (index, value) in chunk.iter().enumerate() {
current[index] = Some((value.as_ref() as &str).to_string());
}
current
})
.collect::<Vec<[Option<String>; 10]>>()
}};
}

pub(crate) mod price {
use std::{cell::RefCell, rc::Rc};

Expand Down Expand Up @@ -26,6 +66,74 @@ pub(crate) mod price {
}
}

#[cfg(test)]
mod macro_test {

#[test]
fn transform_vector_to_vector_of_single_array() {
let input = vec!["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"];
let output = chunk_into_option_arrays![input];
assert_eq!(
output,
vec![[
Some("a".to_string()),
Some("b".to_string()),
Some("c".to_string()),
Some("d".to_string()),
Some("e".to_string()),
Some("f".to_string()),
Some("g".to_string()),
Some("h".to_string()),
Some("i".to_string()),
Some("j".to_string())
]]
);
}

#[test]
fn transform_vector_to_vector_of_multiple_arrays_filled_with_none() {
let input = vec!["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "f"];
let output = chunk_into_option_arrays![input];
assert_eq!(
output,
vec![
[
Some("a".to_string()),
Some("b".to_string()),
Some("c".to_string()),
Some("d".to_string()),
Some("e".to_string()),
Some("f".to_string()),
Some("g".to_string()),
Some("h".to_string()),
Some("i".to_string()),
Some("j".to_string())
],
[
Some("f".to_string()),
None,
None,
None,
None,
None,
None,
None,
None,
None
]
]
);
}

#[test]
fn transform_empty_vector_to_empty_vector() {
let input: Vec<&str> = vec![];
let output = chunk_into_option_arrays![input];
let expected: Vec<[Option<String>; 10]> = vec![];
assert_eq!(output, expected);
}
}

#[cfg(test)]
mod price_test {
use super::price::*;
Expand Down

0 comments on commit 1e333e1

Please sign in to comment.