use std::{
convert::Infallible,
sync::{Arc, atomic::AtomicUsize},
};
use crate::{task::Task, task::from_request::FromRequest};
#[derive(Debug, Clone)]
pub struct Attempt(Arc<AtomicUsize>);
impl Default for Attempt {
fn default() -> Self {
Self(Arc::new(AtomicUsize::new(0)))
}
}
impl Attempt {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn new_with_value(value: usize) -> Self {
Self(Arc::new(AtomicUsize::from(value)))
}
#[must_use]
pub fn current(&self) -> usize {
self.0.load(std::sync::atomic::Ordering::SeqCst)
}
#[must_use]
pub(crate) fn increment(&self) -> usize {
self.0.fetch_add(1, std::sync::atomic::Ordering::SeqCst)
}
}
impl<Args> FromRequest<Task<Args>> for Attempt
where
Args: Sync,
{
type Error = Infallible;
async fn from_request(task: &Task<Args>) -> Result<Self, Self::Error> {
Ok(task.raw_attempt().clone())
}
}
#[cfg(feature = "serde")]
mod serde_impl {
use std::sync::atomic::Ordering;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use super::*;
fn serialize<S>(attempt: &Attempt, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let value = attempt.0.load(Ordering::SeqCst);
serializer.serialize_u64(value as u64)
}
fn deserialize<'de, D>(deserializer: D) -> Result<Attempt, D::Error>
where
D: Deserializer<'de>,
{
let value = u64::deserialize(deserializer)?;
Ok(Attempt(Arc::new(AtomicUsize::new(value as usize))))
}
impl Serialize for Attempt {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serialize(self, serializer)
}
}
impl<'de> Deserialize<'de> for Attempt {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserialize(deserializer)
}
}
}