use std::fmt::{Display, Formatter}; use crate::piece::PieceId; /// Stable identifier for a download group. #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct DownloadId(u64); impl DownloadId { /// Wraps the raw numeric identifier used internally and on the RPC surface. #[must_use] pub const fn new(raw: u64) -> Self { Self(raw) } /// Returns the raw numeric identifier. #[must_use] pub const fn as_u64(self) -> u64 { self.0 } /// Parses the hexadecimal GID representation used by aria2 RPC clients. #[must_use] pub fn parse_hex(raw: &str) -> Option { u64::from_str_radix(raw, 16).ok().map(Self) } } impl Display for DownloadId { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{:016x}", self.0) } } /// User-visible lifecycle state for a download group. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum DownloadStatus { /// The group is actively transferring data. Active, /// The group is queued and waiting to start. Waiting, /// The group is paused by user or scheduler action. Paused, /// The group stopped because the last attempt failed. Error, /// The group finished successfully. Complete, /// The group was removed from runtime state. Removed, } impl DownloadStatus { /// Returns the lowercase RPC status token expected by aria2-compatible clients. #[must_use] pub const fn as_rpc_status(&self) -> &'static str { match self { Self::Active => "active", Self::Waiting => "waiting", Self::Paused => "paused", Self::Error => "error", Self::Complete => "complete", Self::Removed => "removed", } } } /// Captures one retry decision for a request or segment. #[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct RetryAttempt { /// Retry attempt ordinal, starting at one for the first retry. pub attempt: u32, /// Byte offset at which the retry resumes. pub offset: u64, /// Optional retry length when the retry only covers one segment. pub length: Option, /// Human-readable error that triggered the retry. pub error: Option, /// Whether the error is considered recoverable by the scheduler. pub recoverable: bool, } impl RetryAttempt { /// Builds a recoverable retry record for the provided attempt number and offset. #[must_use] pub const fn new(attempt: u32, offset: u64) -> Self { Self { attempt, offset, length: None, error: None, recoverable: true, } } } /// Resume metadata recovered from persisted session state. #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] pub struct ResumeState { /// Whether this resume snapshot came from persisted storage. pub persisted: bool, /// Byte offset from which the resumed transfer should continue. pub resume_offset: u64, /// Verified payload length recovered from prior state, if known. pub validated_length: Option, /// Optional piece cursor used to continue segmented scheduling. pub segment_cursor: Option, }