use std::time::Duration;
use crate::types::{Cookie, Cookies, SameSite};
#[derive(Debug)]
pub struct CookieOptions {
pub name: &'static str,
pub path: &'static str,
pub secure: bool,
pub http_only: bool,
pub max_age: Option<Duration>,
pub domain: Option<&'static str>,
pub same_site: Option<SameSite>,
}
impl CookieOptions {
pub const MAX_AGE: u64 = 3600 * 24;
#[must_use]
pub fn new(name: &'static str) -> Self {
Self::default().name(name)
}
#[must_use]
pub fn name(mut self, name: &'static str) -> Self {
self.name = name;
self
}
#[must_use]
pub fn max_age(mut self, max_age: Duration) -> Self {
self.max_age.replace(max_age);
self
}
#[must_use]
pub fn domain(mut self, domain: &'static str) -> Self {
self.domain.replace(domain);
self
}
#[must_use]
pub fn path(mut self, path: &'static str) -> Self {
self.path = path;
self
}
#[must_use]
pub fn secure(mut self, secure: bool) -> Self {
self.secure = secure;
self
}
#[must_use]
pub fn http_only(mut self, http_only: bool) -> Self {
self.http_only = http_only;
self
}
#[must_use]
pub fn same_site(mut self, same_site: SameSite) -> Self {
self.same_site.replace(same_site);
self
}
pub fn into_cookie(&self, value: impl Into<String>) -> Cookie<'_> {
let mut cookie = Cookie::new(self.name, value.into());
cookie.set_path(self.path);
cookie.set_secure(self.secure);
cookie.set_http_only(self.http_only);
cookie.set_same_site(self.same_site);
if let Some(domain) = self.domain {
cookie.set_domain(domain);
}
if let Some(max_age) = self.max_age {
cookie
.set_max_age(::cookie::time::Duration::try_from(max_age).expect(
"`std::time::Duration` cannot be converted to `cookie::ime::Duration`",
));
}
cookie
}
}
impl Default for CookieOptions {
fn default() -> Self {
Self {
domain: None,
secure: true,
http_only: true,
path: "/",
name: "viz.sid",
same_site: Some(SameSite::Lax),
max_age: Some(Duration::from_secs(Self::MAX_AGE)),
}
}
}
#[cfg(not(feature = "cookie-private"))]
pub trait Cookieable {
fn options(&self) -> &CookieOptions;
fn get_cookie<'a>(&'a self, cookies: &'a Cookies) -> Option<Cookie<'a>> {
cookies.get(self.options().name)
}
fn remove_cookie<'a>(&'a self, cookies: &'a Cookies) {
cookies.remove(self.options().name);
}
fn set_cookie<'a>(&'a self, cookies: &'a Cookies, value: impl Into<String>) {
cookies.add(self.options().into_cookie(value));
}
}
#[cfg(feature = "cookie-private")]
pub trait Cookieable {
fn options(&self) -> &CookieOptions;
fn get_cookie<'a>(&'a self, cookies: &'a Cookies) -> Option<Cookie<'a>> {
cookies.private_get(self.options().name)
}
fn remove_cookie<'a>(&'a self, cookies: &'a Cookies) {
cookies.private_remove(self.options().name);
}
fn set_cookie<'a>(&'a self, cookies: &'a Cookies, value: impl Into<String>) {
cookies.private_add(self.options().into_cookie(value));
}
}