timer-deque-rs 0.8.0

A OS based timer and timer queue which implements timeout queues of different types.
Documentation
/*-
 * timer-deque-rs - a Rust crate which provides timer and timer queues based on target OS
 *  functionality.
 * 
 * Copyright (C) 2025 Aleksandr Morozov alex@nixd.org
 *  4neko.org alex@4neko.org
 * 
 * The timer-rs crate can be redistributed and/or modified
 * under the terms of either of the following licenses:
 *
 *   1. the Mozilla Public License Version 2.0 (the “MPL”) OR
 *                     
 *   2. The MIT License (MIT)
 *                     
 *   3. EUROPEAN UNION PUBLIC LICENCE v. 1.2 EUPL © the European Union 2007, 2016
 */

use std::{borrow::Borrow, fmt, sync::{Arc, Weak}};

use crate::
{
    common::TimerDequeId, 
    deque_timeout::{OrderedTimerDequeHandle, OrderedTimerDequeInterf, OrderedTimerDequeMode}, 
    error::{TimerErrorType, TimerResult}, 
    map_timer_err, 
    timer_portable::timer::{AbsoluteTime, RelativeTime}
};



/// A ticket which is issued to the caller. 
/// If `TimerDequeTicket` is dropped, the [Weak] reference to [Arc]
/// will no longer be valid and the timer would ignore the instance and remove
/// it from the queue independeltly from the deque operation mode.
#[derive(Debug, Hash, Eq, PartialOrd, Ord)]
pub struct TimerDequeTicket
{
    /// It holds the uniq ID which can be used to remove the instance 
    /// from the queue manually.
    status: Arc<TimerDequeId>,
}

impl AsRef<TimerDequeId> for TimerDequeTicket
{
    fn as_ref(&self) -> &TimerDequeId 
    {
        return &self.status;
    }
}

impl Borrow<TimerDequeId> for TimerDequeTicket
{
    fn borrow(&self) -> &TimerDequeId 
    {
        return &self.status;
    }
}

impl fmt::Display for TimerDequeTicket
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
    {
        write!(f, "{}", self.status)
    }
}

impl PartialEq for TimerDequeTicket
{
    fn eq(&self, other: &Self) -> bool 
    {
        return self.status == other.status;
    }
}

impl PartialEq<TimerDequeId> for TimerDequeTicket
{
    fn eq(&self, other: &TimerDequeId) -> bool 
    {
        return self.status.as_ref() == other;
    }
}

impl PartialEq<&TimerDequeId> for TimerDequeTicket
{
    fn eq(&self, other: &&TimerDequeId) -> bool 
    {
        return self.status.as_ref() == *other;
    }
}

impl PartialEq<TimerDequeTicket> for TimerDequeId
{
    fn eq(&self, other: &TimerDequeTicket) -> bool 
    {
        return self == other.status.as_ref();
    }
}

impl<MODE: OrderedTimerDequeMode> PartialEq<TimerDequeTicketIssuer<MODE>> for TimerDequeTicket
{
    fn eq(&self, other: &TimerDequeTicketIssuer<MODE>) -> bool 
    {
        let Some(up) = other.weak_status.upgrade()
            else { return false };

        return self.status.as_ref() == up.as_ref();
    }
}

impl TimerDequeTicket
{
    fn new() -> Self
    {
        return 
            Self
            { 
                status: 
                    Arc::new(TimerDequeId::new()),
            };
    }

    fn pair(&self) -> Weak<TimerDequeId>
    {
        return Arc::downgrade(&self.status);
    }

    pub 
    fn get_deque_id(&self) -> &TimerDequeId
    {
        return self.status.as_ref();
    }

    pub 
    fn is_queued(&self) -> bool
    {
        return Arc::weak_count(&self.status) > 1;
    }
}

/// A type of deque which issues a `tickets` [TimerDequeTicket] which
/// contains a [TimerDequeId] - a uniq number of the ticket.
/// On timeout, the [TimerDequeId] is returned to indentify the timeout
/// source.
/// 
/// # Generics
/// 
/// `MODE` - a [OrderedTimerDequeMode] defines the deque behaviour. There are
///     two types of the operation:
/// 
/// * [`DequeOnce`]: crate::deque_timeout#DequeOnce  
/// After timeout the element is removed from the queue.
/// 
/// * [`DequePeriodic`]: crate::deque_timeout#DequePeriodic  
/// After timeout the element timeout is extended automatically
/// until the item removed from the queue manually.
/// 
/// # Examples
/// 
/// ```ignore
/// let mut time_list = 
///     OrderedTimerDeque
///         ::<DequeOnce, TimerDequeTicketIssuer<_>>
///         ::new("test_label1".into(), 4, false, true)
///            .unwrap();
/// ```
/// or
/// ```ignore
/// let mut time_list = 
///     OrderedTimerDeque
///         ::<DequePeriodic, TimerDequeTicketIssuer<_>>
///         ::new("test_label1".into(), 4, false, true)
///            .unwrap();
/// ```
#[derive(Debug)]
pub struct TimerDequeTicketIssuer<MODE>
where 
    MODE: OrderedTimerDequeMode
{
    /// A [Weak] reference to [Arc] which holds the queue identification.
    weak_status: Weak<TimerDequeId>,

    /// An absolute timestamp in seconds (UTC time) sets the timer.
    timeout_mode: MODE,
}

impl<MODE: OrderedTimerDequeMode> fmt::Display for TimerDequeTicketIssuer<MODE>
{  
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> 
    { 
        write!(f, "{} until: {}", self.weak_status.upgrade().map_or("dropped".into(), |f| f.to_string()), 
            self.timeout_mode)
    }
}

impl<MODE: OrderedTimerDequeMode> Eq for TimerDequeTicketIssuer<MODE> {}

impl<MODE: OrderedTimerDequeMode> PartialEq for TimerDequeTicketIssuer<MODE>
{
    fn eq(&self, other: &Self) -> bool 
    {
        let s = self.weak_status.upgrade();
        let o = other.weak_status.upgrade();

        return s == o;
    }
}

impl<MODE: OrderedTimerDequeMode> PartialEq<TimerDequeId> for TimerDequeTicketIssuer<MODE>
{
    fn eq(&self, other: &TimerDequeId) -> bool 
    {
        return 
            self
                .weak_status
                .upgrade()
                .map_or(false, |f| f.as_ref() == other);
    }
}

impl<MODE: OrderedTimerDequeMode> PartialEq<TimerDequeTicket> for TimerDequeTicketIssuer<MODE>
{
    fn eq(&self, other: &TimerDequeTicket) -> bool 
    {
        let Some(s) = self.weak_status.upgrade()
            else { return false };

        return s.as_ref() == other.status.as_ref();
    }
}

impl<MODE: OrderedTimerDequeMode> Ord for TimerDequeTicketIssuer<MODE>
{
    fn cmp(&self, other: &Self) -> std::cmp::Ordering 
    {
        return self.timeout_mode.cmp(&other.timeout_mode);
    }
}

impl<MODE: OrderedTimerDequeMode> PartialOrd for TimerDequeTicketIssuer<MODE>
{
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> 
    {
        return Some(self.cmp(other));
    }
}

impl<MODE> TimerDequeTicketIssuer<MODE>
where   
    MODE: OrderedTimerDequeMode
{
    pub(super)
    fn new(time: MODE) -> TimerResult<(Self, TimerDequeTicket)>
    { 
        time.validate_time(AbsoluteTime::now())?;

        let ext_ticket = TimerDequeTicket::new();

        let int_ticket = 
            Self
            {
                weak_status: 
                    ext_ticket.pair(),
                timeout_mode: 
                   time
            };


        return Ok((int_ticket, ext_ticket));
    }

    pub(super) 
    fn get_queue_id(&self) -> TimerResult<Arc<TimerDequeId>>
    {
        return 
            self
                .weak_status
                .upgrade()
                .ok_or(
                    map_timer_err!(TimerErrorType::TicketInstanceGone, "ticket is no longer valid")
                );
    }
}

impl<MODE> OrderedTimerDequeInterf<MODE> for TimerDequeTicketIssuer<MODE>
where 
    MODE: OrderedTimerDequeMode,
{
    #[inline]
    fn get_timeout_absolute(&self) -> AbsoluteTime 
    {
        return self.timeout_mode.get_absolut_timeout();
    }
}



impl<MODE> OrderedTimerDequeHandle<MODE> for TimerDequeTicketIssuer<MODE>
where 
    MODE: OrderedTimerDequeMode,
{
    /// Input item.
    type TimerId = TimerDequeId;

    type HandleRes = Vec<Self::TimerId>;

    fn handle(mut self, timer_self: &mut super::OrderTimerDeque<MODE, Self>, 
        timer_ids: &mut Self::HandleRes) -> TimerResult<()>
    {
        if let Some(target) = self.into_inner()
        {
            timer_ids.push(target);

            self.timeout_mode.advance_timeout();

            if MODE::IS_ONCE == false
            {
                return timer_self.queue_item(self);
            }
            else
            {
                return Ok(());
            }
        }

        return Ok(());
    }

    #[inline]
    fn is_same(&self, other: &Self::TimerId) -> bool 
    {
        return self.into_inner().as_ref() == Some(other);
    }

    #[inline]
    fn postpone(&mut self, postp_time: RelativeTime) -> TimerResult<()> 
    {
        let _ = self.get_queue_id()?;

        return self.timeout_mode.postpone(postp_time);
    }
    
    #[inline]
    fn resched(&mut self, time: MODE) -> TimerResult<()> 
    {
        let _ = self.get_queue_id()?;

        self.timeout_mode = time;

        return Ok(());
    }

    #[inline]
    fn into_timer_id(self) -> Option<Self::TimerId>
    {
        return self.into_inner();
    }
}

impl<MODE: OrderedTimerDequeMode> TimerDequeTicketIssuer<MODE>
{
    /// Checks if the instance is still actual i.e was not dropeed.
    fn is_valid(&self) -> bool
    {
        return self.weak_status.upgrade().is_some();
    }

    /// Obtains the [TimerDequeueId] only if the [Weak] pointer `weak_status`
    /// to ID is still actual.
    fn into_inner(&self) -> Option<TimerDequeId>
    {
        return self.weak_status.upgrade().map(|f| *f.as_ref());
    }
}