use std::{collections::HashMap, str::FromStr};
use derive_builder::Builder;
use http::{HeaderValue, Request};
pub trait FeaturedEndpoint {
fn features(&self) -> Option<Features>;
}
#[derive(Builder, Default, Debug, Clone)]
#[builder(setter(strip_option, into), default)]
pub struct Features {
pub blocking: Option<Blocking>,
pub cached: Option<String>,
pub filter: Option<String>,
pub mode: Option<ConsistencyMode>,
}
impl Features {
#[instrument(skip(self, request))]
pub fn process(&self, request: &mut Request<Vec<u8>>) {
let mut query = HashMap::<String, String>::new();
let mut keys = Vec::<String>::new();
info!("Adding features to request");
if let Some(b) = &self.blocking {
if let Some(w) = &b.wait {
query.insert("wait".into(), w.clone());
}
query.insert("index".into(), b.index.to_string());
}
if let Some(c) = &self.cached {
if !c.is_empty() {
request
.headers_mut()
.insert("Cache-Control", HeaderValue::from_str(c.as_str()).unwrap());
}
keys.push("cached".into());
}
if let Some(f) = &self.filter {
query.insert("filter".into(), f.clone());
}
if let Some(m) = &self.mode {
let mode = match m {
ConsistencyMode::CONSISTENT => "consistent",
ConsistencyMode::STALE => "stale",
};
keys.push(mode.into())
}
let mut url = url::Url::parse(request.uri().to_string().as_str()).unwrap();
if !query.is_empty() {
url.query_pairs_mut().extend_pairs(query);
}
if !keys.is_empty() {
url.query_pairs_mut()
.extend_keys_only::<Vec<String>, String>(keys);
}
*request.uri_mut() = http::Uri::from_str(url.as_str()).unwrap();
info!("Final url with features: {}", request.uri());
}
pub fn builder() -> FeaturesBuilder {
FeaturesBuilder::default()
}
}
#[derive(Debug, Clone)]
pub struct Blocking {
pub index: u64,
pub wait: Option<String>,
}
#[derive(Debug, Clone)]
pub enum ConsistencyMode {
CONSISTENT,
STALE,
}