use std::future::Future;
use url::Url;
pub trait Session {
fn should_procede(&mut self, url: &Url) -> bool;
fn mark_success(&mut self, url: &Url);
fn mark_failure(&mut self, url: &Url);
}
pub trait SessionFactory {
type Session: Session;
fn build_session(&self) -> Self::Session;
}
pub struct RequestCountSession {
count: usize,
max_requests: usize,
}
#[derive(Clone, Debug)]
pub struct SessionError;
pub async fn guard<Fut, T, E, S>(fut: Fut, url: &Url, mut session: S) -> Result<T, E>
where
Fut: Future<Output = Result<T, E>>,
E: From<SessionError>,
S: Session,
{
if !session.should_procede(url) {
return Err(SessionError.into());
}
match fut.await {
Ok(t) => {
session.mark_success(url);
Ok(t)
}
Err(e) => {
session.mark_failure(url);
Err(e)
}
}
}
impl RequestCountSession {
pub fn max(max_requests: usize) -> Self {
Self {
count: 0,
max_requests,
}
}
}
impl std::fmt::Display for SessionError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "SessionError")
}
}
impl std::error::Error for SessionError {}
impl Session for RequestCountSession {
fn should_procede(&mut self, _: &Url) -> bool {
self.count < self.max_requests
}
fn mark_success(&mut self, _: &Url) {
self.count += 1;
}
fn mark_failure(&mut self, _: &Url) {
self.count += 1;
}
}
impl Session for () {
fn should_procede(&mut self, _: &Url) -> bool {
true
}
fn mark_success(&mut self, _: &Url) {}
fn mark_failure(&mut self, _: &Url) {}
}
impl<'a, T> Session for &'a mut T
where
T: Session,
{
fn should_procede(&mut self, url: &Url) -> bool {
T::should_procede(self, url)
}
fn mark_success(&mut self, url: &Url) {
T::mark_success(self, url)
}
fn mark_failure(&mut self, url: &Url) {
T::mark_failure(self, url)
}
}
impl<T> Session for Box<T>
where
T: Session,
{
fn should_procede(&mut self, url: &Url) -> bool {
T::should_procede(self, url)
}
fn mark_success(&mut self, url: &Url) {
T::mark_success(self, url)
}
fn mark_failure(&mut self, url: &Url) {
T::mark_failure(self, url)
}
}
impl<T, U> Session for (T, U)
where
T: Session,
U: Session,
{
fn should_procede(&mut self, url: &Url) -> bool {
self.0.should_procede(url) && self.1.should_procede(url)
}
fn mark_success(&mut self, url: &Url) {
self.0.mark_success(url);
self.1.mark_success(url);
}
fn mark_failure(&mut self, url: &Url) {
self.0.mark_failure(url);
self.1.mark_failure(url);
}
}
impl<T, U, V> Session for (T, U, V)
where
T: Session,
U: Session,
V: Session,
{
fn should_procede(&mut self, url: &Url) -> bool {
self.0.should_procede(url) && self.1.should_procede(url) && self.2.should_procede(url)
}
fn mark_success(&mut self, url: &Url) {
self.0.mark_success(url);
self.1.mark_success(url);
self.2.mark_success(url);
}
fn mark_failure(&mut self, url: &Url) {
self.0.mark_failure(url);
self.1.mark_failure(url);
self.2.mark_failure(url);
}
}
impl<T, U, V, W> Session for (T, U, V, W)
where
T: Session,
U: Session,
V: Session,
W: Session,
{
fn should_procede(&mut self, url: &Url) -> bool {
self.0.should_procede(url)
&& self.1.should_procede(url)
&& self.2.should_procede(url)
&& self.3.should_procede(url)
}
fn mark_success(&mut self, url: &Url) {
self.0.mark_success(url);
self.1.mark_success(url);
self.2.mark_success(url);
self.3.mark_success(url);
}
fn mark_failure(&mut self, url: &Url) {
self.0.mark_failure(url);
self.1.mark_failure(url);
self.2.mark_failure(url);
self.3.mark_failure(url);
}
}
impl<T, U, V, W, X> Session for (T, U, V, W, X)
where
T: Session,
U: Session,
V: Session,
W: Session,
X: Session,
{
fn should_procede(&mut self, url: &Url) -> bool {
self.0.should_procede(url)
&& self.1.should_procede(url)
&& self.2.should_procede(url)
&& self.3.should_procede(url)
&& self.4.should_procede(url)
}
fn mark_success(&mut self, url: &Url) {
self.0.mark_success(url);
self.1.mark_success(url);
self.2.mark_success(url);
self.3.mark_success(url);
self.4.mark_success(url);
}
fn mark_failure(&mut self, url: &Url) {
self.0.mark_failure(url);
self.1.mark_failure(url);
self.2.mark_failure(url);
self.3.mark_failure(url);
self.4.mark_failure(url);
}
}
impl<T, U, V, W, X, Y> Session for (T, U, V, W, X, Y)
where
T: Session,
U: Session,
V: Session,
W: Session,
X: Session,
Y: Session,
{
fn should_procede(&mut self, url: &Url) -> bool {
self.0.should_procede(url)
&& self.1.should_procede(url)
&& self.2.should_procede(url)
&& self.3.should_procede(url)
&& self.4.should_procede(url)
&& self.5.should_procede(url)
}
fn mark_success(&mut self, url: &Url) {
self.0.mark_success(url);
self.1.mark_success(url);
self.2.mark_success(url);
self.3.mark_success(url);
self.4.mark_success(url);
self.5.mark_success(url);
}
fn mark_failure(&mut self, url: &Url) {
self.0.mark_failure(url);
self.1.mark_failure(url);
self.2.mark_failure(url);
self.3.mark_failure(url);
self.4.mark_failure(url);
self.5.mark_failure(url);
}
}
impl<T, U, V, W, X, Y, Z> Session for (T, U, V, W, X, Y, Z)
where
T: Session,
U: Session,
V: Session,
W: Session,
X: Session,
Y: Session,
Z: Session,
{
fn should_procede(&mut self, url: &Url) -> bool {
self.0.should_procede(url)
&& self.1.should_procede(url)
&& self.2.should_procede(url)
&& self.3.should_procede(url)
&& self.4.should_procede(url)
&& self.5.should_procede(url)
&& self.6.should_procede(url)
}
fn mark_success(&mut self, url: &Url) {
self.0.mark_success(url);
self.1.mark_success(url);
self.2.mark_success(url);
self.3.mark_success(url);
self.4.mark_success(url);
self.5.mark_success(url);
self.6.mark_success(url);
}
fn mark_failure(&mut self, url: &Url) {
self.0.mark_failure(url);
self.1.mark_failure(url);
self.2.mark_failure(url);
self.3.mark_failure(url);
self.4.mark_failure(url);
self.5.mark_failure(url);
self.6.mark_failure(url);
}
}