recipes/api/src/rest/ctrl/ingredient.rs

58 lines
1.7 KiB
Rust

use std::io::Cursor;
use std::str::FromStr;
use tiny_http::{Header, Response};
use crate::domain;
use crate::domain::ingredient::types::Lang;
use crate::repo::ingredient::StaticIngredientRepo;
use crate::rest::types::{QueryParams, Url};
#[derive(Default, Debug)]
struct FetchIngredientsOpts<'a> {
lang: Option<&'a str>,
keys: Option<Vec<&'a str>>,
}
impl<'a> From<QueryParams<'a>> for FetchIngredientsOpts<'a> {
fn from(params: QueryParams<'a>) -> Self {
params
.into_iter()
.fold(FetchIngredientsOpts::default(), |mut opts, p| {
match p {
("lang", val) => opts.lang = Some(val),
("key", val) => {
let mut keys = opts.keys.unwrap_or_default();
keys.push(val);
opts.keys = Some(keys)
}
_ => {}
};
opts
})
}
}
impl From<FetchIngredientsOpts<'_>> for domain::ingredient::fetch_list::RequestOpts {
fn from(rest: FetchIngredientsOpts) -> Self {
let lang = rest.lang.and_then(|l| Lang::from_str(l).ok());
let keys = rest
.keys
.map(|keys| keys.into_iter().map(String::from).collect());
Self { lang, keys }
}
}
pub fn fetch_list(url: &Url) -> Response<Cursor<Vec<u8>>> {
use domain::ingredient::fetch_list;
let opts = FetchIngredientsOpts::from(url.query_params());
let repo = StaticIngredientRepo;
let ingredients = fetch_list::execute(&repo, opts.into());
let data = serde_json::to_string(&ingredients).unwrap();
Response::from_string(data)
.with_header(Header::from_str("content-type: application/json").unwrap())
}