timer-deque-rs 0.7.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::{fmt, io::ErrorKind};

use nix::errno::Errno;


#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TimerErrorType
{
    /// The procvided time has expired before setting
    Expired,

    /// Error in timer subsystem
    TimerError(Errno),

    /// Performing oprtation on empty queue.
    QueueEmpty,

    /// Epoll returned error [Errno].
    EPoll(Errno),

    EventFd(Errno),

    /// Already polling
    EPollAlreadyPolling,

    /// Can not convert time.
    Conversion,

    /// Some error which came from other crate.
    ExternalError,

    /// Duplicate record.
    Duplicate,

    /// Already polled
    AlreadyPolled,

    /// Item not found
    NotFound,

    /// Ticket got invalid
    TicketInstanceGone,

    /// Item belong to other instance
    BelongOtherInstance,

    /// MPSC channel disconnected.
    ChannelDisconnected,

    /// Thread poisoned
    Poisoned,

    SpawnError(ErrorKind),

    ReferenceGone,

    MpscTimeout,

    ZeroRelativeTime,
}

impl fmt::Display for TimerErrorType
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
    {
        match self
        {
            Self::Expired => 
                write!(f, "absolute time has expired"),
            Self::TimerError(e) => 
                write!(f, "timer setup error: {}", e.desc()),
            Self::QueueEmpty => 
                write!(f, "the queue is empty"),
            Self::EPoll(errno) => 
                write!(f, "epoll() error: {}", errno.desc()),
            Self::EventFd(errno) => 
                write!(f, "eventfd() error: {}", errno.desc()),
            Self::EPollAlreadyPolling =>
                write!(f, "other thread already polling"),
            Self::Conversion => 
                write!(f, "cannot convert time"),
            Self::ExternalError => 
                write!(f, "external error"),
            Self::Duplicate => 
                write!(f, "duplicate"),
            Self::AlreadyPolled =>
                write!(f, "instance is already on watch"),
            Self::NotFound => 
                write!(f, "not found"),
            Self::TicketInstanceGone => 
                write!(f, "ticket dropped"),
            Self::BelongOtherInstance =>
                write!(f, "item belongs to other instance"),
            Self::ChannelDisconnected => 
                write!(f, "MPSC sender has disconnected from receiver"),
            Self::Poisoned =>
                write!(f, "mutex poisoned"),
            Self::SpawnError(e) =>
                write!(f, "thread spawn error: {}", e),
            Self::ReferenceGone =>
                write!(f, "Weak reference gone"),
            Self::MpscTimeout => 
                write!(f, "MPSC timeout"),
            Self::ZeroRelativeTime => 
                write!(f, "The relative time for offset is zero.")
        }
    }
}

/// Error storage.
#[derive(Debug, Clone)]
pub struct TimerError
{
    /// Error code.
    reason: TimerErrorType,

    /// Error descrition.
    msg: String
}

impl Eq for TimerError {}

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

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

impl TimerError
{
    pub 
    fn new(reason: TimerErrorType, msg: String) -> Self
    {
        return Self{ reason, msg };
    }

    pub 
    fn get_error_type(&self) -> TimerErrorType
    {
        return self.reason;
    }

    pub 
    fn get_error_msg(&self) -> &str
    {
        return &self.msg;
    }
}

/// Alias for the [Result] used by timer queues.
pub type TimerResult<R> = Result<R, TimerError>;

#[macro_export]
macro_rules! timer_err
{
    ($reason:expr,$($arg:tt)*) => (
        return std::result::Result::Err( $crate::error::TimerError::new($reason, format!($($arg)*)) )
    )
}

#[macro_export]
macro_rules! map_timer_err
{
    ($reason:expr, $($arg:tt)*) => (
        $crate::error::TimerError::new($reason, format!($($arg)*))
    )
}