use std::{cell::Cell, rc::Rc, sync::Arc};
use bytes::Bytes;
use crate::{
body::Body,
headers::{HeaderName, HeaderValue, Headers},
matchers,
matchers::Matcher,
request::Method,
};
#[derive(Default, Clone)]
pub struct When(Rc<Cell<Vec<Arc<dyn Matcher>>>>);
impl When {
pub fn new() -> Self {
Self(Rc::new(Cell::new(Vec::new())))
}
pub fn into_inner(self) -> Vec<Arc<dyn Matcher>> {
let mut m = self.0.take();
m.sort_unstable();
m.dedup();
m
}
fn push(&self, matcher: impl Matcher) {
let mut m = self.0.take();
m.push(Arc::new(matcher));
self.0.set(m);
}
pub fn any(self) -> Self {
self.push(matchers::any());
self
}
pub fn method(self, method: impl Into<Method>) -> Self {
self.push(matchers::method(method.into()));
self
}
pub fn path(self, path: impl Into<String>) -> Self {
self.push(matchers::path(path));
self
}
pub fn path_prefix(self, prefix: impl Into<String>) -> Self {
self.push(matchers::path_prefix(prefix));
self
}
pub fn body(self, body: Body) -> Self {
self.push(matchers::body(body));
self
}
pub fn headers<T, U>(self, headers: impl IntoIterator<Item = (T, U)>) -> Self
where
T: Into<HeaderName>,
U: Into<HeaderValue>,
{
self.push(matchers::headers(Headers::from_iter(headers)));
self
}
pub fn headers_exact<T, U>(self, headers: impl IntoIterator<Item = (T, U)>) -> Self
where
T: Into<HeaderName>,
U: Into<HeaderValue>,
{
self.push(matchers::headers_exact(Headers::from_iter(headers)));
self
}
pub fn header(self, name: impl Into<String>, value: impl Into<String>) -> Self {
self.push(matchers::header(name, value));
self
}
pub fn header_exists(self, name: impl Into<String>) -> Self {
self.push(matchers::header_exists(name));
self
}
pub fn query_params(
self,
pairs: impl IntoIterator<Item = (impl Into<String>, impl Into<String>)>,
) -> Self {
self.push(matchers::query_params(pairs));
self
}
pub fn query_param(self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.push(matchers::query_param(key, value));
self
}
pub fn query_param_exists(self, key: impl Into<String>) -> Self {
self.push(matchers::query_param_exists(key));
self
}
pub fn matcher(self, matcher: impl Matcher) -> Self {
self.push(matcher);
self
}
}
impl When {
pub fn empty(self) -> Self {
self.push(matchers::body(Body::empty()));
self
}
pub fn bytes(self, body: impl Into<Bytes>) -> Self {
self.push(matchers::body(Body::bytes(body.into())));
self
}
pub fn bytes_stream(self, messages: impl IntoIterator<Item = impl Into<Bytes>>) -> Self {
self.push(matchers::body(Body::bytes_stream(messages)));
self
}
pub fn text(self, body: impl Into<String>) -> Self {
let body: String = body.into();
self.push(matchers::body(Body::bytes(body)));
self
}
pub fn text_stream(self, messages: impl IntoIterator<Item = impl Into<String>>) -> Self {
let messages = messages.into_iter().map(|msg| {
let msg: String = msg.into();
msg
});
self.push(matchers::body(Body::bytes_stream(messages)));
self
}
pub fn json(self, body: impl serde::Serialize) -> Self {
self.push(matchers::body(Body::json(body)));
self
}
pub fn json_lines_stream(
self,
messages: impl IntoIterator<Item = impl serde::Serialize>,
) -> Self {
self.push(matchers::body(Body::json_lines_stream(messages)));
self
}
pub fn pb(self, body: impl prost::Message) -> Self {
self.push(matchers::body(Body::pb(body)));
self
}
pub fn pb_stream(self, messages: impl IntoIterator<Item = impl prost::Message>) -> Self {
self.push(matchers::body(Body::pb_stream(messages)));
self
}
}
impl When {
pub fn get(self) -> Self {
self.push(matchers::method(Method::GET));
self
}
pub fn post(self) -> Self {
self.push(matchers::method(Method::POST));
self
}
pub fn put(self) -> Self {
self.push(matchers::method(Method::PUT));
self
}
pub fn delete(self) -> Self {
self.push(matchers::method(Method::DELETE));
self
}
pub fn head(self) -> Self {
self.push(matchers::method(Method::HEAD));
self
}
}