chore: initial sanitized public snapshot

This commit is contained in:
Aria2 Rust Pro Contributors
2026-07-18 14:16:57 +08:00
commit 17688c3e34
321 changed files with 76859 additions and 0 deletions
@@ -0,0 +1,391 @@
//! Compatibility wrappers that bridge BitTorrent, magnet, and Metalink models.
#![forbid(unsafe_code)]
use std::fmt::{Display, Formatter};
use crate::{
magnet::{MagnetUriModel, parse_magnet_uri},
metalink::{MetalinkDocumentModel, parse_metalink_document},
torrent::{TorrentMetadataModel, parse_torrent_metadata},
};
/// Declares how far a protocol family has progressed in the current implementation.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ProtocolSupportState {
/// The protocol is known but not yet wired into the workspace.
Planned,
/// Parsing and model registration exist, but transfer execution is pending.
Registered,
/// A compatibility skeleton is present and exposes the public API shape.
Skeleton,
}
/// Summarizes protocol readiness across BitTorrent-adjacent inputs.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ProtocolSupportMatrix {
/// Current state of `.torrent` metadata handling.
pub bit_torrent: ProtocolSupportState,
/// Current state of magnet URI handling.
pub magnet: ProtocolSupportState,
/// Current state of Metalink XML handling.
pub metalink: ProtocolSupportState,
}
/// Returns the current protocol support matrix exposed by this compatibility layer.
#[must_use]
pub const fn protocol_support_matrix() -> ProtocolSupportMatrix {
ProtocolSupportMatrix {
bit_torrent: ProtocolSupportState::Skeleton,
magnet: ProtocolSupportState::Registered,
metalink: ProtocolSupportState::Registered,
}
}
/// Compatibility wrapper for parsed magnet URI metadata.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MagnetUri {
/// Parsed BTIH info hash.
pub info_hash: String,
/// Optional display name from the `dn` query field.
pub display_name: Option<String>,
/// Ordered tracker URLs from `tr` query fields.
pub trackers: Vec<String>,
/// Ordered web-seed URLs from `ws` query fields.
pub web_seeds: Vec<String>,
}
/// Compatibility wrapper for parsed Metalink documents.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MetalinkDocument {
/// Root element name used for diagnostics.
pub root_element: String,
/// Parser state describing whether a real model was produced.
pub status: ParserStatus,
/// Parsed Metalink document model when parsing succeeded.
pub document: Option<MetalinkDocumentModel>,
}
/// Records whether a compatibility parser stayed stubbed or produced a model.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ParserStatus {
/// Parsing support is registered but no real model was built.
RegisteredStub,
/// Parsing produced a protocol-layer document model.
ParsedModel,
}
/// Errors raised while converting BitTorrent-adjacent formats into compatibility models.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum BtMetalinkError {
/// The magnet URI was malformed.
InvalidMagnet {
/// Parser-specific explanation of the magnet failure.
reason: String,
},
/// The requested torrent feature is not yet implemented.
UnsupportedTorrentBinary,
/// The Metalink document was malformed or unsupported.
InvalidMetalink {
/// Parser-specific explanation of the Metalink failure.
reason: String,
},
}
impl Display for BtMetalinkError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::InvalidMagnet { reason } => write!(f, "invalid magnet: {reason}"),
Self::UnsupportedTorrentBinary => {
f.write_str("torrent binary parsing is not implemented")
}
Self::InvalidMetalink { reason } => write!(f, "invalid metalink: {reason}"),
}
}
}
impl std::error::Error for BtMetalinkError {}
impl MagnetUri {
/// Builds the compatibility wrapper from the protocol-layer model.
#[must_use]
pub fn from_model(model: MagnetUriModel) -> Self {
Self {
info_hash: model.info_hash,
display_name: model.display_name,
trackers: model.trackers,
web_seeds: model.web_seeds,
}
}
/// Parses a magnet URI into the compatibility skeleton.
///
/// # Errors
///
/// Returns an error when the `magnet:?` prefix is missing or the URI does
/// not contain an `xt=urn:btih:<hash>` value.
pub fn parse(input: &str) -> Result<Self, BtMetalinkError> {
parse_magnet_uri(input).map(Self::from_model)
}
}
impl MetalinkDocument {
/// Builds the compatibility wrapper from the protocol-layer Metalink model.
#[must_use]
pub fn from_model(model: MetalinkDocumentModel) -> Self {
Self {
root_element: "metalink".to_owned(),
status: ParserStatus::ParsedModel,
document: Some(model),
}
}
/// Parses Metalink XML text through the protocol-layer Metalink parser.
///
/// # Errors
///
/// Returns an error when the input is not a valid Metalink document or
/// when the document has no actionable resources.
pub fn parse(input: &str) -> Result<Self, BtMetalinkError> {
let document = parse_metalink_document(input)
.map_err(|reason| BtMetalinkError::InvalidMetalink { reason })?;
Ok(Self {
root_element: "metalink".to_owned(),
status: ParserStatus::ParsedModel,
document: Some(document),
})
}
}
/// Compatibility wrapper for parsed torrent metadata.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TorrentMetadata {
/// Parsed torrent metadata model.
pub model: TorrentMetadataModel,
}
/// Errors raised while parsing `.torrent` metadata.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum TorrentMetadataError {
/// The torrent payload was syntactically invalid.
Invalid {
/// Parser-specific explanation of the torrent failure.
reason: String,
},
/// The payload used an unsupported feature.
Unsupported {
/// Name of the unsupported torrent feature.
feature: &'static str,
},
}
impl Display for TorrentMetadataError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::Invalid { reason } => write!(f, "invalid torrent metadata: {reason}"),
Self::Unsupported { feature } => write!(f, "{feature} is not implemented"),
}
}
}
impl std::error::Error for TorrentMetadataError {}
impl TorrentMetadata {
/// Wraps a protocol-layer torrent model.
#[must_use]
pub fn from_model(model: TorrentMetadataModel) -> Self {
Self { model }
}
/// Returns a shared reference to the underlying torrent metadata model.
#[must_use]
pub fn as_model(&self) -> &TorrentMetadataModel {
&self.model
}
/// Consumes the wrapper and returns the underlying torrent metadata model.
#[must_use]
pub fn into_model(self) -> TorrentMetadataModel {
self.model
}
/// Parses torrent binary metadata through the shared protocol-layer parser.
///
/// # Errors
///
/// Returns a structured invalid-metadata error when the payload cannot be parsed.
pub fn parse(input: &[u8]) -> Result<Self, TorrentMetadataError> {
parse_torrent_metadata(input)
.map(Self::from_model)
.map_err(|error| TorrentMetadataError::Invalid { reason: error })
}
}
#[cfg(test)]
mod tests {
use super::{
MagnetUri, MetalinkDocument, ParserStatus, TorrentMetadata, TorrentMetadataError,
parse_magnet_uri,
};
use crate::{
TorrentFileEntryModel, TorrentInfoModel, TorrentMetadataModel, TorrentPeerModel,
TorrentTrackerModel,
};
#[test]
fn magnet_wrapper_parse_matches_magnet_model_fields() {
let input = "magnet:?xt=urn:btih:0123456789abcdef&dn=Ubuntu%2024.04&tr=http%3A%2F%2Ftracker.example.org%2Fannounce&ws=https%3A%2F%2Fcdn.example.org%2Fubuntu.iso";
let parsed = MagnetUri::parse(input).expect("magnet wrapper should parse");
let model = parse_magnet_uri(input).expect("protocol magnet parser should parse");
assert_eq!(parsed.info_hash, model.info_hash);
assert_eq!(parsed.display_name, model.display_name);
assert_eq!(parsed.trackers, model.trackers);
assert_eq!(parsed.web_seeds, model.web_seeds);
}
#[test]
fn torrent_wrapper_round_trips_model_without_changing_shape() {
let model = TorrentMetadataModel {
info: TorrentInfoModel {
name: "sample".to_owned(),
piece_length: 16,
pieces: vec![[0_u8; 20]],
files: vec![TorrentFileEntryModel {
path: "sample.bin".to_owned(),
length: 16,
piece_offset: Some(0),
selected: true,
}],
hash: None,
private: false,
},
announce: Some("http://tracker.example.org/announce".to_owned()),
trackers: vec![TorrentTrackerModel {
url: "http://tracker.example.org/announce".to_owned(),
tier: Some(1),
id: None,
seeders: None,
leechers: None,
}],
peers: vec![TorrentPeerModel {
peer_id: None,
ip: "127.0.0.1".to_owned(),
port: 6881,
client_name: None,
interested: false,
choked: true,
}],
dht_nodes: vec!["router.example.org:6881".to_owned()],
pieces: Vec::new(),
creation_date: None,
comment: None,
};
let wrapper = TorrentMetadata::from_model(model.clone());
assert_eq!(wrapper.as_model(), &model);
assert_eq!(wrapper.into_model(), model);
}
#[test]
fn torrent_wrapper_surfaces_parse_errors_as_invalid_metadata() {
let error = TorrentMetadata::parse(b"not-a-torrent").expect_err("bad torrent should fail");
match error {
TorrentMetadataError::Invalid { reason } => assert!(!reason.is_empty()),
TorrentMetadataError::Unsupported { feature } => {
panic!("unexpected torrent error variant: unsupported feature {feature}")
}
}
}
#[test]
fn metalink_wrapper_parse_returns_real_parsed_model() {
let parsed = MetalinkDocument::parse(
r#"<?xml version="1.0" encoding="utf-8"?>
<metalink version="4.0" xmlns="urn:ietf:params:xml:ns:metalink">
<identity>wrapped fixture</identity>
<file name="wrapped.iso">
<description>real parser payload</description>
<url priority="1" location="us">https://mirror.example.com/wrapped.iso</url>
</file>
</metalink>"#,
)
.expect("metalink wrapper should parse through the real model");
assert_eq!(parsed.root_element, "metalink");
assert_eq!(parsed.status, ParserStatus::ParsedModel);
let document = parsed
.document
.expect("wrapper should retain parsed document");
assert_eq!(document.version.as_deref(), Some("4.0"));
assert_eq!(document.identity.as_deref(), Some("wrapped fixture"));
assert_eq!(document.files.len(), 1);
assert_eq!(document.files[0].name, "wrapped.iso");
assert_eq!(
document.files[0].description.as_deref(),
Some("real parser payload")
);
assert_eq!(
document.files[0].resources[0].url,
"https://mirror.example.com/wrapped.iso"
);
}
#[test]
fn metalink_wrapper_preserves_normalized_file_metadata_and_resource_hints() {
let parsed = MetalinkDocument::parse(
r#"<?xml version="1.0" encoding="utf-8"?>
<metalink version="4.0" xmlns="urn:ietf:params:xml:ns:metalink">
<identity>wrapper fixture</identity>
<file name=" wrapped.iso ">
<identity> release-42 </identity>
<signature><![CDATA[SIG-WRAP]]></signature>
<hash type="SHA256"> AA BB </hash>
<url location=" us " maxconnections="8">https://mirror.example.com/wrapped.iso</url>
</file>
</metalink>"#,
)
.expect("metalink wrapper should preserve normalized parser output");
let document = parsed
.document
.expect("wrapper should retain parsed document");
assert_eq!(document.identity.as_deref(), Some("wrapper fixture"));
assert_eq!(document.files[0].name, "wrapped.iso");
assert_eq!(document.files[0].identifier.as_deref(), Some("release-42"));
assert_eq!(document.files[0].signatures, vec!["SIG-WRAP".to_owned()]);
assert_eq!(document.files[0].checksums[0].algorithm, "sha-256");
assert_eq!(document.files[0].checksums[0].value, "aabb");
assert_eq!(
document.files[0].resources[0].location.as_deref(),
Some("us")
);
assert_eq!(document.files[0].resources[0].max_connections, Some(8));
assert_eq!(
document.files[0].resources[0].type_hint.as_deref(),
Some("https")
);
}
#[test]
fn metalink_wrapper_parse_rejects_invalid_root_only_stub_shape() {
let error = MetalinkDocument::parse(
r#"<?xml version="1.0" encoding="utf-8"?>
<metalink version="4.0" xmlns="urn:ietf:params:xml:ns:metalink">
<file name="empty.iso">
<url priority="1"> </url>
</file>
</metalink>"#,
)
.expect_err("root-only stub success should be rejected");
assert!(
error
.to_string()
.contains("metalink document contains no resource urls"),
"unexpected error: {error}"
);
}
}