chore: initial sanitized public snapshot

This commit is contained in:
Aria2 Rust Pro Contributors
2026-07-18 14:04:26 +08:00
commit 7b3816441c
320 changed files with 76813 additions and 0 deletions
@@ -0,0 +1,222 @@
#![doc(hidden)]
#![expect(
clippy::needless_pass_by_value,
clippy::redundant_pub_crate,
reason = "this private runtime-planning module shares parent-only planning structs and helpers across the split CLI runtime"
)]
use std::path::PathBuf;
use aria2_rust_pro_compat::{ConfigParseError, ConfigProfile};
use aria2_rust_pro_core::RuntimeConfig;
use aria2_rust_pro_protocol::{Downloader, HttpSessionModel, Protocol};
use super::{
CliError, CliTransferSource, ConfigLoadReport, DispatcherRegistrationKind,
InProcessRpcDispatcher, StartupProfile, TransferInputEntry, TransferSelection,
classify_transfer, derive_http_session, derive_runtime_config, expand_transfer_entries,
load_config_report, merged_profile, parse_protocol, register_resolved_entry_with_dispatcher,
resolve_transfer_entry_with_downloader,
};
#[derive(Clone, Debug)]
pub(super) struct RuntimeInputContext {
pub(super) config_report: Option<ConfigLoadReport>,
pub(super) effective_profile: Option<ConfigProfile>,
pub(super) recognized_schemes: Vec<String>,
pub(super) transfer_kinds: Vec<TransferSelection>,
pub(super) derived_runtime: RuntimeConfig,
pub(super) http_session: HttpSessionModel,
pub(super) resolved_entries: Vec<ResolvedRuntimeEntry>,
}
#[derive(Clone, Debug)]
pub(super) struct ResolvedRuntimeEntry {
pub(super) entry: TransferInputEntry,
pub(super) entry_profile: Option<ConfigProfile>,
pub(super) runtime: RuntimeConfig,
pub(super) http_session: HttpSessionModel,
pub(super) uri: String,
}
#[derive(Clone, Debug)]
pub(super) struct RegisteredRuntimeEntry {
pub(super) resolved: ResolvedRuntimeEntry,
pub(super) gid: String,
pub(super) registration_kind: DispatcherRegistrationKind,
}
#[derive(Clone, Debug)]
struct DerivedEntryContext {
runtime: RuntimeConfig,
http_session: HttpSessionModel,
}
pub(super) fn build_runtime_input_context<D: Downloader + Sync>(
config_path: Option<PathBuf>,
uris: Vec<String>,
startup: &StartupProfile,
cli_profile: Option<&ConfigProfile>,
cli_transfer_sources: Option<&[CliTransferSource]>,
downloader: &D,
) -> Result<RuntimeInputContext, CliError> {
let config_report = config_path
.as_ref()
.map(|path| load_config_report(path, true))
.transpose()?;
let file_profile = config_report.as_ref().map(|report| &report.profile);
let effective_profile = merged_profile(file_profile, cli_profile);
let profile = effective_profile.as_ref();
let input_entries = expand_transfer_entries(&uris, profile, cli_transfer_sources)?;
let first_entry_profile = input_entries.first().and_then(|entry| {
let implied = merged_profile(entry.implied_profile.as_ref(), profile);
merged_profile(implied.as_ref(), entry.profile.as_ref())
});
let report_profile = first_entry_profile.as_ref().or(profile);
let derived_runtime = derive_runtime_config(report_profile, startup);
let http_session = derive_http_session(report_profile, startup);
let recognized_schemes = input_entries
.iter()
.filter_map(|entry| entry.uris.first())
.filter_map(|uri| parse_protocol(uri).map(Protocol::as_str))
.map(str::to_owned)
.collect::<Vec<_>>();
let transfer_kinds = input_entries
.iter()
.filter_map(|entry| entry.uris.first())
.map(String::as_str)
.map(classify_transfer)
.collect::<Vec<_>>();
let resolved_entries = resolve_runtime_entries(&input_entries, startup, profile, downloader)?;
Ok(RuntimeInputContext {
config_report,
effective_profile,
recognized_schemes,
transfer_kinds,
derived_runtime,
http_session,
resolved_entries,
})
}
pub(super) fn register_runtime_entries<D: Downloader + Sync>(
dispatcher: &mut InProcessRpcDispatcher,
downloader: &D,
entries: Vec<ResolvedRuntimeEntry>,
base_profile: Option<&ConfigProfile>,
) -> Result<Vec<RegisteredRuntimeEntry>, CliError> {
let mut registered_entries = Vec::with_capacity(entries.len());
for resolved in entries {
let (gid, registration_kind) = register_resolved_entry_with_dispatcher(
dispatcher,
downloader,
&resolved.entry,
&resolved.uri,
resolved.entry_profile.as_ref().or(base_profile),
&resolved.http_session,
&resolved.runtime,
)?;
registered_entries.push(RegisteredRuntimeEntry {
resolved,
gid,
registration_kind,
});
}
Ok(registered_entries)
}
fn resolve_runtime_entries<D: Downloader + Sync>(
input_entries: &[TransferInputEntry],
startup: &StartupProfile,
profile: Option<&ConfigProfile>,
downloader: &D,
) -> Result<Vec<ResolvedRuntimeEntry>, CliError> {
let mut resolved_entries = Vec::new();
let mut derived_context_cache = Vec::new();
for entry in input_entries {
let direct_passthrough = entry
.uris
.first()
.is_some_and(|uri| classify_transfer(uri) != TransferSelection::Metalink);
let pre_resolve_profile = merged_profile(
merged_profile(entry.implied_profile.as_ref(), profile).as_ref(),
entry.profile.as_ref(),
);
let pre_resolve_context = derived_entry_context(
&mut derived_context_cache,
pre_resolve_profile.as_ref(),
startup,
);
let expanded_entries = resolve_transfer_entry_with_downloader(
entry,
downloader,
&pre_resolve_context.http_session,
&pre_resolve_context.runtime,
)?;
if direct_passthrough && expanded_entries.len() == 1 {
let resolved_uri = entry.uris.first().cloned().ok_or_else(|| {
CliError::Config(ConfigParseError::InvalidDirective(
"input-file entry missing URI".to_owned(),
))
})?;
let expanded_entry = expanded_entries
.into_iter()
.next()
.expect("direct entry fast path should preserve one resolved entry");
resolved_entries.push(ResolvedRuntimeEntry {
entry: expanded_entry,
entry_profile: pre_resolve_profile,
runtime: pre_resolve_context.runtime,
http_session: pre_resolve_context.http_session,
uri: resolved_uri,
});
continue;
}
for expanded_entry in expanded_entries {
let entry_profile = merged_profile(
merged_profile(expanded_entry.implied_profile.as_ref(), profile).as_ref(),
expanded_entry.profile.as_ref(),
);
let entry_context =
derived_entry_context(&mut derived_context_cache, entry_profile.as_ref(), startup);
let resolved_uri = expanded_entry.uris.first().cloned().ok_or_else(|| {
CliError::Config(ConfigParseError::InvalidDirective(
"input-file entry missing URI".to_owned(),
))
})?;
resolved_entries.push(ResolvedRuntimeEntry {
entry: expanded_entry,
entry_profile,
runtime: entry_context.runtime,
http_session: entry_context.http_session,
uri: resolved_uri,
});
}
}
Ok(resolved_entries)
}
fn derived_entry_context(
cache: &mut Vec<(Option<ConfigProfile>, DerivedEntryContext)>,
profile: Option<&ConfigProfile>,
startup: &StartupProfile,
) -> DerivedEntryContext {
if let Some((_, cached)) = cache
.iter()
.find(|(cached_profile, _)| cached_profile.as_ref() == profile)
{
return cached.clone();
}
let derived = DerivedEntryContext {
runtime: derive_runtime_config(profile, startup),
http_session: derive_http_session(profile, startup),
};
cache.push((profile.cloned(), derived.clone()));
derived
}