108 lines
3.2 KiB
Rust
108 lines
3.2 KiB
Rust
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<Self> {
|
|
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<u64>,
|
|
/// Human-readable error that triggered the retry.
|
|
pub error: Option<String>,
|
|
/// 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<u64>,
|
|
/// Optional piece cursor used to continue segmented scheduling.
|
|
pub segment_cursor: Option<PieceId>,
|
|
}
|