125 lines
4.0 KiB
Rust
125 lines
4.0 KiB
Rust
use std::{fmt, io};
|
|
|
|
use crate::{
|
|
checksum::Checksum,
|
|
model::{DownloadFile, PieceIndex, PieceState},
|
|
};
|
|
|
|
/// Version tag for the simplified control-file format.
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
pub struct ControlFileVersion {
|
|
/// Major version component.
|
|
major: u16,
|
|
/// Minor version component.
|
|
minor: u16,
|
|
}
|
|
|
|
impl ControlFileVersion {
|
|
/// Current text-first control-file version.
|
|
pub const CURRENT: Self = Self { major: 1, minor: 0 };
|
|
/// Binary-compatible control-file version.
|
|
pub const BINARY_V1: Self = Self { major: 1, minor: 1 };
|
|
|
|
/// Builds a version value from explicit major/minor parts.
|
|
#[must_use]
|
|
pub(crate) const fn from_parts(major: u16, minor: u16) -> Self {
|
|
Self { major, minor }
|
|
}
|
|
|
|
/// Returns the major version component.
|
|
#[must_use]
|
|
pub const fn major(self) -> u16 {
|
|
self.major
|
|
}
|
|
|
|
/// Returns the minor version component.
|
|
#[must_use]
|
|
pub const fn minor(self) -> u16 {
|
|
self.minor
|
|
}
|
|
}
|
|
|
|
/// Normalized control metadata stored by the Rust implementation.
|
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
pub struct ControlMetadata {
|
|
/// Version of the serialized control-file format.
|
|
pub version: ControlFileVersion,
|
|
/// Files tracked by the control metadata.
|
|
pub files: Vec<DownloadFile>,
|
|
/// Whole-download or file-level checksums.
|
|
pub checksums: Vec<Checksum>,
|
|
/// Non-default piece states captured by the downloader.
|
|
pub piece_states: Vec<(PieceIndex, PieceState)>,
|
|
/// Number of completed bytes known at serialization time.
|
|
pub completed_length: u64,
|
|
/// Number of retry attempts already consumed.
|
|
pub retry_count: u32,
|
|
/// Last runtime error, if one was recorded.
|
|
pub last_error: Option<String>,
|
|
/// Timestamp for the last runtime error in Unix milliseconds.
|
|
pub last_error_at_unix_ms: Option<u64>,
|
|
/// Timestamp for the last retry attempt in Unix milliseconds.
|
|
pub last_retry_at_unix_ms: Option<u64>,
|
|
/// Timestamp for the next scheduled retry in Unix milliseconds.
|
|
pub next_retry_at_unix_ms: Option<u64>,
|
|
/// Number of consecutive transfer failures, when tracked.
|
|
pub consecutive_failure_count: Option<u32>,
|
|
/// Number of active download segments, when tracked.
|
|
pub active_segment_count: Option<u32>,
|
|
/// Timestamp when resume verification last completed.
|
|
pub resume_verified_at_unix_ms: Option<u64>,
|
|
/// Resume-generation counter used to correlate session state.
|
|
pub resume_generation: Option<u64>,
|
|
}
|
|
|
|
/// Text control-file representation preserved for diagnostics.
|
|
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
|
pub struct ControlFileTextModel {
|
|
/// Raw control-file lines.
|
|
pub lines: Vec<String>,
|
|
}
|
|
|
|
/// Binary control-file representation preserved for diagnostics.
|
|
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
|
pub struct ControlFileBinaryModel {
|
|
/// Four-byte binary magic value.
|
|
pub magic: [u8; 4],
|
|
/// Encoded major version component.
|
|
pub version_major: u16,
|
|
/// Encoded minor version component.
|
|
pub version_minor: u16,
|
|
/// Binary payload after the header.
|
|
pub payload: Vec<u8>,
|
|
}
|
|
|
|
/// Errors that can occur while reading or writing control files.
|
|
#[derive(Debug)]
|
|
pub enum ControlFileError {
|
|
/// Underlying filesystem I/O error.
|
|
Io(io::Error),
|
|
/// Malformed or unsupported control-file contents.
|
|
Parse(String),
|
|
/// Upstream binary format variant is unsupported.
|
|
UnsupportedBinaryCompatibility,
|
|
}
|
|
|
|
impl fmt::Display for ControlFileError {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
Self::Io(error) => write!(f, "io error: {error}"),
|
|
Self::Parse(message) => write!(f, "parse error: {message}"),
|
|
Self::UnsupportedBinaryCompatibility => {
|
|
write!(f, "unsupported binary .aria2 control-file format")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::error::Error for ControlFileError {}
|
|
|
|
impl From<io::Error> for ControlFileError {
|
|
fn from(value: io::Error) -> Self {
|
|
Self::Io(value)
|
|
}
|
|
}
|