use super::{Form, Method};
use crate::{
error::Error,
routing::{Path, Route},
};
use hyper::header::{HeaderMap, HeaderName, HeaderValue};
use serde::Serialize;
#[derive(Debug)]
#[must_use = "request has not been fully built"]
pub struct RequestBuilder(Request);
impl RequestBuilder {
pub fn new(route: &Route<'_>) -> Self {
Self(Request::from_route(route))
}
pub const fn raw(method: Method, ratelimit_path: Path, path_and_query: String) -> Self {
Self(Request {
body: None,
form: None,
headers: None,
method,
path: path_and_query,
ratelimit_path,
use_authorization_token: true,
})
}
#[allow(clippy::missing_const_for_fn)]
#[must_use = "request information is not useful on its own and must be acted on"]
pub fn build(self) -> Request {
self.0
}
pub fn body(mut self, body: Vec<u8>) -> Self {
self.0.body = Some(body);
self
}
#[allow(clippy::missing_const_for_fn)]
pub fn form(mut self, form: Form) -> Self {
self.0.form = Some(form);
self
}
pub fn headers(mut self, iter: impl Iterator<Item = (HeaderName, HeaderValue)>) -> Self {
self.0.headers.replace(iter.collect());
self
}
pub fn json(self, to: &impl Serialize) -> Result<Self, Error> {
let bytes = crate::json::to_vec(to).map_err(Error::json)?;
Ok(self.body(bytes))
}
pub const fn use_authorization_token(mut self, use_authorization_token: bool) -> Self {
self.0.use_authorization_token = use_authorization_token;
self
}
}
#[derive(Clone, Debug)]
pub struct Request {
pub(crate) body: Option<Vec<u8>>,
pub(crate) form: Option<Form>,
pub(crate) headers: Option<HeaderMap<HeaderValue>>,
pub(crate) method: Method,
pub(crate) path: String,
pub(crate) ratelimit_path: Path,
pub(crate) use_authorization_token: bool,
}
impl Request {
pub fn builder(route: &Route<'_>) -> RequestBuilder {
RequestBuilder::new(route)
}
pub fn from_route(route: &Route<'_>) -> Self {
Self {
body: None,
form: None,
headers: None,
method: route.method(),
path: route.to_string(),
ratelimit_path: route.to_path(),
use_authorization_token: true,
}
}
pub fn body(&self) -> Option<&[u8]> {
self.body.as_deref()
}
pub const fn form(&self) -> Option<&Form> {
self.form.as_ref()
}
pub const fn headers(&self) -> Option<&HeaderMap<HeaderValue>> {
self.headers.as_ref()
}
pub const fn method(&self) -> Method {
self.method
}
pub fn path(&self) -> &str {
&self.path
}
pub const fn ratelimit_path(&self) -> &Path {
&self.ratelimit_path
}
pub const fn use_authorization_token(&self) -> bool {
self.use_authorization_token
}
}
#[cfg(test)]
mod tests {
use super::RequestBuilder;
use static_assertions::assert_impl_all;
use std::fmt::Debug;
assert_impl_all!(RequestBuilder: Debug, Send, Sync);
}